Skip to content

fix(github): fail closed instead of running client git against a remote repoPath when the SSH provider is unregistered - #14945

Merged
brennanb2025 merged 9 commits into
mainfrom
brennanb2025/boundary-client-git
Aug 17, 2026
Merged

brennanb2025 merged 9 commits into
mainfrom
brennanb2025/boundary-client-git

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Aug 16, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 5 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​408 $\color{#cf222e}{\Huge{\mathbf{−}}}$​1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​407
Prod 10 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​233 $\color{#cf222e}{\Huge{\mathbf{−}}}$​97 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​136

The rule

For an SSH-hosted repo, an operation on a remote repoPath must never fall back to running on the client machine. "We could not ask" has to fail closed, not answer. The codebase already states and enforces this:

  • src/main/source-control/repo-default-branch.ts:76-78 — "a dropped SSH provider must not fall back to local git — the repoPath is remote, so a local run could answer for the wrong repo"
  • src/main/repo-worktrees.ts:45-48
  • src/main/runtime/orca-runtime.ts — "fail closed to unknown instead of probing a server path on the desktop filesystem"
  • src/renderer/src/lib/connection-context.ts:22-24
  • src/main/runtime/orca-runtime-git.ts enforces it ~33 times by throwing when connectionId is set but the provider is missing

getSshGitProvider returns undefined (it does not throw) when a connection is unregistered, so the boundary has to be checked explicitly.

The two sites

Both in src/main/github/client.ts, same shape:

const provider = connectionId ? getSshGitProvider(connectionId) : null
const result = provider ? await provider.exec(...) : await gitExecFileAsync(..., { cwd: repoPath })
  1. getCurrentHeadOid (rev-parse HEAD)
  2. probeTrackedUpstreamBranches (for-each-ref refs/heads)

When connectionId is set but the provider is unregistered — connection dropped, or not yet reattached — the ternary silently selected the local branch and ran client git with cwd set to a remote path. On a machine where a same-named path exists locally, it returns the wrong repository's answer instead of failing.

getCurrentHeadOid feeds shouldHideMergedImplicitPR, so a wrong OID silently changes which PR the UI attributes to a worktree.

The fix

Both functions already have a natural "unknown" return, so no new signalling was needed:

  • getCurrentHeadOid → null
  • probeTrackedUpstreamBranches → { probeFailed: true, upstreamsByBranchName: new Map() }

The guard is lifted above the try and mirrors repo-default-branch.ts exactly. probeFailed: true also keeps the empty snapshot out of the tracked-upstream cache, so the probe re-runs once the provider reattaches rather than pinning an empty result for the TTL.

Local and WSL behavior is unchanged. The new branch is reached only when connectionId is truthy; wslDistro still routes through gitExecFileAsync with { cwd, wslDistro } exactly as before, and both WSL paths are pinned by new tests.

Red-first evidence

New suite: src/main/github/client-ssh-provider-execution-boundary.test.ts (6 tests), built on the existing client-test-mocks / client-test-harness rig used by client-merged-pr-visibility.test.ts and client-tracked-upstream-snapshot.test.ts. It follows the precedent set by client-pr-local-runtime.test.ts ("never falls through to the default gh host for an unresolved SSH repository"), asserting that the local exec mock is not called.

Verified red by reverting client.ts to HEAD and running the new suite unchanged:

FAIL  client-ssh-provider-execution-boundary.test.ts > does not rev-parse HEAD locally when the SSH provider is unregistered
AssertionError: expected "vi.fn()" to not be called at all, but actually been called 1 times
  1st vi.fn() call:
    [ [ "rev-parse", "HEAD" ], { "cwd": "/remote/repo" } ]

FAIL  client-ssh-provider-execution-boundary.test.ts > does not read tracked upstreams locally when the SSH provider is unregistered
AssertionError: expected "vi.fn()" to not be called at all, but actually been called 1 times
  1st vi.fn() call:
    [ [ "for-each-ref", "--format=%(refname)%00%(upstream)", "refs/heads" ], { "cwd": "/remote/repo" } ]

Tests  2 failed | 4 passed (6)

The failure output is the bug: local git invoked with cwd: /remote/repo. With the fix restored, 6/6 pass.

The 4 tests that pass in both runs are deliberate non-regression controls — they pin that a registered provider still gets provider.exec, and that a WSL repo still gets gitExecFileAsync(..., { cwd, wslDistro }) — so the guard cannot be over-broad.

Gates

  • vitest run --config config/vitest.config.ts src/main/github/ — 61 files, 655 tests, all pass
  • oxlint on both changed files — clean (verified the gate is live by linting a probe file with an injected no-unused-vars + no-debugger, which reported both)
  • tsc --noEmit -p config/tsconfig.node.json — exit 0 (src/main/**/* covers the new test file)
  • oxfmt (no prettier); commit passed lint-staged incl. the react-doctor pass

Scope

Two call sites only. No behavior change for local or WSL repos, and no change to what the SSH path does when a provider is registered.

@coderabbitai

coderabbitai Bot commented Aug 16, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 161aeec3-71df-4f7c-ad32-019ec371ce00

📥 Commits

Reviewing files that changed from the base of the PR and between 3c8410d and 8d715ab.

📒 Files selected for processing (2)
  • src/main/github/client-ssh-provider-execution-boundary.test.ts
  • src/main/github/client.ts

Included review availability: Your plan includes up to 10 reviews per rolling hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

The change updates PR branch resolution to resolve SSH Git providers before executing Git operations. Missing SSH providers now return no head or an empty upstream result without using local Git. WSL repositories continue to use the local Git runtime with configured options. New tests cover provider routing, command arguments, fallback suppression, GitHub lookup counts, and current-branch or upstream PR results.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description gives detailed change, rationale, scope, and test results, but omits the required Linked Issue, Visual Proof, and most template sections. Add the missing template sections, provide a valid Fixes #... link, mark Visual Proof N/A with a reason, and complete applicable checklist items.
✅ Passed checks (4 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 main fix: preventing client-side Git execution when an SSH provider is unregistered.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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.

getCurrentHeadOid and probeTrackedUpstreamBranches only routed through the
SSH provider when one was registered. With connectionId set but the provider
unregistered (dropped connection, not yet reattached) they fell through to
client-side git with cwd pointing at the remote repoPath — on a machine with
a same-named local path that silently answers for the wrong repository.

getCurrentHeadOid feeds shouldHideMergedImplicitPR, so a wrong OID changes
which PR the UI attributes to a worktree.

Both now take their existing unknown path (null / probeFailed) instead,
matching repo-default-branch.ts. Local and WSL routing is unchanged.
@brennanb2025
brennanb2025 force-pushed the brennanb2025/boundary-client-git branch from 8d715ab to 817ae27 Compare August 17, 2026 03:27
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review verdict: code-approved after fixes at 0edf8f92b04262ca7c0daf3dc9664553773d7c3d, but do not merge until the newly queued CI completes.

The review found and fixed several execution-boundary issues: missing SSH providers could fall back to client Git, transient SSH probe/auth failures could collapse into no-pr or clear cached PR state, tolerant rate-limit preflights inherited strict behavior, and SSH repository identity caches were not isolated across provider generations. Repeated same-model adversarial review and the end readiness pass are now clean with no remaining P0/P1/P2 findings.

Observed validation on the exact pushed head:

  • 62 GitHub/remote URL test files passed, 672 tests total.
  • Full node/CLI/web typecheck passed.
  • Changed-file oxlint, max-lines ratchet, and git diff --check passed.
  • Ubuntu 20.04 / glibc 2.31 / Git 2.25.1 SSH relay deployment succeeded.
  • CI for this exact head is currently queued, including Node 24 and Windows jobs; local tests ran on Node 26.5.0.

Electron QA used the exact worktree build through Playwright CDP. The child dispatch path was consumer-fenced, so I captured the evidence directly. The exact build rendered successfully, but initiating the real SSH connection made the CDP endpoint stop responding; therefore the post-connect/disconnect UI refresh leg is unverifiable, not passed. No Windows/WSL UI leg was observed.

Exact Orca Electron build used for QA

@brennanb2025
brennanb2025 merged commit 8e9b5c9 into main Aug 17, 2026
45 checks passed
paidaxingyo666 pushed a commit to paidaxingyo666/Manta that referenced this pull request Aug 21, 2026
…te repoPath when the SSH provider is unregistered (stablyai#14945)

* fix(github): fail closed when the SSH git provider is gone

getCurrentHeadOid and probeTrackedUpstreamBranches only routed through the
SSH provider when one was registered. With connectionId set but the provider
unregistered (dropped connection, not yet reattached) they fell through to
client-side git with cwd pointing at the remote repoPath — on a machine with
a same-named local path that silently answers for the wrong repository.

getCurrentHeadOid feeds shouldHideMergedImplicitPR, so a wrong OID changes
which PR the UI attributes to a worktree.

Both now take their existing unknown path (null / probeFailed) instead,
matching repo-default-branch.ts. Local and WSL routing is unchanged.

* fix(github): preserve PR state when SSH probes fail

* fix(github): keep failed SSH discovery unverifiable

* fix(github): propagate SSH identity failures

* fix(github): scope verified SSH identity probes

* test(github): preserve tolerant resolver calls

* fix(github): preserve indeterminate auth discovery

* fix(github): isolate SSH repository probe generations

* test(github): expose SSH probe generation in mocks
enrick-dev pushed a commit to enrick-dev/orca that referenced this pull request Oct 15, 2026
…te repoPath when the SSH provider is unregistered (stablyai#14945)

* fix(github): fail closed when the SSH git provider is gone

getCurrentHeadOid and probeTrackedUpstreamBranches only routed through the
SSH provider when one was registered. With connectionId set but the provider
unregistered (dropped connection, not yet reattached) they fell through to
client-side git with cwd pointing at the remote repoPath — on a machine with
a same-named local path that silently answers for the wrong repository.

getCurrentHeadOid feeds shouldHideMergedImplicitPR, so a wrong OID changes
which PR the UI attributes to a worktree.

Both now take their existing unknown path (null / probeFailed) instead,
matching repo-default-branch.ts. Local and WSL routing is unchanged.

* fix(github): preserve PR state when SSH probes fail

* fix(github): keep failed SSH discovery unverifiable

* fix(github): propagate SSH identity failures

* fix(github): scope verified SSH identity probes

* test(github): preserve tolerant resolver calls

* fix(github): preserve indeterminate auth discovery

* fix(github): isolate SSH repository probe generations

* test(github): expose SSH probe generation in mocks
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