mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
Status notes (the per-metric text a model writes) move out of audit_logs into InsightStatusCache: one row per user, metric and locale, the note encrypted at rest, upserted in place, with the input and snapshot fingerprints and a separate negative-cache window. Migration 0344 creates the table and deletes every audit_logs row whose action matches insights.%-status.%. The notes are a regenerable cache and the old rows are plaintext, so nothing is copied; the first nightly run after the upgrade writes them again. Take a backup before applying. The table is registered for key rotation, excluded from backups as a regenerable cache, and deleted by Delete All Data. Refs #975
45 lines
1.9 KiB
SQL
45 lines
1.9 KiB
SQL
-- Status notes move out of the audit log.
|
|
--
|
|
-- The per-metric status notes used to be appended to `audit_logs` as plaintext
|
|
-- JSON, one row per metric per day, next to the security trail. They now live
|
|
-- in their own table, encrypted at rest, one row per (user, metric, locale),
|
|
-- upserted in place.
|
|
--
|
|
-- 1. The new table.
|
|
-- CreateTable
|
|
CREATE TABLE "insight_status_caches" (
|
|
"id" TEXT NOT NULL,
|
|
"user_id" TEXT NOT NULL,
|
|
"metric" TEXT NOT NULL,
|
|
"locale" TEXT NOT NULL,
|
|
"text_encrypted" BYTEA,
|
|
"items_encrypted" BYTEA,
|
|
"input_hash" TEXT,
|
|
"snapshot_hash" TEXT,
|
|
"date_key" TEXT NOT NULL,
|
|
"generated_at" TIMESTAMP(3),
|
|
"retry_at" TIMESTAMP(3),
|
|
"negative_reason" TEXT,
|
|
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updated_at" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "insight_status_caches_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "insight_status_caches_user_id_metric_locale_key" ON "insight_status_caches"("user_id", "metric", "locale");
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "insight_status_caches" ADD CONSTRAINT "insight_status_caches_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- 2. The old rows go. DESTRUCTIVE by design: the notes are a regenerable
|
|
-- cache, nothing reads them from `audit_logs` any more, and leaving them
|
|
-- would keep plaintext health text in a table documented as holding none.
|
|
-- Nothing is copied across, because the old rows are plaintext and a
|
|
-- migration cannot encrypt; the first nightly run after the upgrade writes
|
|
-- every note again. Take a database backup before applying, as for 0339.
|
|
-- Matches exactly the cache keys `insights.<scope>-status.<locale>` (the
|
|
-- seven specialised scopes and the `metric:` / `derived-score:` /
|
|
-- `biomarker:` generic ones); no security-trail action has this shape.
|
|
DELETE FROM "audit_logs" WHERE "action" LIKE 'insights.%-status.%';
|