brokerId / employerId before returning or mutating data.
Role Definitions
member role is defined in the type system for future member-portal use but is not currently active in the application UI.Tenant Scoping
Multi-tenancy is enforced structurally, not just by convention. Every database query that returns scheme, member, or employer data includes abrokerId or employerId filter derived from the authenticated session:
Role Mapping
The application maps database role names to session role values insrc/lib/auth.ts:
Session Claims
Every authenticated session carries:API Enforcement Pattern
1
Extract session
const session = await auth() — retrieves the validated JWT session server-side.2
Check authentication
If
!session?.user, return 401 Unauthorized.3
Check role
If the route requires a specific role (e.g.,
broker or admin), check session.user.role. Return 403 Forbidden if insufficient.4
Scope the query
Append
brokerId or employerId to every database query using the session claim.Audit Trail
All material actions — regardless of role — are written to the append-onlyaudit_logs table, recording the actorId, actorType, action performed, previous state, and new state. See Audit Logging for schema details.
AI Change Proposals
AI-generated suggestions never bypass RBAC. ThechangeProposals table enforces:
- Proposals are scoped to a
brokerId(and optionallyschemeId,memberId) - Only an authorised broker user can approve or reject a proposal
- Required attestations must be completed before approval is permitted
- Proposals auto-expire if not acted upon