fix(migrations): restore 0180's bytes and freeze released migrations against post-release edits (#9420) - #9776
Merged
Merged
Conversation
…9420) #9420 updated a doc COMMENT inside migrations/0180_decision_ledger.sql. No DDL changed. It shipped in orb-v3.5.0. runSelfHostMigrations records a sha256 of each applied migration's FULL text and re-hashes on every boot, throwing selfhost_migration_content_drift on a mismatch. Comments are part of that text. So every deployment that had already applied 0180 would REFUSE TO BOOT on upgrade -- not degrade, fail to start, review pipeline down until a human restored the file. Confirmed against the live ORB: its _selfhost_migrations row for 0180 stores 0a95840f..., byte-identical to orb-v3.5.0-beta.10 and different from main. A full sweep of all 199 ledger rows found 0180 to be the only such drift. Restore 0180 verbatim. Nothing is lost: #9420 wrote the same prose into src/review/decision-record.ts's header, which is where it belongs and where it can change freely -- that header now says so, and says why the .sql must not. Add db:migrations:immutable:check: once a migration exists in a released orb-v tag its bytes are frozen, baselined at its FIRST release so a later tag that disagrees (as 3.5.0 does) cannot move the target and block the repair. The 35 files edited before this rule existed are re-frozen at current content rather than exempted, so the guard has no permanent holes.
Contributor
|
Important 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏳ LoopOver is waiting…LoopOver has seen this pull request and is waiting on CI checks to finish before reviewing it. This comment will update once the review runs. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed · 🟨 Waiting |
Contributor
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
loopover-ui | c5135b2 | Commit Preview URL Branch Preview URL |
Jul 29 2026, 08:10 AM |
…-drift-0180 # Conflicts: # package.json
Bundle ReportBundle size has no change ✅ |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9776 +/- ##
=======================================
Coverage 90.30% 90.30%
=======================================
Files 912 912
Lines 113547 113547
Branches 26951 26951
=======================================
Hits 102536 102536
Misses 9682 9682
Partials 1329 1329
Flags with carried forward coverage won't be shown. Click here to find out more.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
#9420 updated a doc comment inside
migrations/0180_decision_ledger.sql. No DDL changed. It merged ~36 minutes before theorb-v3.5.0stable tag and shipped in it.runSelfHostMigrations(src/selfhost/migrate.ts) records a sha256 of each applied migration's full text and re-hashes it on every boot, throwingselfhost_migration_content_drifton a mismatch. Comments are part of that text.So any deployment that had already applied 0180 would refuse to boot after upgrading — not degrade, not warn: fail to start, with the review pipeline down until a human restored the file by hand.
How it was caught
Cutting the next ORB beta. Before building, I compared the live server's
_selfhost_migrationsledger against the repo:A sweep of all 199 ledger rows confirmed 0180 is the only drift. The stable
orb-v3.5.0image already carries it, so this is not hypothetical for anyone upgrading from<= beta.10.The fix
Restore 0180 verbatim. Nothing is lost — #9420 wrote the same prose into
src/review/decision-record.ts's header, which is where documentation about this table belongs and where it can change freely. That header now states the split and why the.sqlmust never be edited.Add
db:migrations:immutable:check. Once a migration appears in a releasedorb-v*tag its bytes are frozen — DDL, typos, comments, all of it. Deletion is refused too.Two design points worth reviewing:
The checker reads the working tree, not
ls-tree HEAD, so it can't go green locally on the exact change it exists to reject.Verification
Guard mutation-tested in all four directions: passes with the fix; fails naming 0180 when #9420's edit is reintroduced; fails naming 0193 when any other released migration is touched; passes again when reverted. 10 unit tests including a regression for the real failure, the deletion case, and an invariant that the rebaseline table cannot grow.
tsc,db:migrations:check,db:migrations:immutable:check,dead-source-files:check,import-specifiers:check,validate:no-hand-written-jsall green.This should land before the next ORB image is cut.