Skip to content

feat(ssh): port the SSH connection work ledger and transport close ledger (#16741 T2) - #24210

Merged
OrcaWin merged 2 commits into
mainfrom
OrcaWin/node-rt-p3-t2a
Oct 1, 2026
Merged

OrcaWin merged 2 commits into
mainfrom
OrcaWin/node-rt-p3-t2a

Conversation

@OrcaWin

@OrcaWin OrcaWin commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator
Files Added Deleted Net
Test 5 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​458 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​458
Prod 4 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​332 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​332

ELI5

This is the first slice of #16741's T2 track (SSH core). It adds a per-connection work ledger that tracks in-flight operations and channels, so a later reset can drain cleanly, plus a transport close ledger. Nothing uses them yet, so behavior doesn't change.

What Changed

  • ssh-connection-work-ledger.ts: tracks operations and channel lifetimes, and blocks new work once a reset starts.
    • Work nested under an operation it already admitted, and one exactly identified control channel, can still run.
    • A failure or unverifiable opening after that point fails the drain, and the drain stays failed.
  • Transport close ledger and close observation.
  • Adapted from feat(orcad): consolidate Bun runtime and SSH/Remote migration #16741:
  • Porting notes are in each commit.

Why

Design D9: these are the T2 foundations that SshConnection wiring and T3 reset build on.

Linked Issue

Part of the Node runtime plan (Phase 3). Stacked on #24185, with #24186 merged in.

Visual Proof

N/A. Nothing uses this code yet.

Testing

  • The ported ledger, channel-lifetime and forward-socket-admission tests pass.

  • Not wired yet:

    • the relay grace-lifecycle drain, which needs host-side handling of a closed admission;
    • SshConnection integration;
    • profile-lifetime admission, which needs a decision on the native addon versus SQLite authority.
  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

@greptile-apps

greptile-apps Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Adds SSH connection and transport lifecycle tracking.

The PR appears safe to merge as an unwired foundation for later SSH reset integration.

Summary

The PR adds per-connection SSH work and channel-lifetime tracking, plus transport-close tracking and observation. The new ledgers are not yet wired into SshConnection; this change adds their implementations and tests without changing the active connection flow.

Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Admit SSH work] --> B[Track operation or channel]
  B --> C[Fence new work for reset]
  C --> D[Drain admitted work]
  D --> E[Observe transport close]
Loading

Reviews (3) · Last reviewed commit: "feat(ssh): add SSH transport close ledge..."

@greptile-apps

greptile-apps Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Comments Outside Diff

These findings could not be posted inline.

  • P1 Required listener can be missing src/main/runtime/runtime-rpc/runtime-rpc-lifecycle.ts:78 ▶

    When requirePinnedWsPort is true, a device-registry or encryption-key initialization failure takes this branch and startup still succeeds with only the Unix socket. The managed SSH tunnel then has no WebSocket listener at its required port. Required-port startup should fail when pairing identity initialization prevents that listener from starting.

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

ℹ️ No critical issues — one API-consistency note inline, a couple of defer-able observations below.

Reviewed changes

  • Per-connection work ledger (src/main/ssh/ssh-connection-work-ledger.ts): tracks operations and channels under an AsyncLocalStorage scope, admits nested work only under an already-admitted non-exempt parent after fenceForReset(), and drains cancellably while retaining the first failure.
  • Channel/socket lifetime tracking (src/main/ssh/ssh-connection-channel-lifetime.ts): binds each open→close to a ledger entry; an untrackable open result is marked unverifiable rather than settled.
  • Transport close ledger and observation (src/main/ssh/ssh-transport-close-ledger.ts, ssh-transport-close-observation.ts): wait for every allocated client's real close (failed-auth included) and refuse allocations added after the drain snapshot.
  • WebSocket lifecycle extraction and strict bind (src/main/runtime/rpc/node-websocket-lifecycle.ts, websocket-transport-limits.ts, ws-transport.ts; from #24186, merged in): handlers and stop() extracted order-equivalently, stop() now also calls closeAllConnections(), and strictPort / requirePinnedWsPort fails closed instead of falling back when a managed tunnel needs one port.
  • Tests for all of the above (33 cases), all passing locally.

ℹ️ Nitpicks

  • src/main/ssh/ssh-connection-work-ledger.ts:44-48 — markTransportUnverifiable() is a silent no-op before fenceForReset(), unlike beginChannelOpen().markUnverifiable(), which persists its error on the entry even pre-fence. Fine if the reset flow always fences first; otherwise a connection-level failure can vanish before the fence.
  • src/main/ssh/ssh-connection-work-ledger.ts:90-132 — beginSession() is the only public method in the port with no test coverage, and it owns non-trivial closed / closeFailed / active state. Close-before-drain, close-with-error mid-flight, and run-after-close would pin it.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Comment on lines +35 to +37
isDrained(): boolean {
return this.pending.size === 0 && !this.failure
}

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.

isDrained() counts the exempt control entry as pending, while drain() and assertDrained() deliberately exclude it. After a legitimate drain with a live control channel (ssh-connection-work-ledger.test.ts:216-233), fence.assertDrained() passes but isDrained() still reports false — anything that gates reset completion on isDrained() would never see it finish. Consider excluding this.exempt (or documenting isDrained() as the pre-fence variant) and adding a matching test.

Technical details
# isDrained() disagrees with the fence's drained definition

## Affected sites
- `src/main/ssh/ssh-connection-work-ledger.ts:35-37` — `isDrained()` returns `pending.size === 0 && !failure`
- `src/main/ssh/ssh-connection-work-ledger.ts:169-175` — `assertDrained()` filters `entry !== this.exempt`
- `src/main/ssh/ssh-connection-work-ledger.ts:184` — `drain()` filters the exempt entry too

## Required outcome
After a legitimate drain that leaves the exempt control channel open, `isDrained()` and the fence's `assertDrained()` return the same verdict.

## Suggested approach (optional)
Filter `this.exempt` out of the `isDrained()` count, or rename/document it as the pre-fence variant. Add a test mirroring the exempt-control case at `ssh-connection-work-ledger.test.ts:216-233`.

@OrcaWin
OrcaWin force-pushed the OrcaWin/node-rt-p3-t1c branch from 5da66b8 to 4446ea6 Compare October 1, 2026 12:35
@OrcaWin
OrcaWin requested a review from brennanb2025 as a code owner October 1, 2026 12:35
@OrcaWin
OrcaWin force-pushed the OrcaWin/node-rt-p3-t2a branch from 54ce722 to 014daa4 Compare October 1, 2026 12:38
@OrcaWin
OrcaWin force-pushed the OrcaWin/node-rt-p3-t1c branch from 4446ea6 to 3977d5b Compare October 1, 2026 14:05
m4air added 2 commits October 1, 2026 07:55
…acking

Dormant foundation for the T2 SSH core port of #16741 (design D9.3). No
production module imports it yet; only tests do, so SSH behavior is
unchanged. The next T2 slice wires SshConnection.exec/sftp/channel opens and
forwarded sockets through it.

Adds:
- SshConnectionWorkLedger: tracks local operation and channel lifetimes per
  connection. fenceForReset closes admission (except work nested under an
  already-admitted operation and one exactly-identified control channel)
  and drain() waits for the rest, failing sticky on any failure or
  unverifiable opening observed after the fence. Channel closure is local
  lifetime evidence only, never proof that a remote process exited.
- trackSshConnectionChannelLifetime / openTrackedSshSocket: bind an opened
  channel or socket to its ledger entry and settle it only on 'close'
  ('end', 'error' and the destroyed flag are not closure).

Porting note (source: #16741 head a68b6f3, merge-base 277c289; T2 per
the #24137 track manifest):
- Taken verbatim: ssh-connection-work-ledger behavior and tests,
  ssh-forward-socket-admission.test.ts, openTrackedSshSocket.
- Adapted: the ledger no longer calls assertProfileLifetimeAdmission on
  every admit. That module is an opt-in native-addon profile lock (addon
  dropped in T0) that overlaps the SQLite authority from #22612; callers
  inject their own admission check through the existing constructor
  argument instead (SshConnection will pass its disposed check). The broad
  `object` resource type became SshConnectionWorkChannel (on/once/
  removeListener), and trackSshConnectionChannelLifetime uses a type guard
  instead of a cast, so a value without removeListener is now reported
  unverifiable rather than tracked. Added ssh-connection-channel-lifetime
  tests, since #16741 covered it only through SshConnection.
- Dropped: none in these files.
- Not in this slice: SshConnection wiring (ssh-connection.ts), forwarded
  channel lifetime (T4), upload session lifetime (T6), profile lifetime
  admission/lock/participation (needs a D9.4 decision against #22612).

No wire change: nothing is sent to relays or clients.
Dormant foundation for the T2 SSH core port of #16741. No production module
imports it yet, so SSH behavior is unchanged; the next T2 slice has
SshConnection track every ssh2 client it allocates and gate its
transport-closure subscribers on this ledger plus the work ledger.

Adds:
- SshTransportCloseLedger: remembers every allocated client (including
  ones whose authentication failed) until it emits 'close'. drain() waits
  for the snapshot and fails with ssh_client_close_allocations_changed if a
  client was allocated after the caller should have fenced allocation.
  Authentication settlement, 'end' and 'error' are not physical closure.
- observeSshTransportClose: registers 'close' listeners on a set of
  transport resources before close is initiated; wait() is cancelable
  without dropping the evidence, dispose() removes the listeners.

Porting note (source: #16741 head a68b6f3, merge-base 277c289; T2 per
the #24137 track manifest):
- Taken verbatim: both modules and ssh-transport-close-ledger.test.ts.
- Adapted: the ledger test no longer casts EventEmitter to ssh2 Client,
  since track() already accepts an EventEmitter. Added
  ssh-transport-close-observation tests, since #16741 covered it only
  through SshConnection.dispose.
- Dropped: none.

No wire change. Loss of transport is still reported as unverifiable, never
as remote process exit.
@OrcaWin
OrcaWin force-pushed the OrcaWin/node-rt-p3-t2a branch from 014daa4 to a5540c4 Compare October 1, 2026 14:55
@OrcaWin
OrcaWin changed the base branch from OrcaWin/node-rt-p3-t1c to main October 1, 2026 14:55
@OrcaWin OrcaWin closed this Oct 1, 2026
@OrcaWin OrcaWin reopened this Oct 1, 2026
@coderabbitai

coderabbitai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: aac39639-4b9d-4f26-820e-2d65971d8af7

📥 Commits

Reviewing files that changed from the base of the PR and between dc08ffe and a5540c4.

📒 Files selected for processing (9)
  • src/main/ssh/ssh-connection-channel-lifetime.test.ts
  • src/main/ssh/ssh-connection-channel-lifetime.ts
  • src/main/ssh/ssh-connection-work-ledger.test.ts
  • src/main/ssh/ssh-connection-work-ledger.ts
  • src/main/ssh/ssh-forward-socket-admission.test.ts
  • src/main/ssh/ssh-transport-close-ledger.test.ts
  • src/main/ssh/ssh-transport-close-ledger.ts
  • src/main/ssh/ssh-transport-close-observation.test.ts
  • src/main/ssh/ssh-transport-close-observation.ts

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


📝 Walkthrough

Walkthrough

The changes add a work ledger for SSH connection operations, sessions, and channel openings. Channel tracking links opened sockets to ledger entries and settles them on closure. The changes also add a ledger for tracking transport client closure and an abortable observer for transport resource close events. Tests cover admission, reset draining, channel errors, close events, aborts, and retries.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to a5540

This change adds tracking modules that nothing uses yet, so SSH behavior is unchanged. No concrete merge-blocking problem was found.

Security Architecture Review

Security architecture risk: 🔵 Low · up to a5540

Current exposure appears limited because the new lifecycle code is not connected to production SSH operations. No introduced attack path was established, but reset and recovery guarantees cannot yet be assessed end to end.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • observed — The examined accounting state is instance-local: each work ledger owns its pending entries and asynchronous admission scope, and each transport ledger owns its tracked client map. These primitives do not themselves establish tenant-wide or persistent reset authority.

Trust Boundaries and Controls

  • observed — Post-fence admission is restricted to an active pending, non-exempt parent. A control-channel exemption requires exactly one pending entry with the same resource identity; stale or ambiguous identities cannot establish that exemption. The injected admission assertion remains a caller-supplied control.

Resilience and Maintainability Implications

  • observed — Once fenced, failed or unverifiable non-exempt work latches a ledger failure that prevents successful drain. Cancelling a wait does not reopen admission or prove resource closure; ownership tracking remains separate from the waiting caller's cancellation.

Hardening Proposals

  • proposed — Future production integration should make allocation fencing and admission authority explicit, register closure tracking before resources can close, and preserve ownership tracking through cancellation and recovery. These are integration obligations, not observed vulnerabilities in this PR.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 9 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 identifies the main change: porting the SSH connection work ledger and transport close ledger.
Description check ✅ Passed The description explains the purpose, scope, implementation, testing, and lack of user-visible behavior changes. It includes the required core sections, but it omits the Review, Notes, and Checklist s…
  • 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

Autopilot is currently an internal CodeRabbit preview.


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.

@OrcaWin
OrcaWin merged commit c991893 into main Oct 1, 2026
53 of 95 checks passed
OrcaWin added a commit that referenced this pull request Oct 2, 2026
* Revert "feat(orcad): source-side dormant export of a relay-hosted SSH target (#16741 T6-8) (#24519)"

This reverts commit 783101b.

* Revert "feat(ssh): update, roll back, recover and stop a managed orcad server (#16741 T6-5 follow-up) (#24463)"

This reverts commit 38c2d1d.

* Revert "feat(ssh): deploy and pair an empty managed orcad server over SSH (#16741 T6-5) (#24453)"

This reverts commit 8b76683.

* Revert "fix(ssh): orcad GC honors the activation journal; readiness requires proven daemon coverage (#16741 T6 follow-up) (#24451)"

This reverts commit d3f8c50.

* Revert "feat(ssh): remote orcad stop by request file and journaled decommission (#16741 T6-4) (#24449)"

This reverts commit 43d9b43.

* Revert "feat(orcad): supervisable server: stop requests, managed stop receipts and a lifetime that keeps its lock on failed teardown (#16741 T6-3) (#24433)"

This reverts commit b093d3a.

* Revert "feat(ssh): crash-safe orcad activation, rollback and recovery (#16741 T6-2) (#24423)"

This reverts commit 1a9ac0e.

* Revert "feat(runtime): SSH access links for paired servers in a downgrade-safe sidecar (#16741 T5-1+T5-2) (#24420)"

This reverts commit 99db2bf.

* Revert "feat(relay): capability-gated owner reset with a durable preparation journal (#16741 T3 R1) (#24418)"

This reverts commit 34a582b.

* Revert "feat(ssh): track connection-manager drains, test probes and provider continuations (#16741 T2 P3+P8a) (#24407)"

This reverts commit d53063d.

* Revert "feat(daemon): idle retirement, session census and recovery-only provider (#16741 T2 P4b) (#24409)"

This reverts commit ff212db.

* Revert "feat(ssh): add pty.resumeClient and split SSH PTY process listing (#16741 T2 P5+P6) (#24414)"

This reverts commit 92cb717.

* Revert "feat(relay): await owned watcher and agent children on shutdown (#16741 T2 P1) (#24400)"

This reverts commit 6b36e4f.

* Revert "feat(session): retry failed renderer session writes and verify local folder PTYs (#16741 T2 P9) (#24406)"

This reverts commit d23ecef.

* Revert "feat(ssh): remote orcad primitives on the pinned Node runtime (#16741 T6-1) (#24419)"

This reverts commit dd87ae5.

* Revert "fix(runtime): fence runtime-environment subscriptions and status probes by identity (#16741 T5-3) (#24421)"

This reverts commit ece9e4d.

* Revert "feat(orcad): migration manifest and dormant-state contracts (#16741 T6-7) (#24422)"

This reverts commit 3fbdaba.

* Revert "feat(ssh): wire SshConnection through the work and transport close ledgers (#16741 T2 P2) (#24401)"

This reverts commit 4e8edc8.

* Revert "feat(profiles): carry markdown frontmatter visibility in project transfers (#16741 T2 P7) (#24405)"

This reverts commit 60c9326.

* Revert "fix(runtime): project the PTY incarnation onto mobile session tabs (#24413)"

This reverts commit 99e0303.

* Revert "feat(daemon): tag daemon stream data with the PTY incarnation id (#16741 T2 P4a) (#24402)"

This reverts commit 817af76.

* Revert "feat(ssh): port the SSH connection work ledger and transport close ledger (#16741 T2) (#24210)"

This reverts commit c991893.

* Revert "feat(relay): fence and drain file and git response streams on shutdown (#24185)"

This reverts commit dc08ffe.

* Revert "refactor(runtime-rpc): extract the Node WebSocket lifecycle; opt-in pinned port (#24186)"

This reverts commit a789233.

* Revert "feat(relay): route relay handlers through work admission; producer publication drain (#24181)"

This reverts commit 0b812bd.

* Revert "feat(relay): land the #16741 T1 seam (work drain, publication drain, release gate) (#24156)"

This reverts commit 3aa2d3a.

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
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