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

3.9 KiB

14 — Support staff UI

Agent: 14/20
Status: Implemented
Coordinates with: 06-staff-roles (middleware + staff_role), 11-support-design / 12-support-backend (claim/scope/agents), 07-admin-shell, 10-admin-orgs-ui (grant role)


PROBLEM

Platform support work lived behind full is_platform_admin. Staff need an inbox with claim/unassign, assignment, and filters — without billing/settings access. Platform admins must be able to grant support_staff from the orgs/users UI.


WHAT SHIPPED

Access model

Actor Gate Surfaces
Full admin (admin / developer / legacy platform admin) RequirePlatformAdmin / staff.full_admin Full /admin/*
support_staff RequireSupportDesk / staff.support_desk /admin/support/** (+ Overview in nav)
Customers company session /support/** (unchanged)
  • API: /api/admin/support/* mounted under RequireSupportDesk (not full admin).
  • Web: requireSupportDesk() on support pages; requirePlatformAdmin() elsewhere.
  • AdminNav hides billing/settings/users/analytics for support-only staff.
  • Layout shows admin shell when staff_access.support_desk or full_admin.

Queue + ticket UI (/admin/support)

  • Scopes: Inbox · Mine · Unassigned · All (All = full admin only). Persisted in ?scope=.
  • Status chips + search (subject / email / company).
  • Claim on unassigned open/pending rows and on ticket detail.
  • Unassign / release when assignee is self (or force for full admin).
  • Assign to staff (full admin): agent picker from GET /api/admin/support/agents.
  • Assignee column shows email / “You” / Unassigned.
  • Visual language matches reworked admin shell (PageShell, Card, TableShell, filter chips).

Role grant coordination (orgs UI)

Platform admins grant roles via:

  • PATCH /api/admin/users/{id}/staff-role body { "staff_role": "support_staff" | "admin" | "developer" | null }
  • Admin Users UI (apps/web/src/routes/admin/users/+page.svelte + $lib/admin-orgs.ts) — role dialog owned with agent 10.
  • Optional alias: PUT /api/admin/support/agents/{id} { "is_support_agent": true } → sets staff_role=support_staff.

/api/auth/me returns staff_access + staff_capabilities for client gating.


FILES (primary)

Area Path
Client API apps/web/src/lib/support/admin-api.ts
Gates apps/web/src/lib/admin-gate.ts (requireSupportDesk)
Types / session apps/web/src/lib/types.ts, auth-session.svelte.ts
Nav / layout AdminNav.svelte, routes/+layout.svelte
Queue / detail routes/admin/support/+page.svelte, [id]/+page.svelte
Handlers apps/api/internal/httpapi/support_handlers.go (scope, claim, release, agents)
Desk domain apps/api/internal/support/desk.go, agents.go

VERIFICATION

cd apps/api && go test ./internal/support/ ./internal/auth/ ./internal/httpapi/ -count=1

Manual:

  1. As platform admin: Users → set a user staff_role=support_staff.
  2. Sign in as that user → admin shell shows Support (not billing).
  3. Open /admin/support?scope=unassigned → Claim → appears under Mine.
  4. Unassign → returns to Unassigned.
  5. As full admin: open ticket → Assign to staff → Apply.
  6. Confirm /admin/billing returns 403 for support_staff (API + UI).

ASSUMPTIONS

  • ASSUMPTION: Agent 6 ResolveStaffAccesssupport_staff never gets full_admin even if is_platform_admin column is true.
  • ASSUMPTION: Least-privilege visibility for agents (inbox / claim) is enforced server-side in list/get/update (agent 12).
  • CSAT ratings UI is owned by sibling agents; this doc does not cover rating widgets.

ROLLBACK

Revert support route UI/gate/nav changes and remount support APIs under RequirePlatformAdmin only if needed. Staff role column (029_staff_roles) is additive — leave in place.