core PK: id 9 required 1 unique

Description

A person receiving support from a peer mentor within an organization. The display label is overrideable per organization via the Organization Labels system (e.g. 'Familie' for Barnekreftforeningen, 'Bruker' for other orgs). Contacts are the central subject of activities, notes, assignments, and relative linkages. All contact data is organization-scoped and sensitive fields trigger the Sensitive Field Readout Warning on screen-reader-equipped devices.

19
Attributes
6
Indexes
9
Validation Rules
20
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Surrogate primary key, generated on creation. Used as stable reference across offline-created records reconciled via ID mapping service.
PKrequiredunique
organization_id uuid Foreign key to the owning organization. All reads and writes are scoped to this value; cross-org access is never permitted without explicit support-access grant.
required
first_name string Contact's given name. Required for identification and display in contact list and activity logging flows.
required
last_name string Contact's family name. Combined with first_name for full-text search and list display.
required
date_of_birth datetime Contact's date of birth. Sensitive field — triggers screen-reader warning when displayed. Used for age-based context in formalized home-visit reports.
-
phone string Primary phone number. Sensitive field — triggers readout warning. Used for coordinator outreach and assignment dispatch. Norwegian E.164 format preferred.
-
email string Email address for contact. Sensitive field. Optional as many contacts are not digitally active.
-
address_line1 string Street address, first line. Sensitive field — used in encrypted assignment dispatch (Blindeforbundet). Triggers readout warning.
-
address_line2 string Street address, second line (apartment, care facility, floor). Optional supplement to address_line1.
-
postal_code string Norwegian postal code (4 digits). Used for geographic matching of peer mentors to contacts (Blindeforbundet) and regional reporting.
-
city string City or municipality derived from or paired with postal_code. Supports geographic display and match logic.
-
gender enum Contact's gender. Used in anonymized Bufdir statistics aggregation and demographic reporting. Optional to respect privacy.
-
language_preference enum Preferred communication language. Drives Sami language support routing and notification language selection.
-
has_sensitive_data boolean Flags that this contact record contains sensitive personal information (medical summary, care context, etc). When true, all rendered fields are wrapped by the Sensitive Field Warning Widget on screen-reader devices.
required
external_id string Identifier from an external member system (e.g. NHF, HLF membership registry). Enables deduplication and future sync with member systems. Scoped within organization — not globally unique.
-
is_active boolean Soft-delete flag. Inactive contacts are hidden from contact list and cannot receive new activities or assignments. Historical records are preserved.
required
created_by uuid Foreign key to the user who registered this contact. Used in audit trail and proxy-reporting context where a coordinator creates contacts on behalf of peer mentors.
required
created_at datetime UTC timestamp of record creation. Set on insert, never updated.
required
updated_at datetime UTC timestamp of last modification. Updated on any field change.
required

Database Indexes

idx_contacts_org_id
btree

Columns: organization_id

idx_contacts_org_name
btree

Columns: organization_id, last_name, first_name

idx_contacts_org_active
btree

Columns: organization_id, is_active

idx_contacts_external_id
btree

Columns: organization_id, external_id

idx_contacts_created_by
btree

Columns: created_by

idx_contacts_created_at
btree

Columns: organization_id, created_at

Validation Rules

first_name_not_empty error

Validation failed

last_name_not_empty error

Validation failed

valid_organization_reference error

Validation failed

valid_created_by_reference error

Validation failed

email_format error

Validation failed

postal_code_format error

Validation failed

date_of_birth_in_past error

Validation failed

language_preference_enum_constraint error

Validation failed

gender_enum_constraint error

Validation failed

Business Rules

org_scoped_access
always

A user may only access contacts belonging to their own organization. The API enforces organization_id filtering on every query. Global Admins require a time-bounded support access grant from Organization Settings before they can read org contact data.

soft_delete_only
on_delete

Contacts are never hard-deleted. Setting is_active=false hides the record from all UI surfaces and prevents new activities, assignments, or notes. Historical associations (activities, notes) remain intact for audit and Bufdir reporting.

no_new_activity_on_inactive_contact
on_create

Activity logging (quick log, wizard, proxy, bulk) is blocked when the selected contact has is_active=false. The activity wizard UI must not render inactive contacts in the contact picker.

sensitive_field_readout_warning
always

When has_sensitive_data=true or when specific sensitive fields (phone, date_of_birth, address_line1) are rendered on screen, the Sensitive Field Warning Widget is mounted to alert screen-reader users before the value is read aloud. This is required for WCAG 2.2 AA compliance and NHF's explicit request.

coordinator_write_peer_mentor_read
always

Peer mentors can view contacts they are linked to via activities or assignments. Coordinators can create, update, and soft-delete contacts within their organization. Org Admins inherit coordinator access on mobile.

unique_external_id_within_org
on_create

If external_id is provided, it must be unique within the organization. This prevents duplicate contact records when syncing with external member registries (NHF, HLF).

offline_optimistic_mutation
on_create

Contact creates and edits are applied optimistically in the local Drift database and queued in the mutation outbox. On sync, the conflict resolver determines whether the server version or local version wins, with last-write-wins for non-structural fields and coordinator-wins for is_active.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
No Partitioning
Retention
Permanent Storage