Skip to content

fix(wsl-host): pair again from the distro when a WSL host refuses the enrolled token - #31745

Merged
nwparker merged 4 commits into
mainfrom
nwparker/wsl-orcad-pairing-repair
Oct 22, 2026
Merged

nwparker merged 4 commits into
mainfrom
nwparker/wsl-orcad-pairing-repair

Conversation

@nwparker

@nwparker nwparker commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 2 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​173 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​173
Prod 9 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​226 $\color{#cf222e}{\Huge{\mathbf{−}}}$​58 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​168

ELI5

If a WSL host's Orca server forgets this desktop (its device list was lost, or the desktop was revoked), it refuses the desktop's saved pairing. SSH hosts already pair again automatically in that case. WSL hosts didn't: the connection stayed refused, and an update over it showed as "deferred" forever. WSL hosts now pair again too, with the same safety checks as SSH.

What Changed

  • Before: a WSL host that refused the enrolled token failed every connect. The update's terminal count couldn't authenticate, so updates read as deferred.
  • After:
  • Mechanism:
    • The repair gate (orcad-managed-pairing-repair.ts) now works over any orcad host transport, with an optional ports lookup that defaults to SSH's deployment. SSH behaviour is unchanged.
    • resolveWslOrcadPairing runs the shared buildWithPairingRepair.
    • When a reused bridge's pairing is refused, that bridge is retired before the failure is published, so the stale token can't be saved over the repair. Retiring it doesn't cancel an Update or Force queued behind it.
    • A user's Connect clears a standing repair failure or a spent cap, as an explicit SSH connect does.
    • The incumbent's terminal count uses the same enrolled-or-live pairing the connect uses.

Why

Reusing the SSH gate keeps one set of rules (cap, standing failure, pinned key) instead of a WSL copy. The distro runs on this machine, so reading its published offer is as trustworthy as SSH's read. The pinned-key check still refuses a server that isn't the one this desktop paired.

Linked Issue

None; follow-up from the review of #31684.

Visual Proof

N/A: no UI change.

Testing

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

Tests:

  • A refused token heals on the next connect, and the next update counts terminals with the new pairing.
  • A different host key never gets the token.
  • A repaired-then-refused pairing retires the bridge, and no failure stores the old token.
  • An Update queued behind a failing reconnect still runs.
  • A user's Connect clears the repair gate.

The SSH repair suites pass unchanged, alongside pnpm tc. The full static job passes locally except the orcad smoke, which fails the same way on a clean origin/main checkout here: no bundle manifest at out/mobile-web/manifest.json (ENOENT), because this machine has no mobile dependencies. CI's change-scope check skips the smoke for this PR. The WSL lane runs in CI. Verified live: nothing beyond CI.

Review

Codex review and an independent review.

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

WSL and the shared SSH repair gate. There is no wire change.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

@nwparker
nwparker force-pushed the nwparker/ssh-orcad-keep-enrolled-pairing branch from 360ec1d to e8f8f49 Compare October 22, 2026 01:15
@nwparker
nwparker force-pushed the nwparker/wsl-orcad-pairing-repair branch from 3c02993 to 65a14e9 Compare October 22, 2026 01:24
@nwparker
nwparker force-pushed the nwparker/ssh-orcad-keep-enrolled-pairing branch 2 times, most recently from e8f8f49 to 5109a40 Compare October 22, 2026 02:00
@nwparker
nwparker force-pushed the nwparker/wsl-orcad-pairing-repair branch from 65a14e9 to ec03666 Compare October 22, 2026 02:04
… enrolled token

A WSL host that lost its device registry, or revoked this desktop, refused the
enrolled token forever, and an update over it read as deferred. The connect now
re-pairs through the managed repair gate SSH uses (one repair at a time, a
capped number per window, only an offer under the pinned host key), reading the
host's published offer from the distro. The incumbent's terminal count uses the
same enrolled-or-live pairing the connect does.
…ser's Connect retry a repair

A refused or repaired-then-refused pairing on a reused bridge left its stale
token cached, and the failure status then saved it over the repair. That bridge
now closes first. A user-initiated Connect clears a standing repair failure or a
spent cap, as an explicit SSH connect does.
…nsport directly, and log refusals neutrally

A host still being added has no stored record for the gate to re-pair, so its
live bridge is reused as before. The WSL repair deps are typed with the WSL
transport, and the shared refusal log no longer says SSH for WSL.
@nwparker
nwparker force-pushed the nwparker/wsl-orcad-pairing-repair branch from ec03666 to a62d11d Compare October 22, 2026 02:31
@nwparker
nwparker changed the base branch from nwparker/ssh-orcad-keep-enrolled-pairing to main October 22, 2026 02:31
@coderabbitai

coderabbitai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

📝 Walkthrough

Managed pairing repair now accepts host-specific access and ports. WSL wiring supplies a repair gate to pairing resolution, which can verify and return a refreshed offer. WSL connection handling uses a matching active offer when no persisted offer exists and drops an existing bridge if pairing resolution fails. User-initiated WSL connections also clear pairing-repair failures for the requested environment.

Priority: ⬇️ Low

Merge Risk: 🔵 Low · up to a62d1

WSL pairing failures can display a misleading SSH-specific message. This is a bounded issue that can be corrected without blocking the connection workflow.

Pre-merge checks: Passed 3 · Failed 2

Failed Failed checks: 2 warnings

Check name Status Explanation Resolution
Description check Warning The description explains the user impact, implementation, rationale, tests, and platform considerations. However, the required Linked Issue section says "None" and does not link an actual issue. The t… Add a direct link to the issue addressed by this PR, such as the relevant follow-up issue, and document the status or CI coverage for pnpm lint, pnpm typecheck, pnpm test, and pnpm build.
Docstring Coverage Warning Docstring coverage is 41.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 12 functions across 11 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 3 passed
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: WSL hosts re-pair from the distro after refusing the enrolled token.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description explains the user impact, implementation, rationale, tests, and platform considerations. However, the required Linked Issue section says "None" and does not link an actual issue. The testing section also does not confirm all required commands.

Resolution

Add a direct link to the issue addressed by this PR, such as the relevant follow-up issue, and document the status or CI coverage for pnpm lint, pnpm typecheck, pnpm test, and pnpm build.

✨ Finishing Touches: 💡 2
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f272e0ed-c3dd-4ce4-84ef-6bc4846f1238
📥 Commits

Reviewing files that changed from the base of the PR and between 5793b05 and a62d11d.

📒 Files selected for processing: 11
  • src/main/managed-server/lifecycle/orcad-managed-bound-port.ts
  • src/main/managed-server/lifecycle/orcad-managed-pairing-repair.ts
  • src/main/managed-server/lifecycle/orcad-managed-tunnel-pairing-recovery.ts
  • src/main/wsl/wsl-host-connector.ts
  • src/main/wsl/wsl-host-service.test.ts
  • src/main/wsl/wsl-host-service.ts
  • src/main/wsl/wsl-orcad-connection-types.ts
  • src/main/wsl/wsl-orcad-connection.test.ts
  • src/main/wsl/wsl-orcad-connection.ts
  • src/main/wsl/wsl-orcad-pairing-identity.ts
  • src/main/wsl/wsl-orcad-pairing-repair.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review.

const record = (environmentId: string) => {
const found = findWslHostDeployment(userDataPath, environmentId)
if (!found) {
throw new OrcadManagedPairingRepairFailedError('this server is not a WSL host')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

rg -n 'class OrcadManagedPairingRepairFailedError|couldn.t pair with it again over SSH|OrcadManagedPairingRepairFailedError' src/main
sed -n '25,85p' src/main/wsl/wsl-orcad-pairing-repair.ts

Repository: stablyai/orca

Length of output: 6758


🏁 Script executed:

set -eu
printf '%s\n' '--- failure constructor ---'
nl -ba src/main/managed-server/lifecycle/orcad-managed-pairing-repair-failure.ts
printf '%s\n' '--- shared repair implementation ---'
nl -ba src/main/managed-server/lifecycle/orcad-managed-pairing-repair.ts | sed -n '1,330p'
printf '%s\n' '--- runtime-environment status owner ---'
nl -ba src/main/ipc/runtime-environments/runtime-environment-status-owner.ts | sed -n '1,130p'
printf '%s\n' '--- refusal handling ---'
nl -ba src/main/ipc/runtime-environments/runtime-environment-managed-pairing-refusal.ts | sed -n '1,130p'
printf '%s\n' '--- WSL recovery references ---'
rg -n -F --glob '*.ts' -e 'createWslOrcadPairingRecovery' -e 'wsl-orcad-pairing-repair' -e 'OrcadManagedPairingRepairFailedError' src/main

Repository: stablyai/orca

Length of output: 30119


🏁 Script executed:

set -eu
printf '%s\n' '--- WSL host connector ---'
nl -ba src/main/wsl/wsl-host-connector.ts
printf '%s\n' '--- WSL status/error consumers ---'
rg -n -F --glob '*.ts' -e 'authenticationRejected' -e 'runtimeHostStatusFailure' -e 'wsl-host-connector' -e 'connectionDependency' src/main/wsl src/main/ipc src/main | sed -n '1,240p'

Repository: stablyai/orca

Length of output: 17843


🏁 Script executed:

set -eu
printf '%s\n' '--- WSL connection manager ---'
nl -ba src/main/wsl/wsl-orcad-connection.ts
printf '%s\n' '--- WSL service contract and recovery call sites ---'
rg -n -F --glob '*.ts' -e 'pairingRecovery' -e 'WslOrcadConnectionManager' -e 'type WslOrcadConnection' -e 'interface WslOrcadConnection' src/main/wsl src/main/ipc

Repository: stablyai/orca

Length of output: 19204


🏁 Script executed:

set -eu
printf '%s\n' '--- error and WSL status helpers ---'
rg -n -F --glob '*.ts' -e 'export function errorMessage' -e 'function errorMessage' -e 'wslConnectFailedStatus' src/shared src/main/wsl
nl -ba src/shared/error-message.ts
nl -ba src/main/wsl/wsl-orcad-connection-status.ts
printf '%s\n' '--- WSL status forwarding ---'
nl -ba src/main/ipc/wsl-host-handlers.ts | sed -n '1,220p'

Repository: stablyai/orca

Length of output: 12986


Use transport-neutral wording for pairing repair failures.

OrcadManagedPairingRepairFailedError is used by both SSH and WSL repair. The WSL connection manager preserves error.message in the failed status, so a WSL user can see the SSH-specific text. Remove the transport-specific phrase from the shared error.

Suggested fix
-/** The host's server refuses this desktop and pairing again over SSH did not fix it. */
+/** The host's server refuses this desktop and pairing again did not fix it. */
 export class OrcadManagedPairingRepairFailedError extends Error {
   readonly code = ORCAD_PAIRING_REPAIR_FAILED_CODE
   constructor(reason: string) {
     super(
       `${ORCAD_PAIRING_REPAIR_FAILED_CODE}: the Orca server on this host no longer accepts this ` +
-        `computer, and Orca couldn't pair with it again over SSH: ${reason}. Nothing on the host ` +
+        `computer, and Orca couldn't pair with it again: ${reason}. Nothing on the host ` +
         `was stopped; its terminals can't be verified until Orca pairs again. Connect again to retry.`
     )

@nwparker
nwparker merged commit 1769476 into main Oct 22, 2026
146 of 210 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant