User Role
Data Entity
Description
Defines the role assigned to a user within a specific organization, governing access control, UI surface, and operational permissions across the Meander platform.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Primary key | PKrequiredunique |
user_id |
uuid |
FK to users table — the user this role record belongs to | required |
organization_id |
uuid |
FK to organizations table — the organization context for this role assignment | required |
role |
enum |
The assigned role. peer_mentor and coordinator are mobile-only. org_admin logs into admin portal (surfaces as coordinator on mobile). global_admin is Norse staff, admin portal only. | required |
is_active |
boolean |
Whether this role assignment is currently active. Deactivated roles block access without deleting history. | required |
granted_by_user_id |
uuid |
FK to users — the admin who assigned this role | - |
granted_at |
datetime |
Timestamp when this role was assigned | required |
revoked_at |
datetime |
Timestamp when this role was revoked/deactivated. Null if still active. | - |
revoked_by_user_id |
uuid |
FK to users — the admin who revoked this role | - |
metadata |
json |
Extensible field for role-specific configuration, e.g. local association scope for coordinators, support access expiry for global admins | - |
created_at |
datetime |
Record creation timestamp | required |
updated_at |
datetime |
Record last-updated timestamp | required |
Database Indexes
idx_user_roles_user_id
Columns: user_id
idx_user_roles_organization_id
Columns: organization_id
idx_user_roles_user_org
Columns: user_id, organization_id
idx_user_roles_user_org_role_active
Columns: user_id, organization_id, role, is_active
idx_user_roles_org_role_active
Columns: organization_id, role, is_active
Validation Rules
valid_role_enum
error
Validation failed
user_id_exists
error
Validation failed
organization_id_exists
error
Validation failed
granted_by_must_be_org_admin_or_global_admin
error
Validation failed
revoked_at_after_granted_at
error
Validation failed
is_active_false_requires_revoked_at
error
Validation failed
Business Rules
one_active_role_per_user_per_org
A user may hold only one active role per organization at a time. Assigning a new role must deactivate the existing active role for that user+org pair before inserting.
global_admin_no_org_scope
global_admin role records are created with a sentinel organization_id (platform-level org) and must never be scoped to a customer organization. Global admins have no default access to any org's operational data.
org_admin_surfaces_as_coordinator_on_mobile
When an org_admin authenticates via the mobile app, the mobile session bootstrap must return 'coordinator' as the effective mobile role. The user_roles record retains org_admin; this mapping is applied at token-claim generation time.
coordinator_and_peer_mentor_no_admin_portal_access
Users whose only active role is peer_mentor or coordinator must be blocked from admin portal login. The RoleGuardMiddleware enforces this at API and SSR level.
global_admin_support_access_time_bounded
When an org grants support access to a global admin, the grant is time-bounded (expiry stored in organization_settings or support_access_grants). The role check must verify expiry on every request; expired grants are treated as revoked.
revocation_audit_trail
Every role deactivation (is_active = false) must write an audit_log record capturing who revoked the role, when, and from which org. This is required for security compliance.
bulk_role_change_audit
Bulk role reassignments performed via BulkUserActionService must individually audit-log each changed record, not log the bulk operation as a single entry.