Contacts
Data Entity
Description
Persons receiving support from peer mentors. Central record connecting activities, notes, caregivers, and relatives within an organization's tenant scope. Sensitive PII (name, phone) is encrypted at the application layer (AES-256-GCM) before storage.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Unique identifier for the contact | PKrequiredunique |
organization_id |
uuid |
Tenant organization that owns this contact record (multi-tenant isolation) | required |
first_name |
string |
Contact's first name. Encrypted at application layer (AES-256-GCM) before persistence. | required |
last_name |
string |
Contact's last name. Encrypted at application layer (AES-256-GCM) before persistence. | required |
display_name |
string |
Searchable / sortable display name derived from first+last. Encrypted at application layer. | - |
phone_number |
string |
Primary contact phone in E.164 format. Encrypted at application layer (AES-256-GCM) before persistence. | - |
email |
string |
Contact email address (optional) | - |
date_of_birth |
datetime |
Date of birth, used for age-based segmentation (especially Barnekreftforeningen) | - |
address_line |
text |
Street address for home visits | - |
postal_code |
string |
Postal code for geographic matching | - |
city |
string |
City for geographic matching and reporting | - |
country_code |
string |
ISO 3166-1 alpha-2 country code; defaults to NO | - |
contact_type |
enum |
Nature of the contact subject (primary case, relative-as-subject, observed family member) | required |
status |
enum |
Lifecycle status of the contact record | required |
assigned_peer_mentor_id |
uuid |
Currently assigned peer mentor (nullable; coordinator-managed) | - |
preferred_language |
string |
BCP-47 language tag for communication preferences (e.g. nb-NO, en-US) | - |
notes_summary |
text |
Short free-text summary visible on the contact card (non-sensitive) | - |
tags |
json |
Free-form tags / categorisation labels (e.g. ['ny', 'hjemmebesok']) | - |
consent_state |
json |
Snapshot of consent flags (data processing, sensitive data dispatch) — authoritative records live in consents table | - |
search_token |
string |
Deterministic blind-index / HMAC token over normalized name+phone used to support encrypted-field search without leaking plaintext | - |
created_by_user_id |
uuid |
User who created the record | required |
created_at |
datetime |
Timestamp of creation (UTC) | required |
updated_at |
datetime |
Timestamp of last update (UTC) | required |
deleted_at |
datetime |
Soft-delete marker; null for active rows | - |
Database Indexes
idx_contacts_organization_id
Columns: organization_id
idx_contacts_org_status
Columns: organization_id, status
idx_contacts_assigned_peer_mentor
Columns: assigned_peer_mentor_id
idx_contacts_search_token
Columns: organization_id, search_token
idx_contacts_postal_code
Columns: organization_id, postal_code
idx_contacts_created_at
Columns: created_at
idx_contacts_deleted_at
Columns: deleted_at
Validation Rules
required_names
error
Validation failed
phone_format_e164
error
Validation failed
email_format
error
Validation failed
postal_code_format
warning
Validation failed
organization_exists
error
Validation failed
assigned_mentor_in_same_org
error
Validation failed
duplicate_detection
warning
Validation failed
date_of_birth_past
error
Validation failed
enum_status_valid
error
Validation failed
Business Rules
tenant_isolation
Contacts MUST belong to an organization and are only visible within that organization's tenant scope. Cross-tenant reads are forbidden.
role_based_access
Only Peer Mentors, Coordinators, and Org Admins (via mobile-as-coordinator) of the owning organization may read contacts. Global Admins require explicit time-bounded support access.
sensitive_field_encryption
Name and phone_number MUST be encrypted at the application layer (AES-256-GCM) before being persisted to the database.
soft_delete_only
Contacts are soft-deleted (deleted_at set). Hard delete is reserved for GDPR erasure requests handled out of band.
auto_unassign_on_mentor_pause
When the assigned peer mentor enters paused status, contacts should be flagged for reassignment by the coordinator.
audit_all_mutations
Every create/update/delete on a contact MUST be recorded in the audit log with actor, timestamp, and field-level diff (excluding plaintext sensitive values).
offline_first_sync
Contact mutations created offline must be staged in the sync outbox and replayed deterministically when connectivity returns.
screen_reader_sensitive_warning
Sensitive contact fields (name, phone, address) must trigger the readout warning before being announced by a screen reader.