Repository navigation
fix: refuse shared projects before minting identity - #1748
Merged
Merged
Conversation
A fresh `lcm migration apply` ran the identity step (local project-map entry plus PostgreSQL destination project) before checking whether the project was already shared, so a second machine bound to a shared project could be refused with multi-machine-installation after a destination project had been created, and the refusal reported applied: true. The scope depends only on whether the local project-map entry carries a remoteProjectId, which the mint never writes. Apply now reads the map under the retained barrier token, right after the confirmed-candidate recheck, and refuses before the identity step, the hold or capture. The read is a snapshot with no backfill or write. The entry-to-scope derivation is shared with authenticateSqliteMigrationSource, which still reads the map itself after the mint so it sees the minted entry. The post-mint scope check stays as defence in depth. The H2 rehearsal row now expects applied: false. The recorded gate files (docs/migration-rehearsal-gate.*) are left untouched: they describe the tested commit and are regenerated by a separate full rehearsal run. Signed-off-by: Bernardo Donadio <bcdonadio@bcdonadio.com>
bcdonadio
enabled auto-merge
October 25, 2026 04:10
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
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.
Why
Fixes #1689. On a second machine whose project-map entry already carries a
remoteProjectId(a project shared across machines),lcm migration apply --confirm-generation <id>correctly refused withmulti-machine-installation, but only after the fresh identity step had run. That step can persist the local map entry and resolve or create the PostgreSQL destination project, so the refusal reportedapplied: trueand could leave a destination identity behind. The shared scope depends only on the existing local map entry, so the refusal can be decided before any write.How
freshCutoverUnderBarriernow runs a read-only scope check right after the confirmed-candidate recheck and before the identity step. A shared entry refusesmulti-machine-installationbefore the identity mint, the maintenance hold and capture, so the envelope reportsapplied: falseand nothing is written.readSqliteMigrationSourceScope(inmaintenance.ts) reads one project-map snapshot under the retained publication token. It shares the entry-to-scope derivation withauthenticateSqliteMigrationSource, which still reads the map itself after the mint so it sees the minted entry.cli-preflight.tsandcli-apply.tsare unchanged. The cutover-set path already refused shared members before its identity step.Testing
test/migration/apply.test.ts: a shared entry refuses before the identity resolver runs (resolver and destination resolution never called, project-map bytes unchanged, no maintenance journal). This fails at the base commit. Controls: a local project still reaches the identity step, and a project bound during the identity step is still refused by the retained post-mint check.test/postgresql/cutover-rehearsal/scenarios.json: the H2b-applyrow now expectsapplied: falseand its note describes the new order. The checked-in rehearsal gate record (docs/migration-rehearsal-gate.*) is a sealed record of an earlier tested commit and is not regenerated here.apply.tsandmaintenance.tsat 100% statements, branches, functions and lines.pnpm run typecheckand eslint pass.Reviewer guide
Start at
freshCutoverUnderBarrierinsrc/migration/apply.ts(the new check beforeresolveIdentityUnderBarrier), thenreadSqliteMigrationSourceScopeandsqliteMigrationSourceProjectIdentityinsrc/migration/maintenance.ts. Docs: themulti-machine-installationremedy indocs/migration-operations.md. Metadata: patch changeset andtest/codecov-ownership/1689-shared-history-refusal-order.yml.