The SSH access link survives restarts
A paired server's SSH access link now survives its restarts, and you can relink it.
When a server you paired with Orca restarts, its orcad process gets a new runtimeId. Orca treated that as a possibly different server, so a server with SSH access set up stopped working, and once you removed the access you couldn't add it back. This fix treats a restart as a restart. The SSH access link stays, and you can remove it and add it again freely.
Two errors after a restart
After a restart, two errors locked SSH access
The only workaround was hand-editing orca-environment-sidecar.json
Issue 32957 reported two errors. After the server restarted, opening a worktree failed with "SSH access operation cannot change the paired runtime identity." After you removed SSH access, setting it again failed because the state was inconsistent with the paired server. The only way out was editing the sidecar file by hand.
A runtimeId names one orcad process
orcad mints a new runtimeId every time it starts
orcad mints a new runtimeId at every start, so the id names one process. In the new tests, one server goes from host runtime to restarted runtime to restarted again. What proves a reply came from the paired server is the pinned host key and the device token, checked in the encrypted handshake, plus the pairing binding. Those stay put, so a new id behind the same pinned pairing is a restart.
markEnvironmentUsed records the new id
markEnvironmentUsed records the new id instead of throwing
The first change is in markEnvironmentUsed. It used to throw whenever a server with SSH access reported a new id, which is the first error from the issue. Now it records the new id. It still refuses a different paired device while the server is linked or has an operation pending, and it still refuses any runtimeId change while a link is pending, so the protection for 27765 stays in place.
The sidecar entry stays after a restart
The sidecar entry no longer vanishes after a restart
That early return dropped the whole entry:
The second change is in overlayRuntimeEnvironmentSidecar. This check returned early whenever the sidecar's runtimeId differed from the store's. That dropped the whole entry: the SSH access, the pending operation, the managed deployment link and the revision floor. After a restart the ids always differ. The check is gone. The store's id wins, and the sidecar's id only fills in while the store has none.
Two checks stop tracking a moving runtimeId
Two checks stop comparing against a runtimeId that moves
A reply that arrives after a restart, mid-unlink, no longer aborts the unlink.
A lost-completion retry checks the runtime the link verified, read by linkedRuntimeId(). An impostor is still refused.
Two smaller changes follow from the same idea. The runtimeId is out of the binding an SSH access operation is checked against, so a reply that arrives after a restart, in the middle of an unlink, no longer aborts it. And a lost-completion retry now compares against the runtime the link actually verified, which a new helper reads from the sidecar entry. An impostor runtime is still refused.
Why the fix is client-only
The fix stays on the client and works with every host version
Two other fixes were considered. Rewriting the sidecar's id together with the store's means two files with a crash window between them, and older builds rewrite the store without touching the sidecar, so the link would still vanish. Clearing the sidecar's id on unlink fixes only the relink half. The chosen fix is client-only. It works with every host version, and nothing on the wire changes.
The tests
Two new tests fail on main, and a third pins what is still refused
The new tests sit beside the store. One restarts a linked server, unlinks, restarts again and relinks, and it fails on main with both reported errors. Another finishes an unlink and a lost-completion retry across a restart, which also fails on main. A third confirms that a new paired device, or a new runtime during a link, is still refused. Locally, about 620 unit tests in 61 files pass, along with the full static analysis job.
What this does not cover
The fix hasn't been run live against a paired server restarting
The tests exercise the store directly. A real paired server with an SSH access link hasn't been run through a restart, and independent SSH access has zero end-to-end specs. Host authentication is unchanged, but a cloned server holding the same private key and device registry is now accepted while linked, the same as the managed path. And a downgrade to a build with the old overlay check hides the link until you upgrade again.
A restart is a restart
Longer term, a stable per-host identity would be a cleaner key for these checks. That needs a host change.
The pinned pairing decides which server it is, and the SSH access link stays through every restart.
A stable per-host identity that survives restarts would be a cleaner key for these checks, and for the registered-more-than-once check too, but that needs a host change and capability negotiation. This fix follows the issue reporter's root-cause analysis. The pinned pairing decides which server it is, and a paired server's SSH access link now survives its restarts.










