Test Cases: Access Control Enforcement

Module: RBAC - Access Control

Enforcement: auth-service/src/rbac.tsrequirePermission(key) middleware. SUPER_ADMIN bypasses all checks; permission set is cached per (tenant + roleCodes) for 5 minutes; DB errors fail closed (403, never 200).

Prerequisites

Test Data — Users by Role

UserRolePrimary access
AdminADMINFull access (all 38 permissions)
Juan SantosOFFICERRead-only visibility (members, events, dashboard, bank-accounts view)
Ana ReyesFINANCE_MANAGERFinance (invoices, payments, dues, donations, bank-accounts) + members/events view
Carlos GarciaEVENT_MANAGEREvents (full) + Broadcasts (full) + members/prospects view
Elena TorresMEMBERSHIP_MANAGERMembers/prospects/invitations/import + events view
Seung Eun LeeCOMMUNICATIONS_MANAGERBroadcasts (full) + members/events view
Maria CruzMEMBEROwn profile, events, own invoices, directory
Roberto MendozaGUESTPublic/events only

Test Cases

TC-RBAC-031: Admin Full Access

StepActionExpected Result
1Login as ADMIN. Open each admin group: Overview, Finance, Members, Events, Communications, Settings.All accessible.
2Open Settings → Roles & Permissions.Access granted.

TC-RBAC-032: Finance Manager — Allowed

StepActionExpected Result
1Login as Ana Reyes. Open Finance → Invoices, Payments, Donations Report.Access granted.
2Open All Members (view) and All Events (view).Access granted (view-level).

TC-RBAC-033: Finance Manager — Denied

StepActionExpected Result
1As Ana Reyes, browse to /admin/roles and /admin/settings.Silent redirect to /home.
2Confirm no Communications/Broadcasts and no Prospects in sidebar.Hidden.
3API: GET /api/broadcasts as FINANCE_MANAGER.Status 403.

TC-RBAC-034: Event Manager — Allowed (incl. Broadcasts)

StepActionExpected Result
1Login as Carlos Garcia. Create/edit an event; view registrations; perform check-in.Permitted (EVENTS:*).
2Open Communications → Broadcasts; create a draft.Permitted — EVENT_MANAGER holds COMMUNICATIONS:*.

TC-RBAC-035: Event Manager — Denied

StepActionExpected Result
1As Carlos, browse to /admin/invoices / /admin/payments.No Finance sidebar; route redirects.
2API: GET /api/billing/admin/payments as EVENT_MANAGER.Status 403.

TC-RBAC-036: Member — Standard Access

StepActionExpected Result
1Login as Maria Cruz. View/edit own profile; view directory; register for an event; view own invoices.All granted.

TC-RBAC-037: Member — Denied Admin Access

StepActionExpected Result
1As Maria, browse to any /admin/* URL.Silent redirect to /home; no admin nav visible.
2API: GET /api/membership/members as MEMBER.Status 403 (no MEMBERS:VIEW:members).
3API: POST /api/events as MEMBER.Status 403.

TC-RBAC-038: Guest — Public Only

StepActionExpected Result
1Login as Roberto Mendoza (GUEST). View public events.Granted.
2Browse to /directory and any /admin/*.Both denied/redirected.

TC-RBAC-039: No Token → 401

StepActionExpected Result
1Call any protected API (e.g. GET /api/admin/roles) with no Authorization header.Status 401.

TC-RBAC-040: Expired / Invalid Token → 401

StepActionExpected Result
1Call a protected API with an expired or malformed JWT.Status 401.

TC-RBAC-041: Conditional UI Rendering

StepActionExpected Result
1As MEMBER, confirm no admin sidebar groups render.Hidden (sidebar is role-gated in branding.ts).
2As EVENT_MANAGER, confirm the Events group + "Create Event" render.Shown.

TC-RBAC-042: Cross-Tenant Isolation

StepActionExpected Result
1As an RCME admin, attempt to read another tenant's resources (e.g. via a foreign ID).Denied — not found / forbidden. Permission cache key includes tenantId.

TC-RBAC-043: SuperAdmin Bypass

StepActionExpected Result
1Authenticate via POST /api/auth/platform/login as SuperAdmin. Call protected org APIs with the platform JWT.requirePermission bypasses all checks (platformRoles includes SUPER_ADMIN).
2Do NOT log SuperAdmin into the org PWA for tenant-scoped work — use the admin portal (stg-admin.membervu.com). Tenant-scoped org API calls may 401 when the JWT has tenantId: null.Documented behaviour.

API Permission Enforcement Matrix

Verified against current route guards (requirePermission(...)). SUPER_ADMIN returns 200 on all org endpoints (bypass) and is omitted for brevity.

Endpoint (guard)ADMINFINANCE_
MANAGER
EVENT_
MANAGER
MEMBERSHIP_
MANAGER
COMMS_
MANAGER
MEMBERNo token
GET /api/admin/roles
ADMIN:VIEW:roles
200403403403403403401
POST /api/events
EVENTS:EDIT:events
200403200403403403401
GET /api/billing/admin/payments
FINANCE:VIEW:payments
200200403403403403401
GET /api/membership/members
MEMBERS:VIEW:members
200200200200200403401
POST /api/membership/members/:id/suspend
ADMIN or MEMBERSHIP_MANAGER
200403403200403403401
GET /api/broadcasts
COMMUNICATIONS:VIEW:broadcasts
200403200403200403401
GET /api/public/events
public
200200200200200200200

Corrected from prior version: GET /api/membership/members is 403 for a plain MEMBER (was wrongly 200); GET /api/broadcasts is 200 for EVENT_MANAGER (was wrongly 403). Endpoint paths were also corrected to the real mounts.