Repository navigation
feat(tunnel): reverse a leased Android device's port over a lease WebSocket on a worker - #1121
Conversation
…els and gets READY, and a device connection arrives as OPEN with its bytes as DATA (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ctions as OPEN and DATA (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ED and close 4003 (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…de and close 4003 (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…credit pausing only its connection (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…credit (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… a closed connection is ignored (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…lstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…when the socket closes, the lease ends or the daemon stops (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…a tunnel's rules and close its connections (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… may (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… worker (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… loopback listener and removes it on close (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…'s refusal reaches the holder with its code (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ction past 256 is closed (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…e connection past 256 is closed (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ckincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ts and manuals (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…allstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…allstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ly on a device proved its own (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…or#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… manual budgets (callstackincubator#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
@coderabbitai review Written by an agent. |
Review ledgerRound 1: ef0194e {"findings":[{"id":"R1","role":"code","class":"hook returns before in-flight rule removal","outcome":"fixed","path":"src/tunnel/sessions.ts","round":"1","fix":"22f1d60d0"},{"id":"R2","role":"code","class":"testing 10","outcome":"fixed","path":"src/daemon/tunnel-lease.e2e.test.ts","round":"1","fix":"5ee15c2a6"},{"id":"R3","role":"claims","class":"doc says refused with codes never sent","outcome":"fixed","path":"website/src/content/docs/docs/reference/errors.mdx","round":"1","fix":"181af2d5c"},{"id":"R4","role":"spec","class":"documentation 7","outcome":"nonblocking","path":"src/core/AGENTS.md","round":"1"},{"id":"R5","role":"code","class":"spec vs rule","outcome":"intentional","path":"src/drivers/android/device-tcp.ts","round":"1"},{"id":"R6","role":"code","class":"cleanup deferred to a reclaim that skips phones","outcome":"fixed","path":"src/tunnel/sessions.ts","round":"2","fix":"42f31b54b"},{"id":"R6c","role":"claims","class":"doc says reclaim removes rules; phones excluded","outcome":"duplicate","canonicalId":"R6","path":"src/tunnel/AGENTS.md","round":"2"},{"id":"R7","role":"claims","class":"comment says reclaim removed rules; phone reclaim removes none","outcome":"fixed","path":"src/drivers/android/index.ts","round":"2","fix":"42f31b54b"}]}Written by an agent. |
… rules at start, name the call in refusals (callstackincubator#1112) A removal that fails keeps the loopback listener reserved and the device's reclaim frees it; the start sweep only reads a leased device's rules and reserves their ports; refusal texts follow the spec's shared values; a cancelled TcpStream no longer closes its readable twice. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…r#1112) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
# Conflicts: # src/contract/AGENTS.md # src/contract/protocol.ts # src/daemon-protocol/index.test.ts # src/daemon/AGENTS.md # src/daemon/main.ts # src/drivers/android/index.test.ts # src/drivers/android/index.ts # src/modules/AGENTS.md # src/modules/testing.ts # website/src/content/docs/docs/reference/errors.mdx
Decision takenThe ADR review (round 1, R1 and R2) found two questions that the spec left open. Both are decided here, pending the maintainer. #1112's body now says the same, with Tests lines that pin each one. R2: tunnel rules on enrolled phones. Reclaim and the start sweep ran
Why (a): it keeps the safety rule as it is, it is the smaller change, and it is easy to widen later. Reverting means option (b): a rule amendment, plus putting the phone branch back in R1: the loopback listener accepts any local connection. While a tunnel is open, another lease's device on the same worker can reach the holder's tunnelled port: an emulator through 10.0.2.2, or any device through an
Why (a): it is what the code does today, and the exposure is opt-in. Reverting means option (b), which would be a follow-up task under #1110. Written by an agent. |
Decision takenThe ADR review (round 2, R5): a tunnel rule left on a phone (after a daemon crash or a failed removal) keeps pointing at a port in 47000-47999. If nothing reserves that port, a later tunnel on another lease could get it, and would then receive that phone's connections for a different holder.
Why (a): it closes a path from one lease into another, and it only reads phone state, so safety rule 1 holds. Reverting means dropping the read of phone rules at start and at reclaim. Written by an agent. |
…one, and a port a phone's rule points to stays held (callstackincubator#1112)
… worker's other devices, and which codes a worker sends (callstackincubator#1112)
Decision takenReview round 2 (R6): a lease end whose signal is already aborted (
Why (a): it keeps ADR 0054 as reviewed and removes only what Simlock set. Reverting means putting the abort skip back on phones. Written by an agent. |
Decisions confirmedThe maintainer confirmed the delivery decisions on 2026-11-01:
Written by an agent. |
Closes #1112
Status
Implement: done Review: fix-check passed (round 1, round 2, fix-check), 5 fixed, 3 decisions taken Hardware: n/a Gate: running
src/tunnel/worker.test.ts,src/daemon/tunnel-lease.e2e.test.tsandsrc/drivers/android/index.test.tsrun locally in the fix runstunnelModuleis in the registry, off by default;simlock statusshows thetunnelcapabilityoffuntil enabled. — module registry test and the status capability test, checked by the spec reviewcapabilities.tunnel.enabled; the errors reference lists the nine codes; the configuration reference says the worker reserves loopback ports 47000-47999 for tunnels; the remote-agents page describes the tunnel socket on a lone worker, says other leases' devices on the same worker can reach a tunnelled port while it is open, and says a tunnel rule a crash leaves on a phone stays until the phone reboots; ARCHITECTURE has the module's row. —configuration.mdx,errors.mdx,remote-agents.mdxandARCHITECTURE.md, checked by the claims reviewAssumptions
RESETwould name an id the caller never saw.a frame came before HELLO,HELLO came twice,unknown frame tag <n>,DATA is past the granted window,connection <n> was never opened,the window is above 2147483648).Review
Spec review: 0 blocking, 0 fixed, 1 notes. Code review: 3 blocking, 3 fixed, 0 notes. Claims review: 2 blocking, 2 fixed, 0 notes.
Rounds: 2. Tokens: 31.5M.
Runs: 14. Cost USD: 9.2006. Agent seconds: 3630.
Rejected:
src/core/AGENTS.md:35omits the new core files andDriverCatalogmethods — incomplete, not false [nonblocking]src/drivers/android/device-tcp.ts:148-149the start sweep only reserves ports on a leased device — follows the Tests line and safety rule 2 [intentional]Assessment: complete
Written by an agent.