mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
Merge branch 'wave/v125-sec' into release/v1.25.0
This commit is contained in:
commit
52e8dab3d7
27 files changed
+1111
-60
No files matched your search
@@ -0,0 +1,35 @@
|
||||
-- v1.25 — encrypt medication free-text notes at rest.
|
||||
--
|
||||
-- Adds the AES-256-GCM ciphertext columns for the three medication
|
||||
-- free-text fields that were still plaintext: the side-effect note
|
||||
-- (`medication_side_effects.notes`), the dose-change titration note
|
||||
-- (`medication_dose_changes.note`), and the inventory-item note
|
||||
-- (`medication_inventory_items.notes`). These were the last plaintext
|
||||
-- PHI columns left after the v1.23 note-encryption rollout.
|
||||
--
|
||||
-- STORAGE CONVENTION: Bytes (`bytea`), matching the dominant free-text
|
||||
-- encrypted-note convention already in the schema (mood_entries.note_
|
||||
-- encrypted, measurements.notes_encrypted, illness_day_logs.note_encrypted,
|
||||
-- labs.note_encrypted, coach_*.{...}_encrypted) — the `encrypt()`
|
||||
-- ciphertext string stored UTF-8 as `bytea`, the shape the rotation
|
||||
-- script's `rotateBytesColumn` already covers. All three columns are
|
||||
-- registered in ENCRYPTED_COLUMNS + the rotation script in the same change.
|
||||
--
|
||||
-- This migration is ADDITIVE ONLY. The legacy plaintext columns
|
||||
-- (`medication_side_effects.notes`, `medication_dose_changes.note`,
|
||||
-- `medication_inventory_items.notes`) are intentionally NOT dropped here:
|
||||
-- an idempotent, transactional, fail-closed boot-time job encrypts the
|
||||
-- existing rows (plaintext -> ciphertext, then nulls the plaintext) so the
|
||||
-- read path can fall back to plaintext for not-yet-migrated rows. Dropping
|
||||
-- the plaintext columns is a deliberate FOLLOW-UP release, once the backfill
|
||||
-- reports zero remaining plaintext-but-no-ciphertext rows — the same
|
||||
-- boundary the encryption-key-rotation playbook uses before dropping a
|
||||
-- legacy key.
|
||||
ALTER TABLE "medication_side_effects"
|
||||
ADD COLUMN IF NOT EXISTS "notes_encrypted" BYTEA;
|
||||
|
||||
ALTER TABLE "medication_dose_changes"
|
||||
ADD COLUMN IF NOT EXISTS "note_encrypted" BYTEA;
|
||||
|
||||
ALTER TABLE "medication_inventory_items"
|
||||
ADD COLUMN IF NOT EXISTS "notes_encrypted" BYTEA;
|
||||
@@ -2310,6 +2310,10 @@ model MedicationDoseChange {
|
||||
/// User-entered titration note ("stepped up after 4 weeks on 5 mg,
|
||||
/// tolerated 7.5 mg with mild nausea day 2").
|
||||
note String?
|
||||
/// v1.25 — AES-256-GCM ciphertext for `note`. The plaintext column
|
||||
/// stays for read-fallback until the backfill reports zero remaining
|
||||
/// rows; the plaintext drop is DEFERRED to a later release.
|
||||
noteEncrypted Bytes? @map("note_encrypted")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
medication Medication @relation(fields: [medicationId], references: [id], onDelete: Cascade)
|
||||
@@ -2401,6 +2405,10 @@ model MedicationInventoryItem {
|
||||
purchasedAt DateTime? @map("purchased_at")
|
||||
/// Free-text note, application-layer max 200 chars.
|
||||
notes String?
|
||||
/// v1.25 — AES-256-GCM ciphertext for `notes`. The plaintext column
|
||||
/// stays for read-fallback until the backfill reports zero remaining
|
||||
/// rows; the plaintext drop is DEFERRED to a later release.
|
||||
notesEncrypted Bytes? @map("notes_encrypted")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@@ -2457,6 +2465,10 @@ model MedicationSideEffect {
|
||||
/// application layer. The DB column is unbounded TEXT for
|
||||
/// consistency with sibling "notes" columns on this schema.
|
||||
notes String?
|
||||
/// v1.25 — AES-256-GCM ciphertext for `notes`. The plaintext column
|
||||
/// stays for read-fallback until the backfill reports zero remaining
|
||||
/// rows; the plaintext drop is DEFERRED to a later release.
|
||||
notesEncrypted Bytes? @map("notes_encrypted")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
Reference in new issue
Block a user