Contact
Data Entity
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.
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
Columns: organization_id
idx_contacts_org_name
Columns: organization_id, last_name, first_name
idx_contacts_org_active
Columns: organization_id, is_active
idx_contacts_external_id
Columns: organization_id, external_id
idx_contacts_created_by
Columns: created_by
idx_contacts_created_at
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
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
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
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
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
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
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
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.