Chapter 33 · Volume IV — Runtime Subsystems

Data Privacy & GDPR

33.1 Overview

ADL provides built-in privacy compliance features for GDPR, CCPA, HIPAA, and FERPA. The system supports field-level privacy classification, data subject rights (access, erasure, portability, rectification), consent management, retention policies, and encryption at rest.

Privacy is declared at the field level and enforced by the runtime. The privacy configuration is the data map. The anonymization rules are the erasure procedure. The consent configuration is the processing control.


33.2 Privacy Classification

Privacy is configured at the domain level and applied to individual fields.

Domain Configuration

domain:
  name: clinicalTrial
  version: "1.0.0"

  privacy:
    enabled: true
    
    classifications:
      personalData:
        description: "Standard personal data"
        retention: 7 years
      sensitiveData:
        description: "Special category data (GDPR Art. 9)"
        retention: 30 years
      financialData:
        description: "Financial and payment information"
        retention: 10 years
    
    subjectIdentifier:
      primary: email
      alternates: [subjectId, ssn, participantNumber]
    
    anonymization:
      method: anonymize
      rules:
        default: "Redacted"
        dateOfBirth: "$fuzzyDate(5 years)"
        diagnosis: "$preserve"

Field-Level Privacy

resources:
  Participant:
    object:
      firstName:
        type: string
        required: true
        privacy:
          classification: personalData
          pii: true
      
      email:
        type: string
        required: true
        privacy:
          classification: personalData
          pii: true
          subjectIdentifier: true
      
      dateOfBirth:
        type: date
        privacy:
          classification: sensitiveData
          pii: true
      
      medicalHistory:
        type: text
        privacy:
          classification: sensitiveData
          sensitive: true
          phi: true
      
      ssn:
        type: string
        privacy:
          classification: financialData
          pii: true
          encrypted: true

Privacy Field Properties

PropertyTypeDescription
classificationstringPrivacy category from domain classifications
piibooleanPersonally Identifiable Information flag
sensitivebooleanSpecial category / sensitive data (GDPR Art. 9)
phibooleanProtected Health Information (HIPAA)
encryptedbooleanEncrypt field at rest
subjectIdentifierbooleanThis field identifies the data subject

33.3 Data Subject Rights APIs

Right of Access (GDPR Art. 15)

GET /api/v1/{domain}/privacy/subject/{identifier}
    ?format=json

Returns all data for the subject across all resources:

{
  "code": 200,
  "data": {
    "subject": "alice@example.com",
    "domain": "clinicalTrial",
    "generatedAt": "2026-05-17T14:30:00Z",
    "resources": {
      "Participant": {
        "count": 1,
        "fields": {
          "personalData": ["email", "firstName", "lastName", "phone"],
          "sensitiveData": ["dateOfBirth", "medicalHistory", "diagnosis"],
          "financialData": ["ssn"]
        },
        "records": [
          {
            "id": "a1b2c3d4...",
            "email": "alice@example.com",
            "firstName": "Alice",
            "lastName": "Johnson",
            "enrollmentDate": "2025-06-15",
            "status": "active"
          }
        ]
      },
      "AdverseEvent": {
        "count": 2,
        "records": [...]
      }
    },
    "audit": {
      "count": 47,
      "note": "47 audit records reference this subject."
    },
    "history": {
      "count": 12,
      "note": "12 history events reference this subject."
    }
  }
}

The runtime traverses every resource, queries for records where any field marked subjectIdentifier: true matches the identifier, and returns the complete data profile.

Right of Erasure (GDPR Art. 17)

POST /api/v1/{domain}/privacy/subject/{identifier}/erase
{
  "method": "anonymize",
  "reason": "Subject request — GDPR Art. 17",
  "retainAudit": true,
  "retainHistory": true,
  "excludeResources": ["ConsentRecord"],
  "dryRun": false
}

Dry run preview:

{
  "code": 200,
  "data": {
    "dryRun": true,
    "subject": "alice@example.com",
    "affectedResources": {
      "Participant": {
        "records": 1,
        "fieldsAnonymized": 8
      },
      "AdverseEvent": {
        "records": 2,
        "fieldsAnonymized": 3
      }
    },
    "auditRecords": {
      "count": 47,
      "action": "anonymize subject references"
    },
    "blockers": []
  }
}

Execution performs erasure in a transaction:

  1. For each resource with matching records, apply the anonymization method
  2. Anonymize audit records (retain change data, anonymize actor)
  3. Anonymize history records (retain event labels, anonymize actor)
  4. Record a privacyErasure event in the privacy log
  5. Record a history event

Legal holds block erasure until resolved:

{
  "blockers": [
    {
      "resource": "AdverseEvent",
      "recordId": "ae-2026-001",
      "reason": "Active regulatory filing — ICH E2B retention",
      "regulation": "21 CFR §314.80"
    }
  ]
}

If blockers exist and dryRun: false, returns HTTP 409 Conflict.

Right of Portability (GDPR Art. 20)

GET /api/v1/{domain}/privacy/subject/{identifier}/export
    ?format=json

Returns the same data as the access endpoint in a machine-readable, portable format for transfer to another controller. CSV format produces one file per resource.

Right of Rectification (GDPR Art. 16)

PATCH /api/v1/{domain}/privacy/subject/{identifier}/rectify
{
  "resource": "Participant",
  "recordId": "a1b2c3d4...",
  "corrections": {
    "email": "alice.johnson@newdomain.com",
    "phone": "+1-555-0199"
  },
  "reason": "Subject request — updated contact information"
}

Applies corrections through the standard update path (respecting permissions and validation) and records a privacyRectification history event.

Right to Restrict Processing (GDPR Art. 18)

POST /api/v1/{domain}/privacy/subject/{identifier}/restrict
{
  "reason": "Subject contest accuracy — GDPR Art. 18(1)(a)",
  "restrictedOperations": ["update", "delete", "transition"],
  "allowedOperations": ["read"]
}

Places a processing lock on the subject’s records. The runtime checks the restriction before every write operation. Read access continues.

Lift restriction:

POST /api/v1/{domain}/privacy/subject/{identifier}/unrestrict
{
  "reason": "Accuracy verified — restriction lifted"
}

33.4 Anonymization Methods

The anonymization block defines how to handle erasure requests.

Three Methods

MethodBehavior
anonymizeReplace PII fields with redaction placeholders or anonymization functions
pseudonymizeReplace PII with consistent pseudonyms (same pseudonym across all resources for the same subject)
deleteHard-delete records (use with caution — may break referential integrity)

Anonymization Rules

anonymization:
  method: anonymize
  rules:
    default: "Redacted"
    firstName: "Redacted"
    lastName: "Redacted"
    email: "{$pseudonym}@redacted.local"
    dateOfBirth: "$fuzzyDate(5 years)"
    diagnosis: "$preserve"
    studyId: "$preserve"

Anonymization functions:

FunctionDescription
RedactedFixed replacement string
$fuzzyDate(offset)Shift date by offset (e.g., 5 years) instead of deleting
$pseudonymGenerate consistent pseudonym for this subject
$hash6First 6 chars of SHA-256 hash
$preserveDo NOT anonymize (keep for research/integrity)

Pseudonym Mapping

When method: pseudonymize, the runtime maintains a mapping table:

CREATE TABLE {domain}_pseudonym_map (
    subject_identifier  TEXT PRIMARY KEY,
    pseudonym           TEXT NOT NULL,
    created_at          TEXT NOT NULL,
    salt                TEXT NOT NULL
);

This enables re-identification if legally required. The table should be encrypted at rest and access-restricted to the privacy officer.


33.5 Encryption at Rest

Fields marked encrypted: true are encrypted before storage and decrypted on read:

privacy:
  encryption:
    provider: aes256gcm
    keySource: environment
    keyVariable: "${ENCRYPTION_KEY}"
    keyRotation: 365 days

The runtime uses AES-256-GCM. Key rotation creates a new key and re-encrypts all encrypted fields in a background task. The old key is retained for a configurable period for disaster recovery.


privacy:
  consent:
    - purpose: primary_treatment
      description: "Treatment and care"
      required: true
      withdrawable: false
    
    - purpose: secondary_research
      description: "Future research studies"
      required: false
      withdrawable: true
      resources: [Participant, AdverseEvent, LabResult]

Grant consent:

POST /api/v1/{domain}/privacy/subject/{identifier}/consent/grant
{
  "purpose": "secondary_research",
  "grantedBy": "subject",
  "evidence": "Signed ICF-2026-001"
}

Withdraw consent:

POST /api/v1/{domain}/privacy/subject/{identifier}/consent/withdraw
{
  "purpose": "secondary_research",
  "reason": "Subject no longer wishes to participate"
}

When consent is withdrawn for a purpose marked withdrawable: true, the runtime:

  1. Records the withdrawal in the consent table
  2. Evaluates which resources are processed under that purpose
  3. Applies anonymization rules to resources processed solely under that purpose
  4. Records a history event

Consent for purposes marked required: true cannot be withdrawn.


33.7 Data Retention Policies

privacy:
  retention:
    - category: personalData
      duration: 7 years
      action: anonymize
      from: lastActivity
    
    - category: sensitiveData
      duration: 30 years
      action: archive
      from: recordCreation
    
    - category: financialData
      duration: 10 years
      action: delete
      from: lastActivity
PropertyDescription
categoryPrivacy classification name
durationRetention period (e.g., 7 years, 90 days)
actionWhat to do when expired: anonymize, archive, delete
fromStart date: recordCreation, lastActivity, lastUpdate

Retention Enforcement

The retention enforcement runs as a scheduled task. For each category:

  1. Query records where from date + duration < now
  2. Apply the configured action
  3. Record a history event for each affected record
  4. Log a privacy log entry
POST /api/v1/{domain}/privacy/legal-hold
{
  "resource": "AdverseEvent",
  "recordId": "ae-2026-001",
  "reason": "Active regulatory filing",
  "regulation": "21 CFR §314.80",
  "expiresAt": "2027-12-31"
}

Legal holds prevent retention enforcement and erasure requests from processing the record until the hold is released.


33.8 Privacy Log

All privacy operations are logged to {domain}_privacy_log:

CREATE TABLE {domain}_privacy_log (
    id              TEXT PRIMARY KEY,
    eventType       TEXT NOT NULL,
    subjectIdentifier TEXT NOT NULL,
    performedBy     TEXT NOT NULL,
    performedAt     TEXT NOT NULL,
    reason          TEXT,
    affectedResources TEXT,
    detail          TEXT
);
Event TypeDescription
subjectAccessRight of access request
subjectExportRight of portability request
subjectErasureRight of erasure executed
subjectRectificationData corrected
processingRestrictionProcessing restricted
consentGrantedConsent granted for purpose
consentWithdrawnConsent withdrawn
retentionEnforcedRetention policy applied
legalHoldAppliedLegal hold placed

33.9 Auto-Generated Data Map

GET /api/v1/{domain}/privacy/data-map

Returns the complete privacy data map:

{
  "domain": "clinicalTrial",
  "generatedAt": "2026-05-17T14:30:00Z",
  "resources": {
    "Participant": {
      "personalData": ["firstName", "lastName", "email", "phone"],
      "sensitiveData": ["dateOfBirth", "medicalHistory", "diagnosis"],
      "financialData": ["ssn"],
      "subjectIdentifiers": ["email"]
    }
  },
  "retentionPolicies": [...]
}

This is the GDPR Article 30 record of processing activities — automatically generated from the schema, always current, never out of date.


33.10 Integration Points

FeatureIntegration
History (§21)Privacy operations produce history events; erasure anonymizes actor references in history
Audit (§8)Privacy operations are audited; erasure anonymizes actor in audit records
Schedules (§24)Retention enforcement runs as scheduled task
Validation (§14)Rectification requests are validated before applying corrections
Permissions (§11)Privacy APIs are permission-gated; typically restricted to privacy officers
EncryptionField-level encryption integrates with storage layer

End of Chapter 33.

Next: Chapter 34 — Localization & i18n