User
Data Entity
Description
Core identity entity representing every person who interacts with the system, including peer mentors, coordinators, and administrators. Users authenticate via email/password, BankID, or Vipps and hold organizational memberships that determine their access scope and data visibility.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Immutable primary key generated by Supabase Auth (auth.uid()). Used as the foreign key anchor across all user-related tables. | PKrequiredunique |
email |
string |
User's email address. Required for email/password login and used as the primary contact identifier across all auth providers. Must be unique system-wide. | requiredunique |
phone |
string |
Norwegian mobile phone number. Used for Vipps authentication matching, push notification fallback, and coordinator contact. Stored in E.164 format (+47XXXXXXXX). | - |
full_name |
string |
User's full legal name as provided during registration or sourced from BankID/Vipps identity token. Displayed across coordinator dashboards, assignment dispatch, and notification payloads. | required |
personnummer |
string |
Norwegian national identity number (11 digits). Populated only for users who authenticate via Vipps SSO when the personnummer scope is granted. Used for member system writeback to Cornerstone and Consio. Stored encrypted at rest. | - |
auth_provider |
enum |
The authentication provider used for the user's initial registration. Determines which auth flow is presented on subsequent logins. Biometric is always secondary to an initial provider. | required |
profile_picture_url |
string |
Optional URL to the user's profile avatar stored in Supabase Storage. Used in peer mentor cards, coordinator dashboards, and assignment interfaces. | - |
preferred_locale |
string |
User's preferred language locale code (BCP 47). Defaults to Norwegian Bokmål ('nb'). Drives organization label resolution, screen reader announcements, and speech recognition locale selection. | required |
public_key |
text |
The user's RSA or EC public key used for end-to-end encrypted assignment dispatch. Registered on first authenticated login by the Key Management Service. Required before a coordinator can send encrypted assignments to this user. | - |
is_active |
boolean |
Soft-delete and deactivation flag. Set to false when a user is deactivated by an admin rather than hard-deleted. Inactive users cannot authenticate and are excluded from all queries by default via RLS. | required |
is_email_verified |
boolean |
Indicates whether the user's email address has been confirmed via Supabase Auth email verification. Email/password users cannot access the app until verified. BankID and Vipps users are considered verified by the identity provider. | required |
nda_required |
boolean |
Indicates whether this user is required to sign a valid NDA before accessing encrypted assignment content. Set to true for peer mentors at Blindeforbundet and any organization with encrypted document workflows. | required |
last_login_at |
datetime |
Timestamp of the user's most recent successful authentication event, regardless of provider. Updated on every successful login. Used for inactivity detection, impact summary eligibility, and audit reporting. | - |
created_at |
datetime |
Immutable timestamp recording when the user record was first created in the system. Set automatically by Supabase on insert. | required |
updated_at |
datetime |
Timestamp of the most recent update to this user record. Maintained automatically via a Supabase database trigger. Used for sync conflict resolution in member system integrations. | required |
deleted_at |
datetime |
Soft-delete timestamp. Null for active users. Set to the deletion timestamp when a user is removed by an admin. Records with non-null deleted_at are excluded from all standard RLS policies and API responses. | - |
metadata |
json |
Arbitrary extensible metadata bag for storing provider-specific claims not covered by structured columns (e.g., BankID acr values, Vipps phone verification level). Populated and read by the respective integration services. | - |
Database Indexes
idx_users_email
Columns: email
idx_users_phone
Columns: phone
idx_users_is_active
Columns: is_active
idx_users_auth_provider
Columns: auth_provider
idx_users_last_login_at
Columns: last_login_at
idx_users_created_at
Columns: created_at
idx_users_deleted_at
Columns: deleted_at
Validation Rules
email_format_validation
error
Validation failed
full_name_not_empty
error
Validation failed
phone_e164_format
error
Validation failed
personnummer_luhn_checksum
error
Validation failed
public_key_pem_format
error
Validation failed
preferred_locale_supported_value
warning
Validation failed
deleted_at_only_set_by_admin
error
Validation failed
is_active_false_requires_admin_role
error
Validation failed
Business Rules
unique_email_across_system
No two user records may share the same email address, regardless of auth provider or organizational affiliation. Email is the global unique identifier for deduplication during member system syncs.
soft_delete_only
Users must never be hard-deleted from the database. Deactivation sets is_active=false and deleted_at to the current timestamp. This preserves audit trail integrity for Bufdir reporting and delegation grant records.
public_key_required_for_encrypted_assignments
A user may not receive encrypted assignments until a public_key is registered in their profile. The Key Management Service registers the key on first authenticated login. Coordinators are blocked from dispatching to key-less users.
nda_gate_for_encrypted_content
Users with nda_required=true must have a valid, non-expired NDA agreement before accessing encrypted documents or assignment payloads. The NDA Validation Service gates all decryption requests.
personnummer_only_via_vipps
The personnummer field may only be populated from a verified Vipps SSO token payload. Direct write by client-side code or admin interfaces is prohibited. The field is written exclusively by the Vipps Member ID Sync Service.
last_login_at_updated_on_auth_success
The last_login_at timestamp must be updated on every successful authentication event, across all providers including biometric re-authentication. Used for inactivity analytics and impact summary eligibility.
inactive_users_excluded_from_all_queries
All Supabase RLS policies on the users table and all referencing tables must filter out records where is_active=false or deleted_at IS NOT NULL. Inactive users cannot authenticate, appear in coordinator lists, or receive notifications.
email_verified_required_for_email_auth
Users who registered via email/password must have is_email_verified=true before they can access any protected route. BankID and Vipps users bypass this check as identity is verified by the external provider.
at_least_one_role_assignment_required
Every active user must have at least one corresponding record in user_roles before they can access any feature beyond the organization selection screen. New users without a role are redirected to the no-access screen.
updated_at_auto_maintained
The updated_at column must be updated automatically by a Supabase database trigger on every row modification. Client code must not manually set updated_at to ensure consistency for member system sync conflict resolution.
CRUD Operations
Storage Configuration
Entity Relationships
Each assignment is created and dispatched by a coordinator user
Each enrollment record belongs to the specific user who enrolled in the course
Each delegation grant records the coordinator who performed the proxy registration
Each delegation grant records the peer mentor on whose behalf the activity was registered
Each participant entry may link to a registered user who attended the event
A completed recruitment record links to the newly registered user who signed up via the referral link
Each user badge award is associated with the specific user who earned it
Each user has one accessibility preferences record configuring their WCAG 2.2 AA accessibility settings app-wide
A user registers multiple activity records over their lifecycle as a peer mentor
A peer mentor accrues honorarium threshold records as assignment counts cross configured milestones
A user may have multiple active sessions across different devices and auth providers
A user may have biometric credentials enrolled on multiple devices
A coordinator creates bulk registrations on behalf of multiple peer mentors
A user may hold multiple certifications for different courses with independent validity periods
A user maintains a list of contacts they work with as a peer mentor or coordinator
A peer mentor acting as a volunteer driver receives multiple honorarium records over time
A user may own multiple encrypted documents containing sensitive personal data for assignment delivery
A user creates group event records representing multi-participant activities
A peer mentor receives annual and half-year impact summaries recognizing their volunteer contributions
A user generates referral links and accumulates peer-to-peer recruitment attribution records
A peer mentor may sign multiple NDA agreements as document versions are updated over time
A user receives multiple in-app and push notifications across all scenario categories
Each peer mentor has exactly one extended peer mentor profile linked to their user account
A user manages multiple legal documents such as powers of attorney across their tenure
A user may have push notification configurations registered across multiple devices
Each user has one theme configuration record controlling font scale and contrast theme selection
A user submits multiple travel expense reports over their tenure as a peer mentor
A user may belong to multiple local associations simultaneously across one or more organizations
A user may hold multiple role assignments across different organizational contexts
Each workshop session is created and facilitated by a coordinator user