Files
descrybe/docs/admin-roles-support/README.md
T
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

146 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Admin roles, legacy plans & support desk
End-to-end work from the **20-agent** `admin-roles-support` swarm: legacy (A1) limited nav, platform staff roles, admin panel polish, support assign/claim + CSAT ratings.
**Runtime rule (tenant features):**
```
effective(feature) = plan_allows(feature)
AND global_section_enabled(section(feature))
AND global_feature_enabled(feature)
```
Staff access is **orthogonal** to plan features: `users.staff_role` + `is_platform_admin` gate `/admin` and the support desk.
---
## Doc map (agents 119)
| Doc | Owner | What it covers |
|-----|-------|----------------|
| [01-ux-research.md](./01-ux-research.md) | 1 | Admin / permissions / support UX patterns |
| [02-current-inventory.md](./02-current-inventory.md) / [02-extension-points.json](./02-extension-points.json) | 2 | Pre-change inventory |
| [03-roles-matrix.md](./03-roles-matrix.md) / [`.json`](./03-roles-matrix.json) | 3 | Legacy allow-list + role→feature matrix |
| [04-contract.md](./04-contract.md) / [`.json`](./04-contract.json) | 4 | Unified plan + staff contract |
| [05-legacy-seed.md](./05-legacy-seed.md) | 5 | Legacy profile seed / A1 detection |
| [06-staff-roles.md](./06-staff-roles.md) | 6 | `admin` / `developer` / `support_staff` backend |
| [07-admin-shell.md](./07-admin-shell.md) | 7 | Admin layout / nav chrome |
| [08-permissions-ui.md](./08-permissions-ui.md) | 8 | Billing → Permissions panel |
| [09-admin-billing-ui.md](./09-admin-billing-ui.md) | 9 | Plans list / assign polish |
| [10-admin-orgs-ui.md](./10-admin-orgs-ui.md) | 10 | Users/companies + staff role grant |
| [11-support-design.md](./11-support-design.md) / [11-support-api-contract.json](./11-support-api-contract.json) | 11 | Support desk design |
| [12-support-backend.md](./12-support-backend.md) | 12 | Tickets / claim / assign API |
| [13-support-ratings.md](./13-support-ratings.md) | 13 | CSAT 15 ratings |
| [14-support-staff-ui.md](./14-support-staff-ui.md) | 14 | Staff inbox + assign UI |
| [15-user-support-ui.md](./15-user-support-ui.md) | 15 | Customer support + rate UI |
| [16-legacy-nav.md](./16-legacy-nav.md) | 16 | A1 image-nav gating |
| [17-security.md](./17-security.md) | 17 | AuthZ / IDOR / CSRF pass |
| [18-performance.md](./18-performance.md) | 18 | Indexes / list bounds |
| [19-defaults-alignment.md](./19-defaults-alignment.md) | 19 | Ladder + Legacy + staff defaults |
Related: [`../plan-permissions/README.md`](../plan-permissions/README.md) (feature keys + admin Permissions API).
---
## Schema (goose)
| Version | File | Purpose |
|---------|------|---------|
| 026 | `apps/api/sql/schema/026_plan_features.sql` | `plans.features` + global gates |
| 027 | `027_capabilities_support_perf.sql` | Capabilities + support queue indexes |
| 028 | `028_plan_is_legacy.sql` | `plans.is_legacy` + name backfill |
| 029 | `029_staff_roles.sql` | `users.staff_role` |
| 030 | `030_support_desk.sql` | CSAT table, claim queue cols, notification kinds |
Apply (Windows):
```powershell
.\scripts\migrate.ps1
# or from apps/api with DATABASE_URL set:
go run github.com/pressly/goose/v3/cmd/goose@v3.24.3 -dir sql/schema postgres $env:DATABASE_URL up
```
Strip UTF-8 BOM from new SQL if goose errors on `\ufeff-- +goose Up`.
---
## Code map
| Concern | Paths |
|---------|--------|
| Legacy detect/seed | `apps/api/internal/billing/legacy_plan*.go` |
| Staff roles | `apps/api/internal/auth/staff*.go`, `httpapi/middleware.go`, `admin_staff_handlers.go` |
| Support desk | `apps/api/internal/support/{desk,ratings,agents,tickets}.go`, `httpapi/support_*.go` |
| Admin shell | `AdminNav.svelte`, `admin-nav-ui.svelte.ts`, root `+layout.svelte` |
| Permissions UI | `PlanPermissionsPanel.svelte`, `admin-plan-permissions.ts` |
| Orgs / staff grant | `routes/admin/users/+page.svelte`, `admin-orgs.ts` |
| Legacy nav | `Nav.svelte`, `plan-capabilities.ts`, `PlanRouteGuard.svelte` |
| Staff inbox | `routes/admin/support/**` |
| User rate | `SupportTicketRating.svelte`, `routes/support/**` |
---
## Manual verify checklist
### A1 / Legacy nav
- [ ] `goose`**30**; `seed-demo` (or `EnsureDefaultPlans`) so **Local Demo Co** is on plan **Legacy** (`is_legacy=true`)
- [ ] Restart API after migrate/seed
- [ ] Login as demo → Local Demo Co → sidebar shows only: Dashboard, Products, Feeds, Export Feeds, Categories, Attributes, Standard Fields, Usage & Billing, Settings
- [ ] No Background Tasks / Processing, Stores, Campaigns, Brand, SEO (no empty **More** unless Platform admin)
- [ ] `GET /api/billing/capabilities`: `processing.monitor` / `stores.hub` / `marketing.*` → false; nav parents → true
- [ ] Deep link `/processing` → upgrade panel
### Admin panel polish
- [ ] `/admin` shell: sidebar groups Monitor / Manage, dark content, mobile drawer
- [ ] `/admin/billing` → Permissions: profiles (incl. Legacy one-click), section toggles
- [ ] `/admin/users`: companies + assign plan + staff role dialog
### Support assign + rate
- [ ] Customer: create ticket → staff reply → resolve → rate 15 (`SupportTicketRating`)
- [ ] Staff: `/admin/support?scope=unassigned` → Claim → Mine; Unassign returns to queue
- [ ] Full admin: ticket detail → Assign to staff → Apply
- [ ] API: support routes under `RequireSupportDesk`; billing mutations still `RequirePlatformAdmin`
### Staff role access
- [ ] Grant `support_staff` from Users → that user sees Support (+ Overview redirects to Support), not Billing/Settings
- [ ] `GET /api/admin/billing` (or plans) → **403** for support_staff
- [ ] `admin` / `developer` / legacy `is_platform_admin` + NULL role → full console
- [ ] Cannot PATCH own `staff_role`
---
## Verify commands
```powershell
.\scripts\migrate.ps1
cd apps\api
go test ./internal/billing/ ./internal/auth/ ./internal/support/ -count=1
go test ./internal/httpapi/ -count=1 -run "Staff|Support|PlanFeature|PlanGate|AdminAuth|RequirePlatform|CSAT|Csat"
cd ..\web
npm run check
```
Optional demo alignment:
```powershell
cd apps\api
go run ./cmd/seed-demo -postgres $env:DATABASE_URL
```
---
## Integration notes (agent 20)
- Merged duplicate `028_*` legacy SQL into `028_plan_is_legacy.sql`; renumbered staff → **029**, support desk → **030**.
- `/admin` Overview: `support_staff` redirected to `/admin/support` (nav still shows Overview).
- `seed-demo` / `EnsureLegacyDefaults` assigns **Legacy** to Local Demo Co / A1 cohort (not Enterprise all-ON).
### Remaining blockers / non-goals
1. Not every tenant mutation is `AssertFeature`'d (same as plan-permissions agent 10) — UI + critical writes first.
2. Live browser QA of admin polish + CSAT requires a running `npm run dev` session and staff test user.
3. OpenAPI public fragment may still omit some support/staff paths (session docs in plan-permissions / support contract JSON).