09 — Consent & Compliance Layer¶
GDPR-First Design¶
Designing for GDPR ensures compliance with HIPAA, India DPDP Act, UAE data protection by default.
Consent Management¶
Consent Purposes¶
| Purpose | Required For | Default |
|---|---|---|
clinical_data_processing |
Any clinical data handling | Required |
cross_border_transfer |
Sending data to destination country | Required |
provider_sharing |
Sharing records with matched providers | Required |
analytics |
De-identified analytics and reporting | Optional |
sms_transactional |
SMS notifications | Optional |
sms_marketing |
Marketing communications | Optional |
Consent Rules¶
- Records are immutable — new versions created, never updated
- Processing blocked without active consent for relevant purpose
- Consent expiry tracked with 30-day automated warnings
- Separate consent versions per privacy policy version
Consent Schema¶
CREATE TABLE consent_records (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
patient_id UUID NOT NULL REFERENCES patients(id),
tenant_id VARCHAR(100) NOT NULL,
purpose VARCHAR(50) NOT NULL,
granted BOOLEAN NOT NULL,
policy_version VARCHAR(20) NOT NULL,
ip_address VARCHAR(45),
user_agent TEXT,
expires_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW()
-- No updated_at: immutable records
);
Data Classification¶
| Classification | Examples | Protection |
|---|---|---|
| PII | Name, email, phone, passport | Field-level encryption at rest, audit-logged access |
| PHI | Medical records, diagnoses, imaging | Field-level encryption, tenant-isolated, consent-gated |
| Operational | Preferences, language, budget | Standard encryption, tenant-scoped |
Data Subject Request Handler (GDPR Article 17)¶
Cascade delete across all data stores: 1. PostgreSQL: patient records, FHIR resources, events, consent, documents 2. Neo4j: patient node and all relationships 3. Qdrant: patient embeddings 4. R2: all uploaded files for this patient 5. Redis: cached data
Generates deletion certificate with affected record counts.
Audit Logging¶
CREATE TABLE audit_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
actor_id VARCHAR(100) NOT NULL,
action VARCHAR(50) NOT NULL, -- 'read', 'create', 'update', 'delete', 'export'
resource_type VARCHAR(50) NOT NULL,
resource_id VARCHAR(100),
tenant_id VARCHAR(100) NOT NULL,
ip_address VARCHAR(45),
user_agent TEXT,
correlation_id VARCHAR(100),
details JSONB,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Append-only. Super admins cannot delete.