Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
238 changes: 238 additions & 0 deletions docs/audit/live-drift-forensics-2026-08.md

Large diffs are not rendered by default.

35 changes: 19 additions & 16 deletions docs/database-drift-detection.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -123,22 +123,25 @@ How `check:drift` treats it (`scripts/check-drift.ts`):
repo-ahead mechanism, not a special case. Deployment is a separately approved
production migration window (plan approval map, Phase 6.1, after Phase 4).

**Expected first live run after deployment.** Only five versions are seeded in
the allowlist (below); the remaining §1.1 rows — `20260701040000
drop_dead_drifted_hybrid_variants`, `20260702100000
add_claim_ingestion_jobs_comment`, `20260702110000 drop_redundant_indexes`,
`20260702120000 rag_retrieval_logs_retention`, `20260702130000
storage_cleanup_jobs_document_fk`, `20260702140000
fix_reset_document_index_duplicate`, `20260702150000
documents_owner_covering_index`, `20260702160000 fix_invoke_agent_url_to_guc`,
`20260702180000 promote_index_generation_id_columns`, and the 2026-07-12 batch
`20260712165915`…`20260712173000` — have **no repo-provable guard** and will be
reported as findings. That is the intended behaviour ("a history-repair row
without a validating guard migration becomes permanent, visible drift"); the
follow-up is to author fail-fast guard migrations for them (Phase 4.4 batches
cover the index ones) and allowlist each with a `validation` guard, not to
allowlist them bare. Versions the live probe does not report surface as stale
entries, which is how a wrong seed is caught.
**Live state after Phase 6.2 (2026-08-19).** The probe went live on production on
2026-08-18 (forensics §3.7) and reported exactly twenty no-statements rows: the
2026-07-01…07-02 cluster and the 2026-07-12 batch of §1.1. All twenty are now
covered — five seeded `superseded` entries (`20260701010000`, `020000`, `030000`,
`060000`, `20260702000000`) and fifteen `validation` entries pointing at the six
Phase 6.2 guard migrations `20260819110000`…`20260819110500` (dropped objects,
comments + retention cron, document foreign keys, operational index shapes, the
`index_generation_id` promotion, function bodies; see forensics §"6.2
completion" for the per-version classification). Those guards were applied to
production by a real `supabase db push` and to staging by the Phase 2 method, so
their own history rows carry statements and can never themselves surface in the
probe. **Any `[migration_history] no_statements` line from now on is therefore
new history repair**, not known backlog: it means someone marked a version
applied without executing it and without shipping a guard — the exact event the
contract forbids. Treat it as a P1 finding: author the guard first, never
allowlist bare. Versions the live probe does not report surface as stale
entries, which is how a wrong seed is caught; against staging every
`migration_history` entry reads stale by design (staging's chain was replayed
with statements), so never run `--prune-stale` there.

## Guard-migration contract

Expand Down
6 changes: 4 additions & 2 deletions docs/database-remediation-coordination.md

Large diffs are not rendered by default.

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
{
"version": 2,
"id": "bbac85a9-de92-42c5-b9e2-3b1fa2a89a56",
"createdOn": "2026-08-19",
"action": "update",
"payload": {
"id": "#Q5JHBJ",
"detail": "PHASE 6.2 COMPLETE 2026-08-19 (owner-authorised production window). All fifteen no-statements versions classified and guarded with class validation (none earned superseded or no_ddl: no single later executed migration re-creates every object, and COMMENT ON is a catalog write, not an empty file). Six fail-fast guard migrations per 20260804110240: 20260819110000 dropped objects (absence of 7 functions + 4 indexes), 110100 catalog comments + purge-rag-retrieval-logs cron, 110200 three document FKs, 110300 forty-six operational index shapes, 110400 the index_generation_id promotion (6 columns + 6 indexes + 3 def_hashes), 110500 fifteen function def_hashes read from schema_drift_snapshot() itself. Allowlist now 20 entries (5 superseded + 15 validation). PROOF: full chain replay into the scratch image Applied 210/210 and CHAIN == MANIFEST (zero unexpected drift) -- every hand repair in sections 2.3/3.3/Phase 4 is reproduced by the chain, no reconcile migration needed; seven mutants raise and name their object; all six dry-ran green on production and a mutant fails there naming reset_document_index def_hash; production push real (migration list pending = exactly six, db push applied, rows stmt_count 4 no_statements false, 210 rows, documents 2851 untouched); staging by the Phase 2 method, six md5-matched rows, 210 rows, no_statements 0, drift comparison green. LIVE-DRIFT run 32251326536 on the branch: Compare step SUCCESS, all 20 history rows allowed, No unexpected schema drift -- #316's finding set is EMPTY for the first time since 2026-07-26. RESIDUAL, not this row's: the job still concludes failure because the Phase 0 step Align migration history (check:migration-history) ran for the first time ever and cannot read supabase_migrations over PostgREST (PGRST106, schema not exposed) -- queued as its own item. Evidence: forensics section '6.2 completion'.",
"baseRowFingerprint": "c504f6aab26c77516a2abc1ded4682f21181ce26ad9f201109cf92731e881d9c"
}
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
{
"version": 2,
"id": "cc60253d-6efe-44ab-a615-8584ab0983b6",
"createdOn": "2026-08-19",
"action": "add",
"payload": {
"pri": "P2",
"type": "issue",
"summary": "live-drift's Align migration history step fails on PGRST106 (supabase_migrations not exposed to PostgREST), so the job stays red and pinned issue #1963 cannot self-close even with zero drift",
"detail": "Exposed 2026-08-19 by Phase 6.2: live-drift run 32251326536 reported No unexpected schema drift (all 20 history rows allowed) but concluded failure because the next step, Align migration history for Supabase Preview (npm run check:migration-history, scripts/check-migration-history-alignment.ts, added in Phase 0 PR #1939), ran for the first time ever -- it was skipped on every earlier run because the compare step failed first, and the last green run (29700973962, 2026-07-19) predates it. It reads supabase_migrations.schema_migrations through PostgREST with Accept-Profile, which this project has never exposed (406 PGRST106: only public, graphql_public). The routing job therefore keeps #1963 open on job result even with an empty findings block. OPTIONS (owner decision): (a) expose supabase_migrations read-only to the service role in the dashboard; (b) rewrite the read onto the management API / supabase migration list using the SUPABASE_ACCESS_TOKEN secret (#183); (c) add a service-role RPC listing versions (new migration, own window). Until fixed, weekly live-drift stays red on that step alone; drift itself is green. Evidence: forensics section 6.2 completion step 6.",
"source": "Phase 6.2 session 2026-08-19; live-drift run 32251326536",
"issueUlid": "01M0CZ8XPMM54C4NDHX8VP2H8Z"
}
}
Loading
Loading