fix(version-switch): refuse vanished targets#1576
Merged
Merged
Conversation
|
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.



What this is
PR 4 of #1570. A version can disappear after the picker loads but before the user selects it. The backend now performs a fresh exact-id availability check immediately before moving a shortcut binding onto an already-local target.
A definitive target 404 refuses the switch. Temporary uncertainty still fails open so the offline Switch anyway path remains usable and bounded by one short attempt.
What changed
get_rom_once(target_rom_id)after all non-writing guards pass and immediately before the binding-write path.RommNotFoundErrorreturns:{success: false, reason: "version_vanished", message: "This version is no longer available on RomM."}allow_strandedbypasses only the save-stranding guard; both Sync now & switch and Switch anyway retries still receive the final liveness check.version_vanishedrefusal; other failures remain classified normally.server_unreachableupdates global connection state.version_switched.The active-target no-op is not probed, and no network request is held inside a SQLite unit of work.
Safety
The check narrows the stale-list window but does not pretend RomM and SQLite share a transaction. RomM can still delete an id after a successful response; retained local identity and the PR-3 recovery path keep that state recoverable.
No library sync or fetch-stamp invalidation is introduced.
Docs
Updated backend architecture, Steam shortcut architecture, and the managing-games user guide. Frozen ADR history remains unchanged.
Verification
The full
mise run gatepassed on the implementation state:Review fixes then passed 100 focused backend/contract tests, 57 frontend tests, changed-file static/type/format checks, and an independent review with no remaining findings.
On-device verification
Passed in Game Mode with a safely staged local binding: a retained id that RomM answers with 404 was temporarily bound to the existing Steam appId, remained visible and disabled, and returned an honest
not_foundresponse on Download. Switching back to its live local sibling succeeded through the new pre-write target probe; the appId stayed stable, RomM was not reported offline, the picker guard released, and the database binding returned to the live id. No RomM data was deleted for the test.Closes part of #1570.