Files
brain/db/migrations/001_legacy_additive.sql
Andrew S Erwin b9721ff13f
release gate / check (push) Failing after 8m35s
initial commit on Federted servers
2026-10-19 16:23:55 -05:00

69 lines
4.1 KiB
SQL

-- 001_legacy_additive.sql — additive upgrades historically shipped as
-- db/upgrade.sql, adopted into the ordered ledger (review MIG-01).
-- Idempotent: every statement is guarded by an existence check, so first
-- ledger adoption on an already-upgraded database is a no-op. From ledger
-- adoption onward recorded migrations are immutable; new changes go into
-- new numbered files. The runner (db/migrate.sh) applies each file in its
-- own transaction with ON_ERROR_STOP.
-- Review MIG-02: report orphaned bookmark->contact references with an
-- actionable error before adding the foreign key, instead of failing with a
-- bare constraint violation. Never erase relationships silently — repair is
-- a deliberate operator decision.
DO $$
DECLARE orphans bigint;
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname='Bookmark_contactId_fkey' AND conrelid='"Bookmark"'::regclass) THEN
SELECT count(*) INTO orphans FROM "Bookmark" b
WHERE b."contactId" IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM "Contact" c WHERE c.id=b."contactId");
IF orphans > 0 THEN
RAISE EXCEPTION 'migration 001: % bookmark(s) reference missing Contact rows; repair them deliberately (e.g. UPDATE "Bookmark" SET "contactId"=NULL WHERE "contactId" IS NOT NULL AND NOT EXISTS (SELECT 1 FROM "Contact" c WHERE c.id="Bookmark"."contactId")) and re-run', orphans;
END IF;
ALTER TABLE "Bookmark" ADD CONSTRAINT "Bookmark_contactId_fkey" FOREIGN KEY ("contactId") REFERENCES "Contact"(id) ON DELETE SET NULL;
END IF;
END $$;
-- Bring pre-port mailbox switches into the background signal scheduler.
-- Existing sources (including paused watches) and modern watchers are preserved.
INSERT INTO "SignalSource"(id,type,config,enabled,"bookmarkId","ownerId")
SELECT 'legacy-'||b.id,'email',json_build_object('subject',COALESCE(b."imapQuery",''),'legacy',true),true,b.id,b."ownerId"
FROM "Bookmark" b
WHERE b."imapWatchEnabled" AND NOT EXISTS (
SELECT 1 FROM "SignalSource" s WHERE s."bookmarkId"=b.id AND s."ownerId"=b."ownerId" AND s.config->>'legacy'='true'
)
ON CONFLICT(id) DO NOTHING;
CREATE INDEX IF NOT EXISTS "Bookmark_ownerId_updatedAt_id_idx" ON "Bookmark"("ownerId","updatedAt" DESC,id DESC);
-- Revocable sessions: cookie JWTs embed this version; signout bumps it.
ALTER TABLE "User" ADD COLUMN IF NOT EXISTS "tokenVersion" integer NOT NULL DEFAULT 1;
-- Query-pattern indexes: shared-date visibility join and the alerts poll.
CREATE INDEX IF NOT EXISTS "SharedDate_creatorId_recipientId_date_idx" ON "SharedDate"("creatorId","recipientId",date);
CREATE INDEX IF NOT EXISTS "Bookmark_ownerId_alertAt_unsent_idx" ON "Bookmark"("ownerId","alertAt") WHERE NOT "alertSent";
-- Prisma's Json maps to jsonb; enables GIN indexing and dedups keys.
-- Re-running on an already-jsonb column is a validated no-op.
ALTER TABLE "SignalSource" ALTER COLUMN config TYPE jsonb USING config::jsonb;
-- Optimistic concurrency for page saves (review DATA-01): content saves bump
-- this revision and a stale base version in PATCH is rejected with 409.
ALTER TABLE "Page" ADD COLUMN IF NOT EXISTS version integer NOT NULL DEFAULT 1;
-- Durable per-source mailbox ingestion checkpoints (review SYNC-02): polls
-- process only UIDs newer than lastUid and advance only after durable inserts.
CREATE TABLE IF NOT EXISTS "SignalCheckpoint" (
"sourceId" text PRIMARY KEY REFERENCES "SignalSource"(id) ON DELETE CASCADE,
"uidValidity" bigint NOT NULL,
"lastUid" bigint NOT NULL,
"updatedAt" timestamptz NOT NULL DEFAULT now()
);
-- One-shot administrator bootstrap state (review AUTH-06): once recorded,
-- signup never auto-promotes again; recovery is operator-driven.
CREATE TABLE IF NOT EXISTS "AppSetting" (
key text PRIMARY KEY,
value jsonb NOT NULL DEFAULT '{}',
"updatedAt" timestamptz NOT NULL DEFAULT now()
);
-- Installations that already have a qualifying administrator completed
-- bootstrap before this ledger existed; record it so demoting that
-- administrator cannot re-open first-signup promotion.
INSERT INTO "AppSetting"(key,value)
SELECT 'adminBootstrap',jsonb_build_object('completed',true)
WHERE EXISTS (SELECT 1 FROM "User" WHERE role='ADMIN' AND email NOT LIKE '%@example.com')
ON CONFLICT(key) DO NOTHING;