Part of #306 — Phase 1.
Goal
Introduce the capability model + DB-backed role matrix + admin editor, seeded to exactly match today's behavior (behavior-neutral until a toggle is flipped). Migrate page gates to capabilities.
Scope
- Capability list — a fixed, code-defined set (page/action to start): e.g.
manage_employees, manage_therapy_types, manage_schedule, manage_appointment_requests, assign_specialists, process_intake, create_referrals, write_therapy_notes, view_therapy_notes, manage_contact_forms, view_patients, view_schedule_all, … (finalize during build).
RoleCapability model (role: UserType, capability: string, @@id([role, capability])) + migration + seed from current defaults (derive grants from today's computePermissions + pageAccessMap so nothing changes).
computePermissions() reads the matrix for the user's role and returns the capability set (plus relationship-derived PATIENT/PARENT as today). Capabilities travel in the session via customSession.
- Page gates: migrate
types/permissions.ts pageAccessMap values from role → capability; middleware/01.permission.global.ts resolves the required capability from the session set.
- Admin "Roles & Permissions" page (
/roles or /permissions, ADMIN-gated, sidebar-linked): a roles × capabilities checkbox grid; save writes RoleCapability. i18n (en/es).
- Guardrail: the ADMIN column is all-capabilities, locked/non-editable; API refuses any change that would leave ADMIN without full access or zero admins.
Out of scope (later phases)
Endpoint access migration + PHI/data capabilities + scope toggle (Phase 2); audit log + session invalidation + PHI warnings (Phase 3).
Acceptance criteria
Part of #306 — Phase 1.
Goal
Introduce the capability model + DB-backed role matrix + admin editor, seeded to exactly match today's behavior (behavior-neutral until a toggle is flipped). Migrate page gates to capabilities.
Scope
manage_employees,manage_therapy_types,manage_schedule,manage_appointment_requests,assign_specialists,process_intake,create_referrals,write_therapy_notes,view_therapy_notes,manage_contact_forms,view_patients,view_schedule_all, … (finalize during build).RoleCapabilitymodel (role:UserType, capability: string,@@id([role, capability])) + migration + seed from current defaults (derive grants from today'scomputePermissions+pageAccessMapso nothing changes).computePermissions()reads the matrix for the user's role and returns the capability set (plus relationship-derived PATIENT/PARENT as today). Capabilities travel in the session viacustomSession.types/permissions.tspageAccessMapvalues from role → capability;middleware/01.permission.global.tsresolves the required capability from the session set./rolesor/permissions, ADMIN-gated, sidebar-linked): a roles × capabilities checkbox grid; save writesRoleCapability. i18n (en/es).Out of scope (later phases)
Endpoint
accessmigration + PHI/data capabilities + scope toggle (Phase 2); audit log + session invalidation + PHI warnings (Phase 3).Acceptance criteria