Role-Based Access Control
Add real roles and permissions: enforced on backend endpoints and reflected honestly in the UI.
The route
6 steps to Done
- 01
Define roles and the permission matrix
Enforcement needs a truth table - write it before code.
Preview prompt + verify gate ▾ Hide ▴
Define the RBAC spec. List: the role set (e.g. admin, member, viewer) and a default role for new users; a permission matrix table of every sensitive action (manage users, edit content, delete records, view admin pages, change settings) versus each role with allow/deny; where the role is stored (user record, server-side) and how the backend reads it (from the session, never the request body).
- ✓ Every sensitive action appears in the matrix
- ✓ Default role for new users is set
- ✓ Role source of truth is the server-side user record
- 02
Add roles to the user model
Persist the role and expose it safely to the session.
Preview prompt + verify gate ▾ Hide ▴
Implement role storage. Requirements: add a role field to the user model with the default applied at signup; migrate/set roles for existing users; include the role in the authenticated session/user fetch so the frontend can adapt; create one test user per role. The client must never be able to write its own role through profile update endpoints.
- ✓ New signups get the default role
- ✓ Session/user fetch includes the role
- ✓ Profile update endpoint ignores/rejects role changes
- 03
Enforce permissions on the backend
The core of RBAC: every protected endpoint checks the matrix.
Preview prompt + verify gate ▾ Hide ▴
Implement backend enforcement. Requirements: a reusable permission check (middleware/dependency) that reads the session user's role and the required permission; apply it to every endpoint in the matrix; forbidden calls return 403 with a clear error body; unauthenticated calls return 401; verify by calling each protected endpoint as each role (test users) and recording the status codes in a table.
- ✓ Every matrix endpoint has the check applied
- ✓ Viewer role gets 403 on admin calls
- ✓ The status-code table matches the matrix exactly
- 04
Adapt the UI per role
Honest UI: users see what they can do, and nothing pretends otherwise.
Preview prompt + verify gate ▾ Hide ▴
Implement role-aware UI. Requirements: hide or disable (with tooltip explaining why) controls the current role cannot use - admin nav, edit/delete buttons, settings sections; base this on the session role, not localStorage; ensure no route renders a forbidden page shell before redirecting; even if a user re-enables a hidden button via devtools, the backend 403 must protect the action and surface a visible error.
- ✓ Viewer sees no edit/delete/admin controls
- ✓ Tooltips explain disabled actions
- ✓ Devtools-forced action hits 403 and shows an error
- 05
Build admin role management
Admins must manage roles safely, without lockouts.
Preview prompt + verify gate ▾ Hide ▴
Implement role management. Requirements: an admin-only users list showing each user's role; a role selector to change it with confirmation; changes persist and take effect on the target's next request (no re-login needed - state how the session picks it up); protection so the last remaining admin cannot demote themselves; audit note (who changed what, when) if lightweight.
- ✓ Role change persists and alters the target's access
- ✓ Target's UI adapts without re-registration
- ✓ Last-admin self-demotion is blocked with a message
- 06
RBAC QA pass
Attack the boundaries as every role and verify the matrix holds.
Preview prompt + verify gate ▾ Hide ▴
Run RBAC QA and report PASS/FAIL with evidence: as each role, attempt every matrix action via the UI and directly via the API; verify 403s where expected; verify the viewer cannot see admin UI; change a role and confirm immediate effect; attempt last-admin self-demotion; attempt role self-escalation via profile endpoint. Fix all failures and re-run the table.
- ✓ Direct API attempts tested per role
- ✓ Self-escalation attempt blocked
- ✓ Role change propagation verified
- ✓ All failures fixed