Role
Data Entity
Description
Defines the four access levels in the system: Peer Mentor, Coordinator, Organization Administrator, and Global Administrator. Roles drive all permission checks, screen visibility, API authorization, and data scoping logic across the entire platform.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Immutable primary key for the role record, generated on system seed. | PKrequiredunique |
slug |
enum |
Machine-readable role identifier used in JWT claims, API authorization checks, permission matrix lookups, and route guards throughout the platform. | requiredunique |
name |
string |
Human-readable display name for the role, shown in user management screens and audit logs. | requiredunique |
description |
text |
Prose description of the role's responsibilities and scope, used in admin panel tooltips and onboarding documentation. | - |
hierarchy_level |
integer |
Numeric ordering that encodes privilege hierarchy: 1=peer_mentor, 2=coordinator, 3=org_admin, 4=global_admin. Used to prevent privilege escalation — admins may only assign roles with hierarchy_level strictly less than their own. | requiredunique |
permission_matrix |
json |
Structured JSON object mapping permission keys to boolean grants. Keys follow the pattern '<resource>:<action>' (e.g., 'activity:create', 'report:export_bufdir', 'user:invite'). Consumed by role-guard-service for synchronous permission lookups and cached client-side in permissions-repository. | required |
mobile_access |
boolean |
Whether this role grants access to the Flutter mobile app. False for global_admin (redirected to admin panel only). | required |
admin_panel_access |
boolean |
Whether this role grants access to the Next.js admin panel. True for coordinator, org_admin, and global_admin. | required |
data_scope |
enum |
Defines the data visibility boundary for this role. Controls how repositories and services scope SQL queries. | required |
created_at |
datetime |
Timestamp when the role record was created (system seed time). | required |
updated_at |
datetime |
Timestamp of the last permission_matrix or metadata update. | required |
Database Indexes
idx_role_slug
Columns: slug
idx_role_hierarchy_level
Columns: hierarchy_level
idx_role_name
Columns: name
Validation Rules
slug_must_be_valid_enum
error
Validation failed
permission_matrix_valid_json
error
Validation failed
hierarchy_level_in_range
error
Validation failed
name_not_empty
error
Validation failed
mobile_and_admin_panel_access_consistent
error
Validation failed
jwt_role_claim_matches_slug
error
Validation failed
Business Rules
system_seeded_immutable_set
Exactly four role records exist and are created exclusively by the database seed migration. No runtime API endpoint may create or delete role records. The set of valid slugs is closed: peer_mentor, coordinator, org_admin, global_admin.
no_privilege_escalation
An authenticated user may only assign roles with a hierarchy_level strictly lower than their own. A Coordinator (level 2) cannot grant Coordinator, Org Admin, or Global Admin roles. Enforced server-side on every invite and role-assignment operation.
global_admin_mobile_redirect
Users whose active role is global_admin must not be granted mobile app access. The No-Access Screen is displayed with a link to the admin panel. The JWT claims for global_admin users must set mobile_access=false.
data_scope_enforcement
Every data-fetching repository and service must apply the data_scope of the requesting user's role. peer_mentor sees only own records; coordinator sees their local_association; org_admin sees their full organization; global_admin sees all data.
permission_matrix_completeness
The permission_matrix JSON for each role must contain an explicit grant (true/false) for every registered permission key. Missing keys default to false, but a schema validator must warn on deployment if any permission key is absent from a role's matrix.
coordinator_requires_association_scope
Any coordinator-level operation (team reports, bulk registration, reimbursement approval) must be scoped to a specific local_association_id drawn from the user's user_organization_roles record. A coordinator may not access data for associations they are not assigned to.
permission_matrix_cached_on_login
After successful authentication, the client must fetch and cache the permission_matrix for the user's active role via the permissions-repository. Subsequent permission checks (route guards, UI visibility) are resolved synchronously from this cache without network round-trips.
CRUD Operations
Storage Configuration
Entity Relationships
A role can be assigned to many users across organizations