core PK: id 8 required 1 unique

Description

Defines the role assigned to a user within a specific organization, governing access control, UI surface, and operational permissions across the Meander platform.

12
Attributes
5
Indexes
6
Validation Rules
18
CRUD Operations

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
btree

Columns: user_id

idx_user_roles_organization_id
btree

Columns: organization_id

idx_user_roles_user_org
btree

Columns: user_id, organization_id

idx_user_roles_user_org_role_active
btree

Columns: user_id, organization_id, role, is_active

idx_user_roles_org_role_active
btree

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
on_create

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
on_create

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
always

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
always

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
always

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
on_update

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
on_update

Bulk role reassignments performed via BulkUserActionService must individually audit-log each changed record, not log the bulk operation as a single entry.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
No Partitioning
Retention
Permanent Storage