Repository navigation
fix(ssh): Cancel on an SSH password prompt no longer brings it straight back - #28402
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Priority: ⬇️ Low Merge Risk: ⚪ Minimal · up to
|
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…ts SSH host Co-Authored-By: Claude <noreply@anthropic.com>
…ful sign-in lifts the decline Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
6a76c67 to
647b5ce
Compare
…ht back (stablyai#28402) * fix(ssh): a cancelled sign-in stays cancelled until the user reconnects Co-Authored-By: Claude <noreply@anthropic.com> * test(ssh): drive the credential cancel through the IPC harness Co-Authored-By: Claude <noreply@anthropic.com> * fix(ssh): an explicit server connect lifts the cancelled sign-in of its SSH host Co-Authored-By: Claude <noreply@anthropic.com> * fix(ssh): the cancelled attempt may still offer a password; a successful sign-in lifts the decline Co-Authored-By: Claude <noreply@anthropic.com> * test(ssh): build the managed-server link without the newer kind field Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: m4air <m4air@Mac.localdomain> Co-authored-by: Claude <noreply@anthropic.com> (cherry picked from commit ed18c2c) Release pick note: runtime-environment-connectivity-handlers.ts conflicted with main's WSL host series (stablyai#27874/stablyai#27940/stablyai#27933), which is not on this release. Kept only this PR's two lines there (the clearSshCredentialDeclinedForEnvironment import and call).
ELI5
If Orca asks for an SSH password or key passphrase and you press Cancel, Orca now takes that as your answer. It stops asking for that host until you click Reconnect (or Connect / Test) yourself.
What Changed
Before: on a host that needs a password or passphrase, pressing Cancel brought the dialog straight back, within a few seconds, over and over. This happened even when no workspace on that host was open. The dialog is modal, so a user who did not remember the password could not use Orca at all.
After: Cancel ends that sign-in. The host shows as needing sign-in ("SSH authentication failed") in its status. Nothing automatic opens the dialog again: background status checks, the managed-server tunnel, terminal and server censuses, reconnect after sleep, startup restore, pane mounts and automations all stay quiet. The user can click Reconnect on the host, the terminal overlay, the status bar or Settings, and the prompt then appears again as normal. A dialog left unanswered until its 2-minute timeout counts as Cancel.
Mechanism: since every SSH host runs a managed Orca server, the app reaches the server through an SSH tunnel. Main-process work dials that tunnel through the shared SSH connection manager. This includes the host-status checker, which retries every 3–60 s, every runtime call, the census and maintenance. Each dial that hit a password or passphrase opened the credential dialog, and a Cancel only failed that one attempt. The next retry prompted again.
There is now one record of "the user cancelled sign-in for host X" (
src/main/ssh/ssh-credential-decline.ts):ssh:needsPassphrasePromptreports true, so panes and automations that probe first skip the dial.ssh:connectfrom a user action, thessh.connectRPC, or Test Connection. The renderer's automatic callers (startup restore, pane mount, automation dispatch) now passautomatic: true, so they cannot clear it.Why
The bug is in "who may open a credential prompt", not in any one retry loop, and there are many automatic callers. Adding a backoff or a check to each one (status owner, tunnel, census, resume, restore) would leave the next new caller free to bring the loop back. A single per-host record, enforced where every dial and every prompt passes, covers all current and future background paths. Keeping the gate at the prompt as well means a key that starts working (for example after
ssh-add) is still accepted by an in-flight reconnect. The record lives in memory, so after a restart the host gets one prompt, not a loop.Regression source: #24863 (Phase 3), which made every SSH host a managed server reached through a tunnel that background work dials. Before that, background work never dialed a host. #27214 also stopped saving
lastRequiredPassphrase, which startup restore used to delay password hosts.Linked Issue
STA-10477
Visual Proof
N/A — no visual change. The existing dialog and host status are reused. The change is that the dialog no longer reappears after Cancel.
Testing
New failing-first tests:
src/main/ipc/ssh-credential-cancel.test.ts: after Cancel, there is no new prompt from automatic requests; panes and automations see "needs sign-in"; startup restore's automatic connect keeps the decline; an explicit Reconnect and Test Connection prompt again; other hosts are unaffected.src/main/ssh/ssh-connection-manager.test.ts: automatic dials are refused as an auth error with no connection opened; a live connection is still reused; dialing works again after an explicit sign-in.src/main/ipc/ssh-passphrase.test.ts: Cancel and timeout record a decline; answered, aborted and windowless requests do not.src/renderer/src/startup/startup-ssh-connection-restore.test.ts: restore dials as automatic.pnpm tc,vitest src/main/ipcplus the affected renderer suites,oxlint,pnpm run check:code-quality:changedandpnpm lintall pass.Not manually tested against a real password host on this machine: no Electron or Docker runs here.
I manually tested these changes locally
Automated tests added/updated, or explained why not below
AI Disclosure
Review
Agent skill upstream boundary
Notes
ssh.connectRPC that remote, mobile and web clients use counts as explicit, so their user-driven connects still prompt on the host. There is no wire change.Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)