Files
forge/claude_artifacts/engineer-20260827-180000.md
T
Dmytro Tkachenko 28d817ebe9 Init
2026-08-29 11:59:28 +03:00

2.5 KiB

engineer — RBAC + Token page + Filtered Excel export + full-width + donut fix

Date: 2026-08-27 · From: principal-20260827-175448

What changed

1. Roles / RBAC

  • server/db.ts: app_users.role TEXT NOT NULL DEFAULT 'viewer' (additive ALTER … ADD COLUMN IF NOT EXISTS). seedUser forces the bootstrap AUTH_USER to admin (and repairs pre-role rows). Added Role/ROLES/isRole, listUsers, createUser (23505 → 'exists'), deleteUser.
  • server/auth.ts: session user = {username, role}; verifyLogin returns the role; requireRole(min) — 401 unauth, 403 under-privileged.
  • index.ts route gates:
    • viewer: /api/tickets, /api/tickets/:number, /api/stats, /api/config
    • pm: /api/analytics/*, /api/insights
    • lead: GET/POST /api/users, DELETE /api/users/:username
    • admin: GET/POST /api/tokens, POST /api/tokens/:id/revoke
    • Only admin may create an admin (server 403 + client dropdown limits leadership to ≤lead).
  • Client: roleAtLeast/ROLE_LABELS; App route guards (reports→pm, /admin→lead); Sidebar shows Analytics only for pm+, Admin only for lead+; TopBar shows role.

2. API token page — pages/Admin (Tokens tab, admin only)

List (label/id/last-used/expires/revoked) + create (raw fg_… shown once, copy) + revoke. Replaces the x-admin-key HTTP gate with the admin session role. mint-token CLI unchanged.

3. Filtered Excel export

utils/excel.utils.ts (write-excel-file dep, as in Husky) → exports the board's currently filtered rows. Button in the board header. 17 columns incl. lifetime, days-in-state, cost, PO, link.

4. Also

  • Overall verifier REDO fixed: donut now fed byRequesterShare (full 966-ticket distribution), not the top-20 nested byRequester → center total 966, correct %.
  • All analytics pages max-width: none (charts span the full container width).

Verification (live, role forge_app DB)

  • server tsc / client tsc clean; client vite build OK; npm test 9 pass.
  • Gating matrix reproduced end-to-end: viewer → tickets/config 200, analytics/insights/users/tokens 403; pm → analytics/insights 200, users/tokens 403; admin → all 200. viewer POST /api/users 403.
  • Bootstrap admin row correctly migrated to role admin (not the 'viewer' default).

Next

security — audit the authz (public domain): privilege escalation, self-delete/last-admin, token exposure. verifier — gate the full change.