02 — User Personas (RBAC Module)
- 1. Priya — Organization Admin (primary persona)
- 2. Arjun — Role Manager (forward-looking, OQ-R1)
- 3. Samira — Member Viewer
- 4. Vikram — Platform Admin (sysadmin)
- 5. David — Guarded End-User (teacher)
- Persona → screen matrix
Five personas cover the RBAC surface. Derived from the seeded roles (
role.schema.ts:8-65), the endpoints (rbac.controller.ts), and the guard pipeline (rbac.guard.ts). The "Role manager" and "Member viewer" personas are forward-looking: the server currently gates/rbac/*behind@Roles('org_admin')(rbac.controller.ts:21), so their ability to act depends on OQ-R1.
1. Priya — Organization Admin (primary persona)
"I need to control who can touch what, and I don't have time for IT tickets."
- Slug/roles:
org_admin— all 95 permissions (role.schema.ts:17-24). - Context: Principal/admin of a 400-student school. Created the org at registration;
the system auto-added her as
org_adminmember (auth.service.ts:84-99). - Goals
- Seed the org quickly: teachers, accountant, librarian, transport manager each get a fitting role without exposing admin powers.
- Create a custom role ("Fee Counter Clerk") with exactly
fees.collect, student.read, receipts.read— no more, no less. - Add members, fix a wrong role, and remove a leaver in under a minute.
- Never accidentally lock herself out; never let a staff member see salary/finance data.
- Frustrations
- A custom role she creates becomes un-editable (system-lock bug,
role.schema.ts:78-79default; see OQ-R2) — the UI must forceisSystem:falseand warn. - Members list shows raw member docs without names (
rbac.service.ts:109-111) — the UI must mergeuser.readdata (OQ-R7). - She can't tell a leaver's permissions at a glance; wants an audit trail.
- A custom role she creates becomes un-editable (system-lock bug,
- Needs: permission matrix grouped by module with search; system-role lock badges;
member tiles with role chips; 403-prevention copy ("You are about to remove your own
org_admin— you will lose access to this screen").
2. Arjun — Role Manager (forward-looking, OQ-R1)
"I audit access quarterly. I want to see who holds what, and why."
- Roles (proposed): a custom role holding
rbac.role.read, rbac.role.update, rbac.member.read, rbac.member.update, user.read, audit.read— notorg_admin. - Context: Operations head trusted with access governance but deliberately not with org billing/settings.
- Goals: browse roles, inspect a role's permission set, adjust a role's perms, reassign
a member's roles, review the permission-audit view (
GET /audit-logs,audit.controller.ts:17). - Frustrations: today the server rejects him with 403 —
@Roles('org_admin')(rbac.controller.ts:21) ignores hisrbac.*permissions. Screen copy must explain "managed by Organization Admin" until OQ-R1 ships. - Needs: read-only-friendly layouts (view mode for the matrix), permission diff preview before saving, audit filter by actor/action.
3. Samira — Member Viewer
"I just need to know who's on the transport desk this week."
- Roles: custom role with
rbac.member.read, user.read(or a staff member). - Context: receptionist cross-checking who can issue books.
- Goals: open the members list, see names + role chips, search a member.
- Frustrations: zero write affordances must ever render for her; a stray "Add member" button that 403s on tap is a trust-breaker.
- Needs: view-only matrix/member list; no FAB; 403 states never reached via UI.
4. Vikram — Platform Admin (sysadmin)
"One product, thousands of tenants. I watch from above, not inside."
- Slug:
platform_admin—[]permissions (role.schema.ts:8-16), cross-tenant repository bypass (base.repository.ts:21). - Context: platform operator. Tenant-scoped RBAC is none of his daily business; his concern is that tenant A's admin can never touch tenant B.
- Goals: verify tenant isolation (QA 14), support escalation reads, never appear in tenant RBAC screens as a normal actor.
- Frustrations:
platform_adminis notorg_admin— the/rbac/*controller would 403 him (rbac.controller.ts:21); repository scoping lets him read across tenants (base.repository.ts:22). The client must treat platform_admin as a distinct shell persona with its own tenant picker — the tenant RBAC screens stay reachable only with an org_admin token in that tenant.
5. David — Guarded End-User (teacher)
"I hit a locked door once; I never want to hit it again."
- Slug:
teacher—student.read, attendance.mark, attendance.edit(role.schema.ts:25-32). - Context: marks attendance daily, sees student rosters. RBAC is invisible to him — until it isn't.
- Goals: never see admin screens; when a route changes mid-session (role edited at lunch), get kicked gracefully with a reason, not a white 403 screen.
- Frustrations: a 403 with no explanation; a hidden-then-broken menu item; being
logged out without explanation after an admin changed his role (JWT roles frozen at
login,
auth.service.ts:145-154; OQ-R4). - Needs: 403 screen with cause + contact copy; route tree rebuilt on permission change (05_Global_Information_Architecture.md §9); offline-tolerant lists.
Persona → screen matrix
| Screen | Priya (org_admin) | Arjun (role mgr, planned) | Samira (viewer) | Vikram (platform) | David (teacher) |
|---|---|---|---|---|---|
| Roles list | full | read/edit (planned) | — | — | — |
| Role detail | full | read | — | — | — |
| Role editor + matrix | full | edit (planned) | — | — | — |
| Members list | full | read/edit (planned) | read (if granted) | tenant-picker (planned) | — |
| Add member | full | edit (planned) | — | — | — |
| Permission audit | full (audit.read) | read | — | — | — |
| 403 screen | never | until OQ-R1 | never via UI | never via UI | when role revoked mid-session |