Repository navigation
refactor(runtime-rpc): extract the Node WebSocket lifecycle; opt-in pinned port - #24186
Conversation
|
| if (this.requirePinnedWsPort) { | ||
| await socketTransport.stop().catch(() => {}) | ||
| throw error |
There was a problem hiding this comment.
Failed start retains old identity
If a caller retries start() on the same server after a required-port bind failure, this branch has left mobileSocketWiring in place. The retry creates a fresh pairing identity but reuses wiring that holds the previous registry and keypair. If device or key state changed between attempts, the new listener can authenticate against stale identity state. Clear the wiring when this start fails.
Knowledge Base Used: Remote runtime transport
| resolve() | ||
| }) | ||
| // Why: idle keep-alive static-web connections would otherwise hold close() open. | ||
| httpServer.closeAllConnections() |
There was a problem hiding this comment.
Shutdown cuts off asset responses
closeAllConnections() closes active HTTP connections, not just idle keep-alive connections. This server also streams web-client assets, so stopping or rebinding it during an asset response now cuts off that download and forces the browser to retry. Consider letting active responses finish within a bounded drain while closing idle connections promptly.
Knowledge Base Used: Remote runtime transport
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
ℹ️ No critical issues — the extraction is faithful. One behavior note inline and a small coverage gap below.
Reviewed changes
- Extract
node-websocket-lifecycle.ts: per-connection lifecycle (attachNodeWebSocketLifecycle), shutdown (stopNodeWebSocketTransport), pre-auth timer clearing, and over-capacity rejection move here. Handlers are read through lazy getters, so a handler registered after start still reaches earlier sockets. The logic is equivalent to the removedhandleConnection/stopbodies. - Extract
websocket-transport-limits.ts: message/connection/TCP caps become named exports (1 MiB,128,256); values unchanged. - Opt-in
strictPortonWebSocketTransport: binds only the configured port and rethrows on failure instead of falling through to the persisted fallback or port 0. requirePinnedWsPortserver option: threadsstrictPort, skips the fallback port, and stops the already-started Unix socket transport before rethrowing so a failed start leaves no orphaned endpoint. Unused in production so far;orcad/serveare the intended consumers.- Tests: a failed required-port start releases its Unix socket;
stop()while an HTTP request is unanswered;strictPortfails closed.
ℹ️ Nitpicks
- The new
strictPort/requirePinnedWsPortsuccess path has no positive test — only the failure case and the non-required fallback case are covered. A test that starts a transport on a free configured port and assertsresolvedPort === portwould pin the main behavior of the new option.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
| resolve() | ||
| }) | ||
| // Why: idle keep-alive static-web connections would otherwise hold close() open. | ||
| httpServer.closeAllConnections() |
There was a problem hiding this comment.
stop() now hard-closes in-flight HTTP connections via closeAllConnections(); the implementation this was extracted from only called close() and waited. That is a real behavior change (a useful one — it removes a way for a keep-alive static-web request to wedge shutdown, or the widen rebind that calls current.stop()), but the PR description says there is no behavior change. Worth calling out in the description since it is bundled into the extraction.
04c9331 to
42e1b12
Compare
7b8fab6 to
9705c35
Compare
42e1b12 to
808078a
Compare
…-port bind mode Port the #16741 T1 transport pieces onto the current Node-only transport. The per-socket lifecycle (pre-auth timer, heartbeat enrolment, finalize on close/error), over-capacity rejection and shutdown move out of ws-transport.ts into node-websocket-lifecycle.ts, and the size/connection caps into websocket-transport-limits.ts. WebSocketTransport gains an opt-in strictPort that binds only the configured port and fails closed instead of walking the fallback ladder; OrcaRuntimeRpcServer exposes it as requirePinnedWsPort, which also skips the persisted fallback port and stops the Unix socket transport before rethrowing, so a caller whose tunnel forwards one fixed port never runs on a port nobody can reach. Porting note (#16741 a68b6f3, T1): - Taken: node-websocket-lifecycle.ts, websocket-transport-limits.ts, WebSocketTransport strictPort, the ws-transport strict-port test, runtime-rpc-state/-pairing-types/-lifecycle requirePinnedWsPort. - Adapted: the lifecycle reads the message/close handlers through getters (the PR snapshotted them per connection) so a handler registered after start still reaches earlier sockets; binary frames convert through a checked RawData branch instead of `as Buffer`; the original Why comments move with the code; stop() keeps a single Node path (no AggregateError) and keeps the PR's closeAllConnections(), now covered by a test that an unanswered HTTP request no longer holds stop() open; the over-capacity test calls the extracted function instead of casting to a private. - Dropped: every bun-websocket-* file and the Bun branches in ws-transport.ts (D9.4); WEBSOCKET_TRANSPORT_MAX_BACKPRESSURE_BYTES (only the Bun transport read it); the relaxed EACCES `port`-field check in isPortListenFallbackError (it covered Bun's listen errors, Node's carry the port). - Not here: the orcad-entry wiring that sets requirePinnedWsPort for `--port` (T6, managed SSH deploy); the transportGeneration context plumbing (its only readers are T3/T7); holdIdleRuntimeEnvironmentCalls (its only caller is the T5 reconciliation coordinator). Wire compatibility: none. The bind policy is server-local, the option defaults off, and no RPC field, method or frame changes.
…Unix socket The required-port startup test only checked the WebSocket side. Also assert no runtime socket file remains, which fails if the lifecycle stops rethrowing without first stopping the Unix socket transport. Porting note (#16741 a68b6f3, T1): review follow-up; taken: none; adapted: strengthens the ported required-port test; dropped: none.
9705c35 to
d18d20d
Compare
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. 🧰 Additional context used📚 Code guidelines (1)No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (8)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review. 📝 WalkthroughWalkthroughThe change extracts Node WebSocket lifecycle handling into shared helpers and defines shared message, WebSocket connection, and TCP connection limits. It adds strict WebSocket port binding and a runtime RPC option that requires the configured port. When required-port startup fails, the runtime stops the Unix socket transport and propagates the error. Tests cover transport shutdown, strict binding, and fallback behavior when a pinned port is optional. Priority: ⬇️ Low Merge Risk: ⚪ Minimal · up to The pinned-port option is opt-in, while existing fallback behavior remains available. Required-port failures clean up the Unix transport and preserve the bind error. The change is mergeable subject to normal checks. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to The opt-in setting prevents fallback to an unexpected port, but startup can still succeed without the required listener when identity setup fails. The inspected changes preserve authentication controls; deployment and recovery coverage remain incomplete. Retained concerns
Security review detailsSecurity Blast Radius
Security Findings and Attack Paths
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
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. Comment |
* 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>

ELI5
This splits the runtime's WebSocket server into small, testable pieces taken from #16741: the per-connection lifecycle, and the connection and message limits. It also adds an option to require an exact port, which the headless server needs for
--port. All Bun WebSocket code from #16741 is dropped.What Changed
node-websocket-lifecycle.ts: handles each connection, covering the pre-auth timer, heartbeat, finalize on close, over-capacity rejection (1013) and shutdown.websocket-transport-limits.ts: holds the message, connection and TCP caps.ws-transport.ts: now a thin class, down from 355 to 260 lines. It adds an opt-instrictPort.requirePinnedWsPort(runtime RPC state and lifecycle): binds only the configured port. On a bind failure it stops the Unix socket transport and rethrows.Why
Design D9, T1 and D9.4: keep the Node WebSocket path and drop Bun's. The headless server (T6) will set
requirePinnedWsPortfor--port.Linked Issue
Part of the Node runtime plan (Phase 3). Stacked on #24181.
Visual Proof
N/A. There's no behavior change; the new option is opt-in and unused so far.
Testing
Ported tests pass.
Added in review: a test that a failed required-port start releases the Unix socket.
Not yet ported:
transportGenerationplumbing (read only by T3 and T7) and the remaining T1 renderer and test-server pieces.I manually tested these changes locally
Automated tests added/updated, or explained why not below
Agent skill upstream boundary
docs/reference/agent-skill-sharing-upstream-boundary.mdand copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.