core PK: id 9 required 1 unique

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.

24
Attributes
7
Indexes
9
Validation Rules
21
CRUD Operations

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
btree

Columns: organization_id

idx_contacts_org_status
btree

Columns: organization_id, status

idx_contacts_assigned_peer_mentor
btree

Columns: assigned_peer_mentor_id

idx_contacts_search_token
btree

Columns: organization_id, search_token

idx_contacts_postal_code
btree

Columns: organization_id, postal_code

idx_contacts_created_at
btree

Columns: created_at

idx_contacts_deleted_at
btree

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
always

Contacts MUST belong to an organization and are only visible within that organization's tenant scope. Cross-tenant reads are forbidden.

role_based_access
always

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
always

Name and phone_number MUST be encrypted at the application layer (AES-256-GCM) before being persisted to the database.

soft_delete_only
on_delete

Contacts are soft-deleted (deleted_at set). Hard delete is reserved for GDPR erasure requests handled out of band.

Enforced by: Contact Service
auto_unassign_on_mentor_pause
on_update

When the assigned peer mentor enters paused status, contacts should be flagged for reassignment by the coordinator.

audit_all_mutations
always

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
always

Contact mutations created offline must be staged in the sync outbox and replayed deterministically when connectivity returns.

screen_reader_sensitive_warning
always

Sensitive contact fields (name, phone, address) must trigger the readout warning before being announced by a screen reader.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
No Partitioning
Retention
Permanent Storage