Files
descrybe/docs/support-auto/08-staff-auto-ai-ui.md
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

3.9 KiB

08 — Staff auto / AI assist UI

Agent: 8/10 · Status: Implemented
Coordinates with: 02-contract (fields), 05-ticket-detail (schema + PATCH), 03/04 (match + AI drafts), 14-support-staff-ui (desk shell)


PROBLEM

Staff need to see auto-match / AI assist outcomes on a ticket, approve or edit draft_only AI drafts, disable further auto per ticket, and filter the queue for needs_human / ai_draft — without elevating support_staff beyond the existing desk gate.


WHAT SHIPPED

Access (least privilege preserved)

Actor Surfaces
support_staff /admin/support/** only via requireSupportDesk / RequireSupportDesk
Full admin Same desk + assign picker (unchanged)
  • New endpoints mount under the same RequireSupportDesk group as claim/reply.
  • Approve/discard/get still call staffMayAccessTicket (support_staff: own claim or unassigned open/pending; cross-assignee → 404 / 409).
  • No KB/settings/billing routes exposed to support_staff.

Queue (/admin/support)

  • Filter chips: Any auto state · Needs human · AI draft (?flag=).
  • Persisted in URL with existing scope / status.
  • Auto column: status badge or “Auto off”.
  • API: GET /api/admin/support/tickets?flag=needs_human|ai_draft
    • ai_draftauto_reply_status = ai_draft
    • needs_humanhanded_off|failed|skipped

Ticket detail (/admin/support/[id])

  • Auto-match / AI assist panel: status, last attempt, disable / re-enable auto (PATCH { auto_reply_disabled }).
  • When auto_reply_status=ai_draft: edit draft body → Approve & send or Discard draft.
  • Thread bubbles label auto/KB/AI messages; drafts stay internal-note style.
  • Client falls back to public reply + disable if approve/discard routes are not yet mounted (404/501).

API client

$lib/support/admin-api.ts + $lib/support/auto-assist.ts

Method Path
list (+ flag) GET …/tickets
update (incl. auto_reply_disabled) PATCH …/tickets/{id}
approve draft POST …/tickets/{id}/ai-draft/approve
discard draft POST …/tickets/{id}/ai-draft/discard

Domain: apps/api/internal/support/staff_auto.go (ApproveAIDraft, DiscardAIDraft, ApplyQueueFlag).


FILES

Area Path
Helpers apps/web/src/lib/support/auto-assist.ts
Client apps/web/src/lib/support/admin-api.ts
Queue UI apps/web/src/routes/admin/support/+page.svelte
Detail UI apps/web/src/routes/admin/support/[id]/+page.svelte
Domain apps/api/internal/support/staff_auto.go, types.go (ListFilter.Flag), errors.go
List filter apps/api/internal/support/tickets.go (ApplyQueueFlag)
HTTP support_handlers.go, server.go (approve/discard mounts)

VERIFICATION

cd apps/web && npm run check
cd apps/api && go test ./internal/support/ ./internal/httpapi/ -count=1

Manual:

  1. As support_staff: open /admin/support?flag=needs_human and ?flag=ai_draft — no billing/settings nav.
  2. Ticket with FAQ/AI outcome: panel shows status; Disable auto sticks across refresh.
  3. ai_draft ticket: edit draft → Approve & send → customer-visible agent reply; draft queue clears.
  4. Discard → handed_off / auto disabled; ticket remains claimable.
  5. Ticket assigned to another agent → get/approve → 404/409 (not full admin leak).

ASSUMPTIONS

  • ASSUMPTION: Ticket auto columns come from agent 5 migration 031_support_ticket_detail (+ agent 3 032 KB). UI tolerates missing fields as empty/none.
  • ASSUMPTION: draft_only AI posts internal notes with is_auto_reply + auto_source=ai and sets auto_reply_status=ai_draft (agent 4).
  • ASSUMPTION: Public staff reply already sets auto_reply_disabled (existing ReplyAsAgent).

ROLLBACK

Revert staff UI/client + staff_auto.go + approve/discard routes + ListFilter.Flag. Leave schema migrations in place.