ADR 0004: Field-level AES-256-GCM for sensitive data

Status: accepted

Decision

Sensitive columns are encrypted in the application with AES-256-GCM before they reach Postgres, transparently through a Drizzle custom type (*_enc columns): CTC figures, recruiter contacts, portal snapshots, stored emails, prep packs, AI cache entries and users' AI keys. Keys are versioned (ENCRYPTION_KEYS=k1:…,k2:…) so they can be rotated.

Job descriptions, notes and screening answers stay plaintext so Postgres full-text search works on them.

Consequences