Skip to content

fix(browser): keep in-app browser logins when a WSL or managed SSH host re-pairs - #29610

Merged
nwparker merged 1 commit into
mainfrom
nwparker/stable-runtime-browser-partition
Oct 21, 2026
Merged

nwparker merged 1 commit into
mainfrom
nwparker/stable-runtime-browser-partition

Conversation

@nwparker

@nwparker nwparker commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 13 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​403 $\color{#cf222e}{\Huge{\mathbf{−}}}$​9 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​394
Prod 16 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​369 $\color{#cf222e}{\Huge{\mathbf{−}}}$​142 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​227

ELI5

When Orca runs its own server inside a WSL distro, the in-app browser pages for that host are shown on this computer and keep their own cookie jar here. That jar was named after the current "pairing" between this desktop and the server. Orca pairs again on its own whenever the host's pairing changes or the server drops this desktop, and every re-pair silently switched to a new, empty jar: the user was signed out of every site they had logged into for that host.

Now the jar is named after the host itself (which saved server it is, plus the server's own public key), so a re-pair keeps the same jar. A server with a different key is a different server and still gets its own, empty jar.

What Changed

  • Before: after a WSL host re-paired, the next browser page for that host opened in a fresh partition with no cookies.
  • After: it opens in the same partition, with the same cookies. Manually paired servers are unchanged.
  • Managed SSH hosts: the same identity rule applies to every server Orca deployed, but on current main their desktop tabs use the SSH browser route (keyed by the SSH target, already stable across re-pairs) and the host's own CLI uses the browser bridge, so they never host pages through this path today. Nothing changes for them in practice.

Mechanism:

  • paired-runtime-browser-authority-identity.ts (moved out of the client-host runtime): for an environment with an orcadDeployment, the authority identity is a digest of the Orca profile, the environment id and the server's public key. The pairing revision and paired device id, which rotate on each re-pair, are left out. Other environments keep exactly today's identity.
  • browser-route-partition-migration.ts: when the identity differs from what the shipping build derives (the "compatible" identity, today's pairing identity), a binding's fingerprint always follows the compatible identity, and the stable fingerprint is stored beside it in a new optional aliasFingerprints list. Existing jars are adopted from the current pairing, or from the older per-process scheme, as before.
  • browser-route-partition-binding-store.ts / -file.ts: lookups match the fingerprint or an alias; rebind and set take an optional alias. Aliases are capped at two and parsed leniently.

Why

The jar must outlive a re-pair but never be reachable by a different server. The environment id plus the pinned server key meet both: a re-pair keeps them, a reinstalled or foreign server has a different key.

Keeping the shipping build's fingerprint as the record's primary key, with the stable one as an alias, keeps mixed desktop versions working. An older build reads only fingerprint, so after a downgrade it still finds the same jar at whatever pairing it is on, instead of opening an empty one or failing with browser_route_partition_binding_conflict. Rewriting the fingerprint outright (the existing runtimeId migration's approach) would break a downgrade; a separate alias file would need its own cleanup on removal and eviction.

This replaces the earlier version of this PR (pairing history in the environment records, WSL registration GUIDs in the identity, alias-only adoption). Keying on the pinned key alone already separates a re-imported distro whose orcad generated a new key, and it removes the record-schema changes and the registry read that the follow-up #31289 needed.

ref-oss check: other remote editors key per-remote local storage by the durable remote address and never by session credentials; that matches this approach, which did not change.

Linked Issue

N/A (maintainer).

Visual Proof

N/A: no UI change. The behavior is covered by partition and session-registry tests.

Testing

  • I manually tested these changes locally (covered by the Docker end-to-end run instead)
  • Automated tests added/updated, or explained why not below

Unit (paired-runtime-browser-client-host-route-identity.test.ts, binding store and migration tests):

  • Managed SSH and WSL keep one identity across a re-pair (new revision, device id and token) and still separate a different key or environment. This test fails on main.
  • An older build's jar is adopted, survives a re-pair, and a downgraded build (reads only fingerprint) reopens it both before and after the re-pair. An older build's rewrite that drops aliases is re-adopted without a binding conflict.
  • A jar minted fresh by this build is also visible to a downgraded build at every pairing.
  • A per-process (runtimeId-era) jar is adopted under the fingerprint an older build reads.
  • Manually paired servers keep the pairing identity unchanged.
  • A page the re-paired server opens while the old pairing's pages are still open joins the same jar instead of failing with a binding conflict (registry test).

End to end: not run live. The managed SSH Docker lane cannot exercise this path (managed SSH tabs never become desktop-hosted pages, confirmed by a spec I wrote and then removed), and the WSL lane drives host RPC only, with no browser. The Docker managed-orcad lane (ssh-orcad-pairing-repair, ssh-orcad-browser-routing, paired-client-hosted-browser-cookie-survival) passed on this change.

Local checks: the full static analysis and typecheck job steps, and the src/main/browser and src/main/ipc/runtime-environments unit folders single-worker (the only local failures, in browser-manager-tab-identity, browser-manager-viewport-ownership, the GC retention tests and runtime-environment-session-tabs-delta, fail identically on main locally).

Known limitations (nothing is deleted in any of them):

  • If the upgrade itself re-pairs the host before the first client-hosted page opens, the old jar is not found and the user starts with an empty jar once. Pairings before the current one are not recorded.
  • If an older build rewrites the binding file (dropping the alias) and the host then re-pairs on that older build, the next upgrade returns to this build's jar and does not see cookies set during the downgrade.

AI Disclosure

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

No wire change. The only persisted change is the optional aliasFingerprints field in the desktop-local partition binding file; older builds ignore it.

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)

@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

📝 Walkthrough

Paired-runtime browser authority identities now include a pairing identity and a shared derivation function. Page preparation passes a compatible route identity to partition resolution. Binding stores can retain and match alias fingerprints, allowing compatible or verified legacy bindings to be adopted. Tests cover managed-host re-pairing, older-build compatibility, partition reuse, and cookie retention.

Priority: ➖ Normal

Merge Risk: 🔵 Low · up to b77de

This change keeps in-app browser logins working when a managed SSH or WSL host re-pairs. The reviewed logic shows no confirmed functional defect. One follow-up is needed: the Docker re-pair end-to-end test does not run when two of the re-pair modules change. A later regression in those modules could therefore merge without that test running. The change is mergeable once the test's file filter is extended.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 58 functions across 44 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
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.
Title check Passed The title clearly describes the primary change: preserving in-app browser logins when managed SSH or WSL hosts re-pair.
Description check Passed The description follows the repository template and explains the user impact, mechanism, rationale, compatibility behavior, testing, limitations, and checklist status. The maintainer appropriately mar…
Full details: Description check

Explanation

The description follows the repository template and explains the user impact, mechanism, rationale, compatibility behavior, testing, limitations, and checklist status. The maintainer appropriately marks the linked issue as N/A, and the lack of visual proof is justified because there is no UI change.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • 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.

@nwparker
nwparker force-pushed the nwparker/stable-runtime-browser-partition branch from 7d0b11a to e3b42f8 Compare October 16, 2026 10:45
@nwparker

Copy link
Copy Markdown
Contributor Author

SSH coverage: this PR changes the browser identity for managed SSH (orcad) hosts, but the PR's own run skipped the SSH Docker lane because of its path filter. I dispatched the e2e workflow on this head (e3b42f8): https://github.com/stablyai/orca/actions/runs/38889312626. Both ssh on managed orcad (Docker 1/2, 2/2) shards and changed e2e specs passed.

@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: 650a3f85-fc20-45d5-a8d2-a29a147f5782
📥 Commits

Reviewing files that changed from the base of the PR and between 7d0b11a7b5fee68b2e0913c9fb7265aa8ba0a2fb and b77de0947e874e01d83a044e403190e39c8ac7ed.

📒 Files selected for processing: 31
  • config/scripts/pr-e2e-source-routing.mjs
  • src/main/browser/browser-client-page-command-executor-dependencies.ts
  • src/main/browser/browser-client-page-command-executor-fencing.test.ts
  • src/main/browser/browser-client-page-command-executor-test-harness.ts
  • src/main/browser/browser-client-page-command-executor.test.ts
  • src/main/browser/browser-client-page-command-executor.ts
  • src/main/browser/browser-client-page-command-integration.test.ts
  • src/main/browser/browser-client-page-creation.ts
  • src/main/browser/browser-client-page-execution-host-supersession.test.ts
  • src/main/browser/browser-client-page-reconciliation-adapters.test.ts
  • src/main/browser/browser-client-page-unavailability.test.ts
  • src/main/browser/browser-client-route-cookie-import-partition-parity.test.ts
  • src/main/browser/browser-client-route-cookie-import.test.ts
  • src/main/browser/browser-client-route-cookie-import.ts
  • src/main/browser/browser-route-partition-binding-file.ts
  • src/main/browser/browser-route-partition-binding-store-fake.ts
  • src/main/browser/browser-route-partition-binding-store.test.ts
  • src/main/browser/browser-route-partition-binding-store.ts
  • src/main/browser/browser-route-partition-migration.test.ts
  • src/main/browser/browser-route-partition-migration.ts
  • src/main/browser/browser-route-partition-storage-retirement.test.ts
  • src/main/browser/browser-route-session-partition-binding.ts
  • src/main/browser/browser-route-session-registry-contract.ts
  • src/main/browser/browser-route-session-registry.ts
  • src/main/browser/browser-route-session-runtime.ts
  • src/main/browser/browser-route-session-state.ts
  • src/main/browser/paired-runtime-browser-authority-identity.ts
  • src/main/browser/paired-runtime-browser-client-host-composition.test.ts
  • src/main/browser/paired-runtime-browser-client-host-route-identity.test.ts
  • src/main/browser/paired-runtime-browser-client-host-runtime.ts
  • tests/e2e/ssh-orcad-browser-re-pair-cookies.spec.ts
🚧 Files skipped from review as they are similar to previous changes: 1
  • src/main/browser/browser-route-partition-migration.test.ts

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

specs: ['tests/e2e/ssh-orcad-browser-re-pair-cookies.spec.ts'],
matches: (file) =>
isProductSource(file) &&
/^src\/main\/browser\/(?:paired-runtime-browser-(?:authority-identity|client-host-runtime)|browser-route-partition-(?:migration|binding-store|binding-file)|browser-client-page-creation|browser-client-route-cookie-import)\.ts$/.test(

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add the session-registry and session-binding modules to the re-pair route.

The ssh.orcad-browser-re-pair-cookies route does not match src/main/browser/browser-route-session-registry.ts or src/main/browser/browser-route-session-partition-binding.ts. Both files are on the path that this spec exercises:

  • assertReusable in browser-route-session-registry.ts now decides whether a live partition is reused after a re-pair. Before this change, the same case threw browser_route_partition_binding_conflict.
  • persistBrowserRouteSessionBinding and resolveBrowserRouteSessionPartition in browser-route-session-partition-binding.ts forward compatibleIdentity and persist aliasFingerprint.

A later PR can break one of these files and the Docker re-pair lane will not run. The author already reported that the path filter skipped the SSH Docker lane for this PR. Add both modules to the pattern.

Proposed fix
--- "a/config/scripts/pr-e2e-source-routing.mjs"
+++ "b/config/scripts/pr-e2e-source-routing.mjs"
@@ -182,7 +182,7 @@
     specs: ['tests/e2e/ssh-orcad-browser-re-pair-cookies.spec.ts'],
     matches: (file) =>
       isProductSource(file) &&
-      /^src\/main\/browser\/(?:paired-runtime-browser-(?:authority-identity|client-host-runtime)|browser-route-partition-(?:migration|binding-store|binding-file)|browser-client-page-creation|browser-client-route-cookie-import)\.ts$/.test(
+      /^src\/main\/browser\/(?:paired-runtime-browser-(?:authority-identity|client-host-runtime)|browser-route-partition-(?:migration|binding-store|binding-file)|browser-route-session-(?:registry|partition-binding)|browser-client-page-creation|browser-client-route-cookie-import)\.ts$/.test(
         file
       )
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/^src\/main\/browser\/(?:paired-runtime-browser-(?:authority-identity|client-host-runtime)|browser-route-partition-(?:migration|binding-store|binding-file)|browser-client-page-creation|browser-client-route-cookie-import)\.ts$/.test(
/^src\/main\/browser\/(?:paired-runtime-browser-(?:authority-identity|client-host-runtime)|browser-route-partition-(?:migration|binding-store|binding-file)|browser-route-session-(?:registry|partition-binding)|browser-client-page-creation|browser-client-route-cookie-import)\.ts$/.test(

…st re-pairs

Client-hosted browser pages for a server Orca deployed (WSL hosts today; managed
SSH desktop tabs use the SSH route) now derive their partition from the
environment and the server's public key, not the pairing revision and device id
that rotate on every re-pair. Existing jars are adopted, and each binding keeps
the shipping build's fingerprint (with the stable one as an alias) so a
downgraded build still opens the same jar.
@nwparker
nwparker force-pushed the nwparker/stable-runtime-browser-partition branch from b77de09 to 57fe0cd Compare October 21, 2026 01:39
@nwparker nwparker changed the title fix(browser): keep in-app browser logins when a managed SSH or WSL host re-pairs fix(browser): keep in-app browser logins when a WSL or managed SSH host re-pairs Oct 21, 2026
@nwparker
nwparker merged commit 60b8eb4 into main Oct 21, 2026
45 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