diff --git a/docs/audit/live-drift-forensics-2026-08.md b/docs/audit/live-drift-forensics-2026-08.md index 83ad10fccd..76072e0b50 100644 --- a/docs/audit/live-drift-forensics-2026-08.md +++ b/docs/audit/live-drift-forensics-2026-08.md @@ -2053,7 +2053,7 @@ $ supabase migration list --linked --project-ref sjrfecxgysukkwxsowpy empty and the step should now pass. **No guard migration is owed**: the row carries executed statements, so it is not a history repair and cannot surface in the `migration_history` probe. -#### The D4 conclusion needs re-testing — the 2026-08-19 test could not detect deploy-on-merge +#### D4: strong evidence of deploy-on-merge — but the toggle itself has not been read `created_by` and `idempotency_key` are NULL for every row from `20260818090000` to `20260820120000`, including the ones this programme applied by operator `db push`, so the history table carries **no @@ -2067,9 +2067,42 @@ distinction is the whole of D4: The 2026-08-19 observation recorded as "D4 is OFF" was that the four `20260819` migrations _sat pending while the PR was open_. That tests deploy-while-open, **not** deploy-on-merge, so it never -contradicted §3.7 — and today's result fits both observations at once. **Treat D4 as UNRESOLVED and -re-verify in the Supabase dashboard before relying on merge being safe.** Until then, assume merging a -migration PR deploys it to production. +contradicted §3.7 — and today's result fits both observations at once. + +**Settled the same day by reading the platform instead of the history table.** +`list_branches(sjrfecxgysukkwxsowpy)` returns exactly one record: + +```json +{ + "name": "main", + "is_default": true, + "git_branch": "main", + "project_ref": "sjrfecxgysukkwxsowpy", + "created_at": "2026-06-27T14:10:20.550361+00:00", + "updated_at": "2026-07-04T08:15:07.640507+00:00" +} +``` + +Production is **still bound to git `main`**, and `updated_at` predates 2026-08-19 — so whatever was +changed that day never touched this binding, and the §3.7 mechanism is intact. Together with §3.7's +34-second apply and `20260820120000` arriving unpushed, that is strong evidence of deploy-on-merge. + +**It remains an inference, and the difference matters.** No field of the branch record reports the +"Deploy to production" setting. The superseded 2026-08-19 account describes that setting being changed +without the binding being deleted, so "toggle off, binding intact" cannot be ruled out from here — and +the two failure modes are not symmetric. Declaring D4 ON tells operators to skip `db push`; if the +toggle is in fact off, every merged migration then sits unapplied and drift returns silently, which is +the original incident. Declaring it OFF risks only a redundant no-op push. + +**So the operative rule is the one that is correct under both states, and it must not be shortened:** + +1. Never merge a migration PR outside its approved window — correct if deploys happen on merge. +2. After any migration merges, run `supabase migration list --linked --project-ref ` and + `db push` anything still pending — correct if they do not. + +One extra command, wrong under neither hypothesis. What would replace this rule with a fact is a +dashboard read of the toggle, or a deployment-settings API that reports it. Raised as a P1 by the Codex +review of PR #2205, and correctly: the earlier wording here presented the inference as a direct read. #### Staging is one version behind — blocked, not skipped diff --git a/docs/database-remediation-coordination.md b/docs/database-remediation-coordination.md index a19b4d4bcd..7e11617ecc 100644 --- a/docs/database-remediation-coordination.md +++ b/docs/database-remediation-coordination.md @@ -105,7 +105,7 @@ no mark-applied path was used, and production received zero writes. Verified rea `ok`; ten `work_mem` values = D1; live-drift run `32131517648` = **0 function mismatches**, 20 `missing_live`, 2 `unexpected_live`, 15 `migration_history`. The RPC track of `#316` is closed. -**KEY FINDING — D4 DECIDED (auto-deploy disabled).** The Supabase GitHub integration (Branching, production +**KEY FINDING — D4: strong evidence of deploy-on-merge; the "disabled" reading does not hold (2026-08-20, below). The toggle itself has not been read — act on the safe-either-way rule, not on the inference.** The Supabase GitHub integration (Branching, production bound to git `main`, branch record from 2026-06-27) auto-applies every migration merged to `main` onto production — live-drift bracketed `110000–112000` to ~34 s after #2106 merged. This undermines the explicit-window model the plan and playbook assume: a merged migration IS a production deploy. @@ -150,15 +150,28 @@ needs the same migration by the Phase 2 method. Until that window runs, the week this one step and #1963 will not self-close. **Update 2026-08-20 (window) — the alignment fix is LIVE on production; staging is one version behind; -D4 is UNRESOLVED again.** PR #2198 merged before the window (squash `a341832af`), and the pre-flight +D4: strong evidence of deploy-on-merge, toggle not directly read.** PR #2198 merged before the window (squash `a341832af`), and the pre-flight found `20260820120000` **already applied** — `stmt_count 3`, executed statements, not mark-applied — so `db push` was never run against production. Verified read-only: `prosecdef true`, `provolatile s`, `search_path=""`, `proacl postgres=X/postgres | service_role=X/postgres`, and the function returns `probe: ok` with `version_count 211` against 211 history rows and 211 local files. No guard migration is -owed. **Two things for the owner:** (1) `created_by` is NULL on every recent row, so nothing proves how -it arrived; the 2026-08-19 "D4 is OFF" test only showed migrations sitting pending _while a PR was -open_, which never contradicted §3.7's 34-second deploy after #2106's squash-merge — re-verify the -dashboard toggle and, until then, assume merging a migration PR deploys it. (2) Staging +owed. **Two things for the owner:** (1) **D4: the "disabled" reading does not hold, but the toggle has +not been read.** `created_by` is NULL on every recent history row, so the database itself proves +nothing. `list_branches(sjrfecxgysukkwxsowpy)` still returns a live Git branch record binding +**production** to git `main`: +`{"name":"main","is_default":true,"git_branch":"main","project_ref":"sjrfecxgysukkwxsowpy","created_at":"2026-06-27","updated_at":"2026-07-04"}`. +`updated_at` predates 2026-08-19, so whatever was changed that day never touched this binding, and the +2026-08-19 "D4 is OFF" test only showed migrations sitting pending _while a PR was open_ — which never +exercised deploy-on-merge. Together with §3.7's 34-second apply and `20260820120000` arriving unpushed, +that is strong evidence of deploy-on-merge. **It is still an inference:** no field of the branch record +reports the "Deploy to production" setting, and the superseded account above describes that setting +being changed without the binding being deleted, so a disabled toggle with the binding intact cannot be +ruled out from here. **Therefore act on the rule that is correct under both states, and do not shorten +it:** never merge a migration PR outside its approved window (correct if deploys happen on merge), and +after any migration merges, run `supabase migration list --linked --project-ref ` and `db push` +anything still pending (correct if they do not). One extra command; wrong under neither hypothesis. A +dashboard read of the toggle, or a deployment-settings API, is what would replace this rule with a +fact. (2) Staging (`ikoiolksxqxfxgiyqpnu`) is at 210 rows without the function; its pending set is exactly one version, but both write paths were denied by the session auto-mode classifier (live-Supabase confirmation rule from PR #2196), so Phase 4's staging parity is open again by one version until an operator applies it.