Skip to content

fix: prevent local session publication from claiming paired host tabs - #25958

Open
nwparker wants to merge 7 commits into
mainfrom
nwparker/fix-foreign-session-publication
Open

nwparker wants to merge 7 commits into
mainfrom
nwparker/fix-foreign-session-publication

Conversation

@nwparker

@nwparker nwparker commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​332 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​332
Prod 5 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​91 $\color{#cf222e}{\Huge{\mathbf{−}}}$​16 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​75

ELI5

A desktop showing another paired host's files and terminals must not advertise them to its clients as its own work.

What Changed

Exclude foreign editors and terminals from local session inventories and mounted or parked runtime graphs. Editor ownership follows the captured opening route, including SSH reached through a paired host. Terminal ownership follows canonical tabs and remote PTY handles, including legacy IDs and cold tabs. Contradictory terminal owner stamps are withheld. Local files and direct SSH continue to publish; drafts and saved sessions remain intact.

Why

The old publisher stripped ownership and claimed foreign rows locally. Receiving clients cannot reconstruct authority that a producer discarded. Filtering at publication fixes that producer; #25954 independently protects the receiver.

Linked Issue

Part of #21489. Independent PR targeting main; no dependency on #25954.

Visual Proof

Production publication and snapshot application ran inside a rebuilt hidden macOS Electron renderer with synthetic WSL/Mac frames. Before, the foreign file was advertised and another host replaced its tab. After, publication omits it and the original owner/file header survives. This is rendered ownership proof, not live remote file I/O.

Before
After

Testing

  • Relevant failures reproduced before their fixes; automated regressions retained. Rebase-specific failures and fixes are described below.
  • Rebased assembled application tree: 6,117 tests passed (four skips); full typecheck and changed-code quality passed, with zero findings across 151 changed files.
  • Fresh app and CLI builds; four hidden macOS flows passed: open/edit/save, first-mount agent/Setup PTY identity, GUI last-host archive, and separate CLI last-host archive. The final main refresh changes only CI files; the application tree is identical to this tested tree.
  • The new ten-shard CI planner from main passes all 82 focused tests.
  • Earlier-base isolated native Windows and Linux runs passed the same four flows: Windows, Linux. These are historical evidence, not verification of this rebased head.
  • Required CI for rebased head 4bd05b5353a3; wait for current-head checks before merging.

Review

The review reproduced publication of an SSH editor reached through a paired host, and publication of a cold terminal with contradictory host stamps. Captured routes and the shared ownership index now exclude both from local inventories and graphs. Local/direct SSH controls continue to publish; filtering leaves drafts intact.

The series includes local/direct SSH isolation, folder workspaces, and remote authority coverage. Real Windows+WSL reproduction of the original damaged profile and a native nested SSH recovery/save journey remain unverified. #25938 and the independent CI memory fix #26049 are merged.

Rebased onto main 00984ccb2504, including managed SSH servers (#24863) and target-owned SSH session partitions (#26088). Publication continues to use captured ownership and exclude foreign rows without a wire change. Low merge risk once current-head CI passes.

Agent skill upstream boundary

  • Not applicable.

Checklist

  • Explained user-facing behavior, mechanism, and tradeoffs.
  • Visual proof attached above, or N/A with reason.
  • Self-reviewed correctness, data preservation, and performance.
  • Cross-platform, SSH, folder-workspace, and compatibility impact considered.
  • Current-head CI is green before merge.

@nwparker
nwparker marked this pull request as draft October 6, 2026 20:18
@nwparker
nwparker force-pushed the nwparker/fix-session-snapshot-host-isolation branch from edacd69 to f6681db Compare October 6, 2026 21:11
@nwparker
nwparker force-pushed the nwparker/fix-foreign-session-publication branch from b491afc to ad4894e Compare October 6, 2026 21:12
@nwparker
nwparker changed the base branch from nwparker/fix-session-snapshot-host-isolation to main October 6, 2026 21:12
@nwparker
nwparker force-pushed the nwparker/fix-foreign-session-publication branch from ad4894e to 5c7a712 Compare October 6, 2026 22:46
@nwparker
nwparker marked this pull request as ready for review October 6, 2026 23:30
@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

📝 Walkthrough

Walkthrough

Runtime-graph and mobile-session publication now use execution-host and runtime metadata to filter runtime-owned editors and terminals. A terminal execution-host index records host IDs by tab and entity ID, and marks conflicting assignments as unknown. Added tests cover ownership-based publication behavior. The SQLite runtime test include list now includes the agent-launch instant-tab test.

Priority: ⬇️ Low

Merge Risk: 🟡 Moderate · up to a4981

The change mostly prevents a desktop from advertising another paired host's editors and terminals. However, a mounted terminal that is still connecting to a remote host can briefly be published as a local terminal before its ownership is recorded. Include live pane PTY identities in the ownership check before merging.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 6 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 and concisely describes the primary change: preventing local session publication from claiming paired host tabs.
Description check ✅ Passed The description is complete and relevant. It explains the user impact, implementation, rationale, linked issue, visual proof, testing, review considerations, and checklist status. It also clearly stat…
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
  • Autopilot · 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 left a comment •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The review reproduced publication of an SSH editor reached through a paired host, and publication of a cold terminal with contradictory host stamps. Captured routes and the shared ownership index now exclude both from local inventories and graphs. Local/direct SSH controls continue to publish; filtering leaves drafts intact.

Final assembled verification: 6,313 tests pass (five skips) in 563 suites, plus 48 upstream authority tests and 81 serial compatibility tests. Typecheck and changed-code quality pass (147 files, zero findings). Fresh hidden macOS and isolated Windows/Linux each pass all four native flows. Windows: https://github.com/stablyai/orca/actions/runs/37556420437. Linux: https://github.com/stablyai/orca/actions/runs/37557129429. Current-head CI is green on a4981b22687e; merge recommended. Contributor originals remain open until their replacements merge.

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

⚠️ Outside diff range comments (1)

🟠 Major · Include live pane PTYs in the ownership filter. · graph-publication.ts:81-85

src/renderer/src/runtime/sync-runtime-graph/graph-publication.ts:81-85
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Include live pane PTYs in the ownership filter.

When a mounted pane's transport already has a remote-runtime PTY, but the tab and saved layout have not stored that PTY yet, isRemoteRuntimeTerminalTab accepts the tab. The subsequent graph.leaves.push publishes the remote PTY through the local mounted-tab path.

Pass the live pane PTY IDs to the predicate before publishing the tab and leaves.

🐛 Suggested fix
diff --git a/src/renderer/src/runtime/sync-runtime-graph/mobile-session-surfaces.ts b/src/renderer/src/runtime/sync-runtime-graph/mobile-session-surfaces.ts
@@
   tab: Pick<NonNullable<AppState['tabsByWorktree'][string]>[number], 'id' | 'ptyId'>,
   layout: AppState['terminalLayoutsByTabId'][string] | undefined,
-  executionHostId?: ExecutionHostId | null
+  executionHostId?: ExecutionHostId | null,
+  livePtyIds: readonly (string | null | undefined)[] = []
 ): boolean {
@@
-  const ptyIds = [tab.ptyId, ...layoutPtyIds].filter(
+  const ptyIds = [tab.ptyId, ...layoutPtyIds, ...livePtyIds].filter(
diff --git a/src/renderer/src/runtime/sync-runtime-graph/graph-publication.ts b/src/renderer/src/runtime/sync-runtime-graph/graph-publication.ts
@@
     if (!tab) {
       continue
     }
+    const manager = registeredTab.getManager()
+    const livePtyIds =
+      manager?.getPanes().map((pane) => registeredTab.getPtyIdForPane(pane.id)) ?? []
     if (
       isRemoteRuntimeTerminalTab(
         tab,
         state.terminalLayoutsByTabId[registeredTab.tabId],
-        terminalHostsByWorktree.get(registeredTab.worktreeId)?.get(tab.id)
+        terminalHostsByWorktree.get(registeredTab.worktreeId)?.get(tab.id),
+        livePtyIds
       )
     ) {
       continue
     }
-    const manager = registeredTab.getManager()

ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3710626e-e418-4f44-94ea-85acff01873f
📥 Commits

Reviewing files that changed from the base of the PR and between 46793f2 and a4981b2.

📒 Files selected for processing (5)
  • config/scripts/vitest-sqlite-database-runtime-files.mjs
  • src/renderer/src/lib/terminal-tab-execution-hosts.ts
  • src/renderer/src/runtime/sync-runtime-graph-foreign-host-publication.test.ts
  • src/renderer/src/runtime/sync-runtime-graph/graph-publication.ts
  • src/renderer/src/runtime/sync-runtime-graph/mobile-session-surfaces.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.

@nwparker
nwparker force-pushed the nwparker/fix-foreign-session-publication branch from a4981b2 to 4bd05b5 Compare October 7, 2026 20:26

@nwparker nwparker left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Adversarial self-review of rebased head 4bd05b5353a3.

Rebased onto main 00984ccb2504, including managed SSH servers (#24863) and target-owned SSH session partitions (#26088). Publication continues to use captured ownership and exclude foreign rows without a wire change. Low merge risk once current-head CI passes.

Validation of the assembled rebased application tree: 6,117 tests passed (four skips), full typecheck, zero changed-code quality findings across 151 files, fresh app/CLI builds, and all four hidden macOS flows. The final main refresh is CI-only and its 82 planner tests pass. Earlier Windows/Linux native runs were on the previous base; current-head CI must pass before merge.

Contributor references and coauthor trailers are preserved. The original damaged Windows+WSL profile and a native nested SSH recovery/save journey remain unverified; this does not justify closing #21489. No PRs were merged or superseded contributor PRs closed during this rebase.

This branch has not been deployed

No deployments
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