diff --git a/docs/audit/live-drift-forensics-2026-08.md b/docs/audit/live-drift-forensics-2026-08.md index 166269ae6e..83ad10fccd 100644 --- a/docs/audit/live-drift-forensics-2026-08.md +++ b/docs/audit/live-drift-forensics-2026-08.md @@ -2018,8 +2018,68 @@ is worse than the red job it replaces. When neither path works, the error names ### What is still owed +_Superseded by the 2026-08-20 window section below: the migration was already applied on production +before the window opened, and D4 is no longer treated as OFF. Kept as the pre-window record._ + The migration is **not deployed**. D4 is OFF, so merging does not apply it, and until it is applied `check:drift` will report `migration_history_versions` as a missing function — i.e. merging before the window trades one red for another. **Deploy from the branch first, then merge**, which is the order Phase 4 used (§Phase 4 completion). Staging needs the same migration by the Phase 2 method to hold the parity Phase 4 restored. + +### Window 2026-08-20 — production already applied; staging still owed + +_Owner-authorised window. Worktree linked to production (`sjrfecxgysukkwxsowpy`), the main checkout +left on its staging link. Every call carried an explicit `--project-ref`._ + +**PR #2198 was merged before the window** (squash `a341832af`), the reverse of the intended +deploy-then-merge order. The pre-flight then found the migration **already applied**: + +``` +$ supabase migration list --linked --project-ref sjrfecxgysukkwxsowpy +… {"local":"20260820120000","remote":"20260820120000","time":"2026-08-20 12:00:00"} +``` + +`db push` was therefore never run against production in this window. Read-only verification: + +| Check | Result | +| ----------------------------------------- | ---------------------------------------------------------- | +| history row shape | `stmt_count 3` — executed statements, **not** mark-applied | +| `prosecdef` / `provolatile` / `proconfig` | `true` / `s` / `search_path=""` | +| `proacl` | `postgres=X/postgres \| service_role=X/postgres` | +| function output | `probe: ok`, `version_count: 211`, `table_rows: 211` | + +211 remote versions against 211 local migration files, so the alignment check's `remoteOnly` set is +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 + +`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 +provenance signal** and cannot say how this row arrived. Two explanations remain open, and the +distinction is the whole of D4: + +1. **Supabase Branching applies on merge.** §3.7 measured exactly this — migrations `110000`–`112000` + bracketed to **34 s** after #2106's squash-merge. A Supabase preview branch existed on #2198 + (project `gjpnznsmbylfkzfeeuki`, "Migrations ✅" 17:08:58 UTC) and the PR merged minutes later. +2. Someone ran `db push` against production in the same hour. + +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. + +#### Staging is one version behind — blocked, not skipped + +Staging (`ikoiolksxqxfxgiyqpnu`, verified before every call) reads **210** history rows, latest +`20260819110500`, `to_regprocedure('public.migration_history_versions()') is null`. Its pending set is +exactly `['20260820120000']` with zero remote-only versions, so a single `db push` (or the Phase 2 +`execute_sql` method) closes it. + +Both write paths were **denied by the session's auto-mode classifier** — `supabase db push` and the +MCP `execute_sql` alike — under the live-Supabase confirmation rule added by PR #2196 the same day. +Read-only calls were unaffected, which is why every verification above exists. This is an +authorisation gap, not a technical one: **staging parity, closed by Phase 4, is open again by one +version until an operator applies it.** diff --git a/docs/branch-review-records/0b9f33dbb3fde5baaca33bd4ac3d075d142ccc11773079e8b7026dcf973d5579.record.md b/docs/branch-review-records/0b9f33dbb3fde5baaca33bd4ac3d075d142ccc11773079e8b7026dcf973d5579.record.md new file mode 100644 index 0000000000..a3613c46ea --- /dev/null +++ b/docs/branch-review-records/0b9f33dbb3fde5baaca33bd4ac3d075d142ccc11773079e8b7026dcf973d5579.record.md @@ -0,0 +1 @@ +| 2026-08-20 | PR #2201 | 44d3cbb41aae5f1b7707d529347ee12dcc0cc44e | PR #2201 drift alignment window record — Codex P1 review-comment resolution | Fixed: the status board's active 'Next dispatches' line, the D4 owner-decision entry, the 2026-08-19 'Resolved' paragraph and the pre-window forensics section still instructed coordinators that D4 is OFF and each migration needs its own db push, contradicting the same PR's finding that D4 is unresolved. All four now say to treat a merge as a production deployment until the dashboard toggle is re-verified. Docs only; no code, migration or fixture touched. | npm run verify:pr-local (docs scope): check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index/inventory/scripts/links, check:branch-review-ledger, check:outstanding-issues, check:ledger-write-discipline — all completed, none failed | diff --git a/docs/branch-review-records/b0f1f213296ed6e158184a90156c52a58b6fa4fc3597114c8fd29864d090f58d.record.md b/docs/branch-review-records/b0f1f213296ed6e158184a90156c52a58b6fa4fc3597114c8fd29864d090f58d.record.md new file mode 100644 index 0000000000..cbb4622f2e --- /dev/null +++ b/docs/branch-review-records/b0f1f213296ed6e158184a90156c52a58b6fa4fc3597114c8fd29864d090f58d.record.md @@ -0,0 +1 @@ +| 2026-08-20 | PR #2198 (claude/phase-4-index-restoration-b0f4ea) | ccc3572f3d069751d3850046ea1e6ea0c2ed8c7a | migration-history alignment RPC: 20260820120000 migration_history_versions(), check-migration-history-alignment.ts transport, schema.sql mirror, drift manifest, new tests, drift/forensics/board docs | Authored and self-reviewed. Root cause proven from live-drift run 32378402265 (compare step success, alignment step 406 PGRST106). Fix is a service-role-only security-definer RPC; Data-API exposure and a management-API token were considered and rejected in forensics. NOT DEPLOYED: db push from this branch in an approved window must precede merge (D4 off), else check:drift reports a missing function. Staging needs the same migration by the Phase 2 method. | check:migration-role PASS; drift:manifest replay PASS (58s, 94 functions, service_role-only acl); vitest drift-detection+migration-history-guards+search-health-index-coverage+migration-history-alignment 40/40 PASS; format whole-tree exit 0; verify:pr-local 12 checks PASS then typecheck/test BLOCKED by DATABASE_HEAVY_RUN_ADMISSION_BUSY from other worktrees - delegated to CI on PR #2198; no provider-backed gate run | diff --git a/docs/database-remediation-coordination.md b/docs/database-remediation-coordination.md index 80d5d4b87b..a19b4d4bcd 100644 --- a/docs/database-remediation-coordination.md +++ b/docs/database-remediation-coordination.md @@ -96,7 +96,7 @@ trusted as-is._ **Owner decisions (2026-08-18):** D1 = codify-as-live (128 MB on the four hybrids, 64 MB on the other six) — DECIDED. D2 = `work_mem` eval-canary exemption — GRANTED. D3 = 6.1 deploy bundled into -the Phase 3 production window — DECIDED. D4 = Supabase GitHub auto-deploy **disabled** — DECIDED (confirmed empirically in the 2026-08-19 Phase 4 window). +the Phase 3 production window — DECIDED. D4 = Supabase GitHub auto-deploy — **REOPENED 2026-08-20, treat as ON** (the 2026-08-19 Phase 4 "disabled" reading never tested deploy-on-merge; see the 2026-08-20 window update below). Until the dashboard toggle is re-verified, assume merging a migration PR deploys it to production. **Production window — CLOSED 2026-08-18 without a push (PR #2123 → forensics §3.7).** The authorised window's pre-flight `supabase migration list` showed all five `20260818*` migrations @@ -109,14 +109,17 @@ no mark-applied path was used, and production received zero writes. Verified rea 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. -**Resolved 2026-08-19:** D4 was decided OFF and "Deploy to production" is disabled (stated in the +**Resolved 2026-08-19 — SUPERSEDED 2026-08-20, see the window update below; do not act on this paragraph:** D4 was decided OFF and "Deploy to production" is disabled (stated in the Phase 4 task brief; who changed the setting and when is not recorded here). The Phase 4 window confirmed it empirically — `supabase migration list` showed the four new `20260819*` versions still pending on production after the branch existed, so nothing had been applied by merge, and they reached production only via an explicit `supabase db push`. **The explicit-window model in the plan and playbook is therefore live again and must be honoured:** a merged migration is no longer a production deploy, so every future phase needs its own approved window and its own push. Phase 4 was built to be safe either way -(prebuild + validate-only guard) and that pattern stays mandatory. +(prebuild + validate-only guard) and that pattern stays mandatory. **That conclusion did not hold** — the +Phase 4 observation only showed migrations pending _while a PR was open_, which never exercised +deploy-on-merge; the 2026-08-20 window reopened D4. The safe-either-way build pattern stays mandatory +regardless. **Ledger state note (2026-08-19):** inbox on `main` holds 23 pending requests (remediation: `#248`/`#183`/`#318`/… `done`s from other streams, several `add`s incl. the review-bot budget P1); @@ -138,12 +141,29 @@ the history version list — plus an RPC-first rewrite of `scripts/check-migration-history-alignment.ts`, `schema.sql` mirror, regenerated manifest (94 functions) and `tests/migration-history-alignment.test.ts`. Exposing `supabase_migrations` to the Data API and adding a management-API token to CI were both considered and rejected (forensics §Alignment-step -repair). **Deploy order matters: `db push` from the branch FIRST, then merge** — D4 is OFF, so merging -alone applies nothing and would make `check:drift` report a missing function in the meantime. Staging +repair). **Deploy order matters: `db push` from the branch FIRST, then merge** — written when D4 was believed +OFF, so that merging alone would apply nothing and would make `check:drift` report a missing function in +the meantime. Push-before-merge is still the right order, but for the opposite reason now: with D4 +reopened, a merge may itself deploy, so the migration must already be applied and verified inside an +approved window before the PR lands. Staging needs the same migration by the Phase 2 method. Until that window runs, the weekly job stays red on this one step and #1963 will not self-close. -**Next dispatches:** merge the 6.2 PR (its CI `Migration replay` and Supabase Preview are the last chain proofs), then Phase 5 close-out (after-EXPLAIN set, `#231` re-test on healthy latency, `check:production-readiness`), then one serialized `issues:reconcile`. Every future migration still needs its own approved window and its own `db push` (D4 OFF). +**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 +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 +(`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. + +**Next dispatches:** merge the 6.2 PR (its CI `Migration replay` and Supabase Preview are the last chain proofs), then Phase 5 close-out (after-EXPLAIN set, `#231` re-test on healthy latency, `check:production-readiness`), then one serialized `issues:reconcile`. Every future migration still needs its own approved window and its own `db push`. **D4 is REOPENED (2026-08-20): treat merging a migration PR as a production deployment** until the Supabase "Deploy to production" toggle is re-verified in the dashboard — so never merge a migration PR outside its approved window, and apply and verify the migration inside that window before it lands. **Where the programme stands after Phase 4 (2026-08-19).****Where the programme stands after Phase 4 (2026-08-19).** The index track of `#316` is closed on both tiers and staging is at full parity, so the remaining live-drift findings are exactly one category: