Repository navigation
Conversation
… through a gateway (#1017)
…its device takes no input (#1017)
…ugh a gateway, or is refused (#1017)
…y refuses a worker that takes no input with 503 INPUT_UNAVAILABLE (#1017)
…sages and the screen config cross the gateway (#1017)
…ches the device (#1017)
…est answered {ok:false}, and the socket stays open (#1017)
… socket 503 WORKER_UNREACHABLE (#1017)
…ect within 10 s of a failed open is refused without a new open (#1017)
… device input closes them 1013, and a failed open is remembered for 10 s (#1017)
…son, and a socket that opens after it is closed too (#1017)
…d a reconnect gets 404 (#1017)
…lease goes, or the daemon stops (#1017)
…001 when it sees the lease go, and 1001 when the daemon stops (#1017)
…way reports a worker that stops as 1011 (#1017)
…and boundary rules (#1017)
…est the catalog's openInput (#1017)
Decision takenQuestion: Options:
Why 1: this is the attack §5 exists to stop, it changes nothing for token users, and it is easy to reverse. Reverting: drop the check from the input route and its Tests row. Folded into #1017's Tests, marked pending the maintainer. Written by an agent. |
…s the daemon, and the abandon paths are proven (#1017)
Review notesNot blocking, not verified. Each is one reviewer's claim.
Written by an agent. |
Review ledgerRound 1: 7a0f715 {"findings":[{"id":"R1","role":"code","class":"last-socket close races a joining socket","outcome":"fixed","path":"src/input/sessions.ts","round":"1","fix":"6afe7802a9d634fd0dd9a72bd5ed4870cae0e959"},{"id":"R2","role":"code","class":"opened resource not released on failed upgrade","outcome":"fixed","path":"src/input/gateway-link.ts","round":"1","fix":"6afe7802a9d634fd0dd9a72bd5ed4870cae0e959"},{"id":"R3","role":"spec","class":"testing 7","outcome":"fixed","path":"src/input/gateway.test.ts","round":"1","fix":"6afe7802a9d634fd0dd9a72bd5ed4870cae0e959"},{"id":"R4","role":"code","class":"spec vs rule","outcome":"intentional","path":"docs/internal/adr/0033-a-sign-in-proxy-is-a-second-way-to-sign-in-and-auth-is-one-module.md","round":"1"},{"id":"R5","role":"code","class":"unhandled stream error crashes the process","outcome":"fixed","path":"src/ports/upgrade-router.ts","round":"2","fix":"635b72184986ef77ec04207e4d41a1b71e17dc1b"},{"id":"R6","role":"code","class":"testing 2","outcome":"fixed","path":"src/ports/upgrade-router.test.ts","round":"2","fix":"635b72184986ef77ec04207e4d41a1b71e17dc1b"},{"id":"R7","role":"code","class":"testing 9","outcome":"fixed","path":"src/ports/upgrade-router.ts","round":"2","fix":"635b72184986ef77ec04207e4d41a1b71e17dc1b"}]}Written by an agent. |
Closes #1019 ### Status Implement: done Review: passed (round 2) Hardware: unavailable (disk 14.8 GiB free, the lane needs 15) Gate: waiting for the stack Next: needs-hardware. Run Done when line 3 on a machine with disk space and an iOS simulator ## Assumptions - Assumption: where the iOS device input lives — `src/drivers/ios/input/` (an `index.ts` and `device-input.ts`, as Android's `input/`) instead of the spec's single `input.ts`, so its test goes through an `index.ts` (testing rule 6). ## Done when - [x] The two Tests lines and the `byte-pipe` test pass in `pnpm test`, and `src/source-hygiene.test.ts` passes. - [x] `pnpm build:capture` builds `simlock-screen-capture` with the input mode where Xcode is selected. - [x] On a simulator, `e2e/slow-agent-device.test.ts` opens a lease and the Appduct fixture through agent-device, opens `WS /v1/leases/{id}/input`, gets 0x83 and 0x82, taps the centre of `tab-status` as agent-device's snapshot places it, and the next snapshot shows the Status tab's screen (slow lane, iOS simulator). — slow lane on 2ffb9ae, 2026-10-27: passed (18 passed, 17 Android cases skipped) - [x] `watching-the-screen.mdx` lists what input does on iOS: touch, scroll, Home, keys on iOS 26 runtimes; not the app switcher, Lock, rotation or keys on iOS 27 (#1024). - [x] An agent token streams its own lease through a gateway and through a standalone worker, and gets 404 for anyone else's. — #1015 (PR #1025), `src/daemon/stream-gateway.e2e.test.ts` - [x] A test client that follows T3 Code's message order (waits for 0x83, reads 0x82, sends touches and keys) drives a faked device through a gateway, in the fast lane. — #1017 (PR #1034), `src/daemon/input-lease.e2e.test.ts` - [x] A real iOS simulator and an Android emulator take a tap through the input socket: a tap on a known control opens the next screen, as agent-device's snapshot shows (slow lane). A person confirms a tap on an Android phone (slow lane, person at the phone). — simulator and emulator taps passed on the slow lane 2026-10-27; the phone tap (`e2e/slow-android-physical-manual.test.ts`) was confirmed by the maintainer at the phone - [x] Ending the lease ends both the stream (with a 0x07 frame) and the input socket (close 4001). — #1015 (`src/stream/create.test.ts`), #1017 (`src/daemon/input-lease.e2e.test.ts`) ## Review Spec review: 0 blocking, 0 fixed, 0 notes. Code review: 1 blocking, 1 fixed, 0 notes. Claims review: 0 blocking, 0 fixed, 0 notes. Rounds: 2. Tokens: 28.5M. Runs: 11. Cost USD: 6.0555. Agent seconds: 2652. Assessment: complete _Written by an agent._
Closes #1017
Status
Implement: done Review: passed (round 2 and a fix-check) Hardware: n/a Gate: waiting for the stack
Done when
pnpm testpasses, includingsrc/daemon/input-lease.e2e.test.tsandsrc/ports/uplink-websocket.test.tsunchanged —input-lease.e2e.test.ts(wiring through a gateway and on a standalone worker),src/input/worker.test.ts,src/input/gateway.test.ts; the uplink test file is not touched.capabilities.input.enabledtrue on a standalone worker, an agent token's upgrade to its own lease's/v1/leases/{id}/inputgets 0x83 then 0x82{"width":1,"height":1,"orientation":"portrait","inputUnavailable":true}; another token gets 404 —input-lease.e2e.test.ts"opens WS /v1/leases/{id}/input…" (standalone()cases).pnpm openapi /tmp/openapi.jsonwrites a document listingGET /v1/leases/{id}/inputwith 101, 401, 404, 426 and 503 (INPUT_UNAVAILABLE,WORKER_UNREACHABLE) —src/input/definition.tshttp, pinned bysrc/http/openapi.test.ts.capabilities.input.enabledandINPUT_UNAVAILABLE—watching-the-screen.mdx(new "Send input to your own lease"),configuration.mdx(row),access-control.mdx(agent row).Assumptions
Sec-Fetch-Site: same-originon a WebSocket upgrade as on a change, 403FORBIDDEN;src/http/auth.ts, proved ininput-lease.e2e.test.tsagainst a daemon withhttp.proxyAuthand a real JWT; ADR 0033 section 5 andsrc/http/AGENTS.mdsay so. The OpenAPI document also lists the 403 the route can answer.src/daemon/main.tstakescreateUpgradeRouterfromports/uplink-websocket.ts(a re-export), because the past-index baseline only shrinks and the ports barrel must not loadws.BAD_REQUESTwithUpgrade: websocket— the existing code closest to "wrong kind of request".onConfigat subscribe time, then on each change — the port lists four members and noconfiggetter.ws's own limit would close it).0xF1 {1001}reach the client? — as 1011Worker <id> stopped answering, since the table lists a worker that stops (uplink lost) as 1011 and 1001 as the answering daemon stopping.typeandusage(serve-sim'skeyandshiftedare not read); the Android and iOS tasks can widen the message type.0x10get back? —0x90{requestId?, ok:false, error:"This device cannot change its pose"}.0xF1wait, 10 s failed-open memory, 5 s heartbeat) insrc/input/*.test.tswith a fake clock, and the real-socket wiring (pong, daemon stop, uplink drop, lease end through a gateway) in the e2e file.Review
Spec review: 1 blocking, 1 fixed, 1 notes. Code review: 6 blocking, 5 fixed, 0 notes. Claims review: 0 blocking, 0 fixed, 0 notes.
Rounds: 2. Tokens: 19.5M.
Runs: 16. Cost USD: 15.3251. Agent seconds: 6204.
Assessment: complete
Rejected:
Written by an agent.