Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
3.9 KiB
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 underRequireSupportDesk(not full admin). - Web:
requireSupportDesk()on support pages;requirePlatformAdmin()elsewhere. AdminNavhides billing/settings/users/analytics for support-only staff.- Layout shows admin shell when
staff_access.support_deskorfull_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-rolebody{ "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 }→ setsstaff_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:
- As platform admin: Users → set a user
staff_role=support_staff. - Sign in as that user → admin shell shows Support (not billing).
- Open
/admin/support?scope=unassigned→ Claim → appears under Mine. - Unassign → returns to Unassigned.
- As full admin: open ticket → Assign to staff → Apply.
- Confirm
/admin/billingreturns 403 for support_staff (API + UI).
ASSUMPTIONS
- ASSUMPTION: Agent 6
ResolveStaffAccess—support_staffnever getsfull_admineven ifis_platform_admincolumn 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.