Files
greeneclipse 8580c996c3 Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
2026-08-09 22:47:43 +02:00

10 KiB
Raw Permalink Blame History

01 — Support desk + admin AI inventory (auto-reply / AI assist)

Agent: 1/10 · Mode: read-only inventory
Tools: codehelper project_contextkickoffquery/investigate; Read/Grep/Shell fallback (read_workspace_file / write_workspace_file unavailable in focused MCP profile)
Related: docs/admin-roles-support/*, docs/plan-permissions/01-feature-keys.json


Executive summary

Support desk is shipped: customer tickets + CSAT, staff queue/claim with support_staff, platform admin aggregate CSAT, agents directory. Platform AI already has a dedicated support role slot (provider / base_url / model / encrypted key) editable at /admin/settings → AI roles. LLM ticket auto-reply is an intentional safe stub (TryAutoReplyLLM → always ErrAIAutoReplyDisabled); Create / ReplyAsUser / ReplyAsAgent must not call Completers. No FAQ/canned/rule-based ticket auto-response exists yet (docs Ask is a separate rule tree and must not use AIRoleSupport).


1. Support desk — current surface

1.1 Schema

Migration Purpose
025_support_center.sql support_tickets, support_messages, support_notifications
027_capabilities_support_perf.sql assignee / activity indexes
029_staff_roles.sql users.staff_roleadmin|developer|support_staff
030_support_desk.sql resolved_by_user_id, CSAT table + token cols, unassigned index, ticket_claimed / csat_requested kinds

Ticket enums: status open|pending|resolved|closed; category billing|bug|account|other; priority low|normal|high.
Message author_role: user|agent|system (authorship, not staff RBAC).
CSAT: support_csat_ratings — one rating per ticket (score 15 + comment). Public token columns exist but are not wired.

1.2 Domain packages

Path Role
apps/api/internal/support/types.go Ticket, Message, CSAT*, CreateInput, ReplyInput, list scopes
apps/api/internal/support/tickets.go Create, Get/GetAdmin, ReplyAsUser, ReplyAsAgent, UpdateAdmin, listMessages
apps/api/internal/support/desk.go scopes, Claim/Release, GetAdminForActor
apps/api/internal/support/agents.go agents directory via staff_role
apps/api/internal/support/ratings.go SubmitCSAT, AggregateCSAT, attachCSAT
apps/api/internal/support/ai_auto_reply.go TryAutoReplyLLM stub (sole LLM gate)
apps/api/internal/support/errors.go ErrAIAutoReplyDisabled

1.3 HTTP API

Customer (RequireSession + RequireCompany) — server.go ~494501:

Method Path
GET/POST /api/support/tickets
GET /api/support/tickets/{id}
POST /api/support/tickets/{id}/messages
POST /api/support/tickets/{id}/csat
GET/POST /api/support/notifications (+ read / read-all)

Staff desk (RequireSupportDesk) — ~304313:

Method Path
GET /api/admin/support/tickets (scope=inbox|mine|unassigned|all)
GET/PATCH /api/admin/support/tickets/{id}
POST …/messages, …/claim, …/release
GET /api/admin/support/agents

Platform admin only — ~316332:

Method Path
GET /api/admin/support/csat?from=&to=
PUT /api/admin/support/agents/{id}
GET/PUT /api/admin/settings (includes ai_roles)
PATCH /api/admin/users/{id}/staff-role

Contract design: docs/admin-roles-support/11-support-api-contract.json · backend notes: 12-support-backend.md · CSAT: 13-support-ratings.md.

1.4 Staff access

Symbol Path Behavior
ResolveStaffAccess apps/api/internal/auth/staff.go support_staff → desk only; admin/developer/legacy platform admin → full
RequireSupportDesk httpapi/middleware.go desk routes
RequirePlatformAdmin same excludes support_staff from billing/settings/users
requireSupportDesk / requirePlatformAdmin apps/web/src/lib/admin-gate.ts UI gates

Visibility: queue + claim (inbox/mine/unassigned; all = full admin). Cross-assignee GET → 404; reply on anothers claim → 409.

1.5 Web UI

Persona Routes Client
Customer /support, /support/new, /support/[ticketId] $lib/support/api.ts, CSAT via SupportTicketRating.svelte
Staff /admin/support, /admin/support/[id] $lib/support/admin-api.ts
Role grant /admin/users PATCH …/staff-role
AI keys /admin/settings tab AI roles $lib/admin-ai-roles.ts

Docs: 14-support-staff-ui.md, 15-user-support-ui.md.

1.6 Plan-permission keys (tenant Support Center)

From docs/plan-permissions/01-feature-keys.json / plan-feature-catalog.ts — section support, defaults ON all public plans:

Key Route
support.center /support
support.ticket_create /support/new
support.ticket_thread /support/[ticketId]
shell.support_notifications notification bell

No plan keys for staff desk, AI auto-reply, or CSAT (CSAT rides on thread eligibility).


2. Admin AI configuration (platform)

2.1 Role catalog

Stored in platform settings JSON (company_settings / SystemCompanyID) — not a dedicated SQL table.

Role key Constant Purpose today
processing AIRoleProcessing / RoleProcessing Product pipeline chat; falls back to legacy openai + env
vectorization AIRoleVectorization Embeddings; env fallback
docs_api AIRoleDocsAPI Config slot only — /docs Ask must not use it
support AIRoleSupport / RoleSupport Ticket-assist slot — configure only; auto-reply gated by stub

Fields per role: provider, base_url, model, encrypted api_key, enabled, optional extras. Secrets masked on GET (api_key_last4 / masked).

2.2 Existing AI admin settings paths

Layer Path / symbol
UI apps/web/src/routes/admin/settings/+page.svelte — tabs Overview / AI roles / Mail / Other / Admin Users
Client load/save apps/web/src/lib/admin-platform-settings.ts — `GET
Client AI roles apps/web/src/lib/admin-ai-roles.tsAI_ROLES, saveAIRoles, extractAIRoles, testAIRole
API handlers apps/api/internal/httpapi/admin_settings_handlers.gohandleGetAdminSettings / handlePutAdminSettings
Storage / resolve apps/api/internal/platformsettings/ai_configs.go (publicAIConfigs, patchAIConfigs, ResolveAIConfig), types.go (AIRoles, AIRoleSupport)
Runtime completer apps/api/internal/aiprovider/roles.goResolveCompleterForRole (supports RoleSupport when configured)
Tenant BYOK test (not platform roles) POST /api/…/integrations/ai/testhandleTestAIIntegration
Optional role probe Client expects POST /api/admin/settings/ai-roles/{role}/testnot mounted; testAIRole treats 404/501 as skipped

ASSUMPTION: Enabling LLM ticket assist should use ResolveCompleterForRole(..., RoleSupport) (or ResolveAIConfig(AIRoleSupport)) only inside/behind TryAutoReplyLLM, never from Create/Reply handlers directly.

2.3 Docs Ask (non-ticket, rule-based)

DocsAskGuide.svelte + $lib/docs-guide — decision tree only. Explicitly must never call AIRoleDocsAPI or AIRoleSupport. Useful pattern for content-based auto-response before LLM fallback — not wired to tickets.


3. Auto-reply / AI assist — current state

Capability Status
Admin config slot ai_roles.support Exists (UI + API + tests)
aiprovider.ResolveCompleterForRole(RoleSupport) Resolves when slot configured
support.TryAutoReplyLLM Stub refuses (ErrAIAutoReplyDisabled)
Call sites from Create / Reply* Forbidden by comments; Create documents “do not call”
FAQ / keyword / canned auto-reply Absent
Draft-assist UI for agents Absent
Job/queue for async auto-reply Absent
Plan/feature flag for auto-reply Absent
author_role=system messages Schema allows; no auto-writer

Test lock: ai_auto_reply_test.goTestTryAutoReplyLLM_refuses.


4. Gaps (richer detail / auto-response / AI fallback)

4.1 Richer ticket detail

  • Staff admin-api.ts SupportTicket omits csat, csat_eligible, resolved_by_user_id — API can attach CSAT on GetAdmin but admin UI/types ignore it.
  • No admin CSAT aggregate UI for GET /api/admin/support/csat.
  • No attachments, linked product/feed IDs, or structured metadata on tickets/messages.
  • No SLA timers, tags, macros, or customer org context beyond company name + requester email.
  • Public CSAT token invite flow (csat_token_hash) unused.
  • Message list is plain body text only (no markdown/HTML sanitization layer called out for AI drafts).

4.2 Auto-response from question content

  • No classifier on CreateInput.subject / body or category.
  • No canned/FAQ store or docs-guide-like tree for tickets.
  • No author_role=system first-response after create.
  • Create commits then returns — no post-commit hook for auto-reply (natural extension: after successful Create / ReplyAsUser, call a non-LLM matcher then optionally TryAutoReplyLLM).

4.3 AI fallback when auto fails

  • Intended entry: implement TryAutoReplyLLM using AIRoleSupport completer; today always fails closed.
  • No confidence threshold, human-handoff status (pending), or “AI attempted” audit fields.
  • No product enable flag separate from ai_roles.support.enabled (comments require an explicit gate).
  • Docs Ask must remain separate — do not reuse docs_api for ticket LLM.

5. Prior inventory note

docs/admin-roles-support/02-current-inventory.md is stale relative to shipped staff roles + CSAT (preagents 6/12/13/14). Prefer 1215 + this doc for current support/AI state.


6. Sources (codehelper + docs)

  • Investigate: TryAutoReplyLLM, publicAIConfigs, GetAdmin
  • Query: support tickets/CSAT, admin AI settings, plan support keys
  • Docs: admin-roles-support/1115, plan-permissions/01-feature-keys.json, 06-defaults-matrix