core PK: id 12 required 1 unique

Description

Encrypted sensitive data dispatch from coordinators to peer mentors, containing personal information such as name, address, and medical summaries (epikrise). Supports delivery confirmation, read confirmation, status tracking, and threshold-based honorarium counting.

19
Attributes
5
Indexes
6
Validation Rules
14
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Primary key, globally unique assignment identifier
PKrequiredunique
organization_id uuid Foreign key to organizations table — enforces tenant isolation so assignments are never visible across organization boundaries
required
recipient_user_id uuid Foreign key to users table — the peer mentor who receives and acts on this assignment
required
dispatched_by_user_id uuid Foreign key to users table — the coordinator who created and dispatched this assignment
required
title string Non-sensitive short label for the assignment used in list views and notifications (e.g. 'Home visit — Oslo East'). Must not contain PII.
required
encrypted_payload text AES-256-GCM encrypted JSON blob containing the sensitive personal data: full name, address, phone, and medical summary (epikrise). Decrypted client-side using the resolved key from secure-key-store.
required
encryption_key_id string Reference identifier for the symmetric key in secure-key-store used to encrypt this payload. Required for key rotation and re-encryption workflows.
required
status enum Lifecycle state of the assignment. Transitions: pending → delivered → read → completed. cancelled and expired are terminal states.
required
priority enum Dispatch urgency. urgent assignments surface above normal in the recipient inbox and may bypass quiet-hours notification rules.
required
contact_deadline_days integer Number of days after dispatch before an automatic reminder is sent if no contact has been established. Defaults to 10 per Blindeforbundet specification.
-
dispatched_at datetime Timestamp when the coordinator finalized and dispatched the assignment. Immutable after set.
required
delivered_at datetime Timestamp when the recipient's device first downloaded and decrypted the assignment payload. Populated by assignment-dispatch-service on first successful payload fetch.
-
read_at datetime Timestamp when the recipient explicitly confirmed they have read the assignment (distinct from delivery). Triggers a read receipt event consumed by threshold-tracking-service.
-
completed_at datetime Timestamp when the peer mentor marked the assignment as completed (contact established and follow-up done).
-
expires_at datetime Optional hard expiry timestamp. After this point the encrypted payload is no longer decryptable and status transitions to expired. Supports GDPR data minimisation.
-
reminder_sent_at datetime Timestamp when the automatic reminder notification was sent after contact_deadline_days elapsed without completion. Null if reminder not yet triggered.
-
coordinator_notes text Non-sensitive context notes written by the coordinator at dispatch time, visible only to the recipient and the dispatching coordinator. Must not duplicate PII already in encrypted_payload.
-
created_at datetime Row creation timestamp. Set by the database on insert.
required
updated_at datetime Row last-modified timestamp. Updated on every status transition or field change.
required

Database Indexes

idx_assignments_recipient_user_id
btree

Columns: recipient_user_id

idx_assignments_organization_status
btree

Columns: organization_id, status

idx_assignments_dispatched_by_user_id
btree

Columns: dispatched_by_user_id

idx_assignments_dispatched_at
btree

Columns: dispatched_at

idx_assignments_status_reminder
btree

Columns: status, reminder_sent_at, dispatched_at

Validation Rules

title_no_pii error

Validation failed

encryption_key_id_exists error

Validation failed

recipient_is_active_peer_mentor error

Validation failed

valid_status_transition error

Validation failed

expires_at_in_future error

Validation failed

contact_deadline_days_positive error

Validation failed

Business Rules

payload_must_be_encrypted_before_storage
on_create

The sensitive_payload field must be encrypted by encryption-service using AES-256-GCM before the row is written to the database. Plaintext personal data must never reach the assignments table.

only_coordinator_can_dispatch
on_create

Only users with the Coordinator role within the same organization may create assignments. Peer Mentors and Organization Admins cannot dispatch assignments.

recipient_must_belong_to_same_organization
on_create

The recipient_user_id must resolve to a user who is an active member of the same organization as the dispatching coordinator. Cross-organization assignment dispatch is forbidden.

assignment_immutable_after_dispatch
on_update

Once dispatched_at is set and status leaves 'pending', the encrypted_payload, recipient_user_id, and dispatched_by_user_id fields cannot be modified. Status and timestamp fields are the only mutable columns after dispatch.

automatic_reminder_after_deadline
always

If status remains 'delivered' or 'read' (but not 'completed') for contact_deadline_days days after dispatched_at, assignment-reminder-service sends a push notification to the recipient and sets reminder_sent_at. Only one reminder per assignment.

threshold_honorarium_counting
on_update

Each time an assignment transitions to 'completed', threshold-tracking-service increments the recipient's completed-assignment count for the current period. The 3rd completed assignment triggers office honorarium eligibility; the 15th triggers a higher honorarium rate. Counts are scoped per organization and per reporting period.

expired_payload_inaccessible
always

When the current timestamp exceeds expires_at, the encryption key for this assignment must be revoked in secure-key-store. Subsequent read attempts receive an 'assignment expired' error without exposing any PII.

audit_all_access
always

Every read of the assignment payload (decryption event) must be recorded in audit-logs-table with user_id, assignment_id, timestamp, and action='payload_decrypted'. This satisfies GDPR access logging requirements for sensitive personal data.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
by_date
Retention
archive_after_1year