Conversation
Three fixes on top of the eager-start/passive change: - A permanent hub failure (403 rejected key, 426 wire skew) returned straight out of `client::run` with a `bail!`. That was safe only because the source could not exist yet — with `eager_start` the command is already running in raw mode, and nothing in the tree restores it: there is no `Drop for RawMode` and the sole `raw.restore()` is the child-exit path. A caller that exits on the error (the CLI does) left the terminal with no echo and no line editing. Announce through the notifier's existing outage pause before propagating, so the terminal comes back cooked with the reason on screen. Also repairs the same hazard on a mid-session reconnect that gets 403'd after the hub's --allow changed. - `passive` was spent in the screen loop — two guards, an 11th argument to `screen_thread`, and messages built and dropped every outage. The notifier is the only producer of `Msg::HubDown`/`HubUp`, so not installing it makes those arms unreachable by construction instead of by two guards that have to stay symmetric. `NoopSinkStatus` already exists for exactly this. - docs/library-api.md still claimed the source factory runs only after the upgrade succeeds; document `eager_start` and its pairing with `passive`. Note on `HubState::live` why it is public. Co-Authored-By: Claude Opus 5 (1M context) <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.
Review follow-up for iksteen#15 — one commit on top of your two, so you can take it, take part of it, or ignore it. Nothing is merged on my side.
1. A permanent hub failure could leave the terminal in raw mode
client::runbails out on a 403 (rejected key) and a 426 (wire skew). That was safe only because the source could not exist yet — the gate you're bypassing is what guaranteed it. Witheager_startthe command is already running in raw mode when those fire, and nothing restores it: there is noDrop for RawMode, and the onlyraw.restore()is the child-exit path, which never runs here. A caller that exits on the error — the CLI does — leaves a terminal with no echo and no line editing.The fix announces through the notifier's existing outage pause before propagating, so the terminal comes back cooked with the reason on screen. A
passivesource is deliberately left alone, same contract as an ordinary outage.Worth noting this was reachable before your PR too: a mid-session reconnect that gets 403'd after the hub's
--allowchanges hits the samebail!with a live backend.eager_startjust moves it from obscure to likely.I did not make 403/426 retryable —
RECONNECT_BACKOFFis 500ms and the hub logs rejections for fail2ban, so a client retrying a bad key twice a second is exactly what that log is for.2.
passivecan stop at the constructorNotifieris the only producer ofMsg::HubDown/HubUp, and the two arms you guard are the only consumers. Not installing it makes them unreachable by construction instead of by two guards that have to stay symmetric, andNoopSinkStatusalready exists for this.screen_threadgoes back to 10 arguments.The flags themselves stay exactly where you put them —
eager_starton the transport,passiveonpty::start. They're orthogonal: anexternal_source()producer already getsNoopSinkStatusand wants only the first, and a PTY embedder may well wantpassivewith the hub-gated start.3. Docs
docs/library-api.mdstill said the factory runs only after the upgrade succeeds. Documentedeager_startand its pairing withpassive, and noted onHubState::livewhy it's public.fmt, clippy
-D warnings,cargo test --workspace(191 passed), and the five subset feature builds are all green. One test added for the new path.🤖 Generated with Claude Code