Repository navigation
fix(move): read the host left behind until every contact has followed - #6
Merged
Merged
Conversation
A move tells each contact the new address in a lane notice inside the session, and until the contact applies it, it keeps appending to the old host on the old lane. Nothing read that host after the move, so whatever contacts wrote there in the meantime was lost; a contact that was offline, and so flushed its queue before it fetched the notice, lost all of it. A move made during a commit race could not settle either: the loser's rebuild Welcome went to the old host. The device now goes on reading the old host. On a move it keeps the old host's deployment, its cursor and each conversation's old inbound lane as the previous inbox (persisted with the deployment). Each sync, and a 5-minute poll, reads that host under a sync key of its own, so it has its own cursor, dedup set and quarantine; records there route to their conversations by the old lanes, are processed as usual, and are never acknowledged at that host. The drain ends once every conversation's peer has been seen at the new host and the old one has nothing left, or after Δ (30 days), the bound within which a contact is held to follow. Reading the old host needs the credential held there, so the profile and the CLI driver keep the replaced credential when a credential for another runtime is installed, and pick the one a request names by runtime id. The desktop refreshes the kept credential at the old host when it nears expiry. On the contact's side, applying a lane notice now readdresses what is still queued on the old lane to the new one and restarts its retries, so a message that could not reach a host already gone goes to the new one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Restores the test moved out of the previous change: with the host left behind still read, the winner's commit on the loser's old lane is taken, the race settles, and the rebuild's lane notice reaches the winner. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
koabula
enabled auto-merge (squash)
November 11, 2026 12:51
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Readdressing every queued envelope when a peer's notice arrived also moved the ones in flight, which then held the new lane until their requests to the old host came back: one request to a host already gone could hold every later message for as long as its timeout. A notice now readdresses only what is idle; an envelope in flight keeps its lane, and if it fails, the flush before its retry readdresses it to its peer's current lane. The relocation test now checks that what Alice queued goes to Bob's new host once she applies the notice, with later messages after it in order. The new test picks Alice's message by its text, settles its append if it went out, and reports what Bob held when it does not take the message. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ts inbox key
The batch passed its sync key to the application-plaintext check and to the
conversation it creates on a first-contact Welcome, both of which want the
device itself. For the host a move left behind the key is previous:{device},
so every application record read there was refused as addressed to another
device. Both now get the recipient the records are addressed to.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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
A move tells each contact the new address in a lane notice inside the session. Until a contact applies that notice, it keeps appending to the old host on the old lane. Nothing read the old host after the move, so whatever contacts wrote there in the meantime was lost:
What
Engine
previous:{device}), so that host has its own cursor, dedup set and quarantine. Records there route to their conversations by the old lanes and go through the ordinary inbound path. They are never acknowledged at that host; they expire there on their own.Platforms
Ledgers. No new request or event kind: reading the old host reuses
GetHeadandFetchMessages, and there is no new emission site.Tests
a_move_goes_on_reading_the_host_it_left. Bob reads his old host under its own credential and takes Alice's message on the old lane, with no ack sent there. When Alice applies the notice, her queued envelope moves to the new lane.the_old_host_is_read_until_every_peer_has_followed. The drain ends once the peer has written to the new host and the old host is read to its end.a_lane_moved_during_a_race_is_announced_after_the_rebuild. A move made during a race settles, and the winner follows the loser's new lane. This test was moved out of fix(direct): open items from the client's spec, and the KeyPackage pool count route #5, where it could not pass without this change.Not verified locally
There is no Rust toolchain on this machine; CI is the first build.
🤖 Generated with Claude Code