Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

05 — Screen Inventory (RBAC Module)

Six screens. Every element traces to an endpoint (rbac.controller.ts) or schema field (role.schema.ts, organization-member.schema.ts). Detailed specs in 06; forms in 08; wire contracts in 12.


#ScreenRouteServer endpoint(s)Personas
S1Roles list/settings/rolesGET /rbac/rolesPriya, Arjun
S2Role detail/settings/roles/:idGET /rbac/roles (client-side lookup)Priya, Arjun
S3Role editor (permission matrix)/settings/roles/new, /settings/roles/:id/editGET /rbac/permissions, POST /rbac/roles, PATCH /rbac/roles/:idPriya, Arjun
S4Members list/settings/membersGET /rbac/members + user.read mergePriya, Arjun, Samira
S5Add member/settings/members/add (bottom sheet)POST /rbac/membersPriya, Arjun
S6Permission audit view/settings/access-auditGET /audit-logs?action=&entityType=&actorId= (audit.controller.ts:17-34)Priya, Arjun

S1 — Roles list

  • Purpose: browse the tenant's roles; distinguish locked system roles from custom.
  • Elements: headlineMedium "Roles & Permissions"; search field (client-filter on name/slug); list of RoleRow sorted priority desc (rbac.service.ts:76); RoleRow = name + slug (mono) + description + system badge + permission-count badge; trailing AppMenu (Edit / Delete) on custom roles only; FAB "Create role".
  • States: loading AppSkeleton(list); error AppErrorState; empty "No custom roles yet — create your first role".
  • Server note: returns raw array, not paginated (rbac.service.ts:75-77); no meta in envelope (response-envelope.interceptor.ts:55-59).

S2 — Role detail

  • Purpose: read a role; jump to edit; see what it grants.
  • Elements: header (name, slug, description, priority, system badge); "N of 95 permissions" summary with permission group tiles (each group: label + chips of granted perms — reuse PermissionGroupSection read-mode); CTA "Edit permissions" (disabled for system roles); member holders section (proposed) — server offers no members-by-role endpoint, so holders would require client-side join of GET /rbac/ members + roles ((proposed), OQ-R7).
  • States: loading; error 404 (role soft-deleted or wrong tenant → treat as not found, RESOURCE_NOT_FOUND); system-role banner "System roles cannot be edited".

S3 — Role editor (permission matrix — hero)

  • Purpose: create/edit a role's permission set. The matrix is the module's hero component (07 §1, 06 §3, 15 §2).
  • Elements: form header (name, slug, description, priority — 08 §1); live badge "X of 95 selected"; AppSearchBar filtering groups/perms; group sections (23 groups, §06) each with select-all toggle + PermissionChips; bottom bar: "Cancel" / "Save role" (loading state); duplicate-slug inline error on 409.
  • Rules (derived): system roles never reach the editor (server refuses with 400 "Cannot modify system roles." rbac.service.ts:94-95); create always sends isSystem:false (OQ-R2); save is one PATCH with the full array (rbac.service.ts:96 $set — no per-cell endpoint).
  • States: loading (permissions + role fetch); error; dirty-state unsaved-changes dialog on back.

S4 — Members list

  • Purpose: who belongs to the tenant and with which roles.
  • Elements: headlineMedium "Members"; search (name/email via merged profile); MemberTile = AppAvatar (user initials/photo) + displayName + email (user.read merge, OQ-R7) + role chips + status badge (active only today, organization-member.schema.ts:7-11; invited/suspended render-only) + joined date; trailing AppMenu (Edit roles / Remove) — hidden for the viewer persona; FAB "Add member".
  • Server note: sorted joinedAt desc (rbac.service.ts:110); array, not paginated; no profile join (see OQ-R7).
  • States: loading/error/empty ("No members yet — add your first member").

S5 — Add member

  • Purpose: create a membership: pick an existing user + one or more role slugs.
  • Elements: full-height AppBottomSheet: AppSearchBar user picker (from GET /api/v1/users, users.controller.ts); selected user tile; role picker (FilterChips from GET /rbac/roles, system + custom, ordered by priority); "Add member" CTA; inline error for duplicate member (client pre-check — server 500s on E11000, OQ-R5).
  • Fields/validation: 08 §2userId @IsMongoId (add-member.dto.ts:6), roles @IsArray @IsString({each}) (add-member.dto.ts:10-12).
  • Server note: PATCH /rbac/members/:id reuses this DTO but ignores userId (rbac.controller.ts:71-72) — the edit-roles sheet can reuse the same role picker.

S6 — Permission audit view

  • Purpose: answer "who changed what, when" for RBAC events (and all other actions).
  • Elements: filter bar (action dropdown, entityType dropdown, actorId picker — all query params of audit.controller.ts:20-25); paginated log list (page/limit, default limit 50 server-side audit.controller.ts:20; envelope has meta — paginated shape per 07 §2); row = timestamp, action, entityType, actorId (mono), requestId.
  • States: loading/error/empty "No activity recorded"; pull-to-refresh; infinite scroll (paginated).
  • Gate note: server guard is JwtAuthGuard only (audit.controller.ts:9) — the audit.read permission is not enforced yet (Phase-5 (planned), docs/IMPLEMENTATION_PLAN.md:241); client gates the route on audit.read regardless.