Skip to content

feat(acp): serve owner-approved sandbox terminals over the relay - #170

Draft
tee8z wants to merge 3 commits into
tee8z/sandbox-attach-claimsfrom
tee8z/sandbox-terminal-relay
Draft

tee8z wants to merge 3 commits into
tee8z/sandbox-attach-claimsfrom
tee8z/sandbox-terminal-relay

Conversation

@tee8z

@tee8z tee8z commented Nov 10, 2026 •

Copy link
Copy Markdown
Collaborator

An owner can approve one interactive terminal in a bound remote-agent workspace. The ACP server carries encrypted PTY traffic through the existing relay and starts a worker only after current authority, atomic acceptance, and bounded readiness are confirmed. A global gateway delegation permits requesting approval; it never authorizes the shell itself.

Production activation requires Linux, strict owner mode, an immutable channel-thread binding, a known owner, and WSS. The private local-test constructor reaches the same engine over loopback WS and can select the actual worker executable. No public trust bypass is added.

Stage Required boundary
Admission Strong current pending/approval heads, verified owner signature, immutable scope, posting roster, and live gateway delegation
Single use Private fsynced journal reservation and exact first-insert relay receipt; generic/duplicate/ambiguous success cannot start a worker
Start Enough remaining authority for the full five-second Ready budget; Open ACK follows actual worker readiness
Active One PTY, bounded frames/rates, asynchronous generation-fenced authority refresh, absolute authority/expiry deadlines on blocked I/O
End Confirmed contained cleanup, reliable final-output drain, metadata-only durable audit retry; fatal containment stops the harness before checkpoint

A refresh begins every five seconds and has a five-second deadline. Its lease begins before the lookup and expires within ten seconds, capped by approval expiry. Slow HTTP does not occupy the relay/PTY loop. Reliable five-second heartbeats preserve liveness without extending five-minute idle expiry. The journal caps records at 256 and each record at 16 KiB; output/data remain in encrypted ephemeral events and bounded local pipes.

Startup reserves and stores the exact unique claim before external publication. A losing or unconfirmed claim cannot publish an end record for a different replica. Restart cannot reopen an approval. End retries retain their exact signed event. The native IPC adapter confirms worker receipt plus exit status, preserves deadlines across select cancellation, and never uses SIGKILL to interrupt descendant cleanup. An audit write failure cannot downgrade an existing fatal containment error.

Validation:

  • Restored full ACP suite: 1,148 passed, 3 infrastructure cases ignored.
  • Five production-binary PTY tests pass: real terminal/resize/environment, bounded input, setsid+double-fork cleanup and sibling preservation, final-output drain, and lease expiry without parent EOF.
  • Sixteen focused server/IPC tests pass through actual HTTP/WS and spawned IPC, including old-relay/duplicate receipt refusal, delayed claim beyond admission expiry, membership/revocation/malformed-head denial, durable restart and fatal containment priority.
  • Eight production mutations fail their intended runtime assertions: first-claim marker, admission readiness lease, strong consistency, current approval signature, local consumed grant, fatal containment priority, full SDK packet admission, and pre-crypto envelope limits. Restored full/native suites and all-target Clippy pass again.
  • Formatting, all-target Clippy with warnings denied, differential file-size checks, diff checks, and locked root/Tauri/GPUI metadata pass.

Independent frozen-source review identified the admission/readiness gap; it is fixed and covered by the delayed receipt regression. The final source matches the second frozen review snapshot. Independent first review verified all nine published source files against the frozen final snapshot and independently reran all fourteen focused tests (14 passed). The admission finding is resolved, with no remaining concrete blocker; minimalism, elegance and correctness each scored 9/10. Actual relay/CLI/worker controlling-PTY journeys passed on the first published server: normal terminal (11.4s), a three-second authority delay with output/Ctrl-C/input continuing (15.63s), replay refusal (12s without another Open ACK or acceptance), and per-approval revocation with process cleanup and exact termios restoration (10.39s). That runtime work found a real frame-size defect: a full 16 KiB SDK packet encrypts to 32,860 bytes, exceeding the old 32 KiB guard. Signed 119b065cc fixes both pre-crypto gates using the existing shared NIP44 envelope (132..=87,472), while decoded data remains 16 KiB. A full authenticated production engine regression now delivers and echoes MAX_DATA_BYTES through spawned worker IPC. Reinstating the old cap fails that regression; removing the envelope check fails the oversize/rate regression. Independent delta review reran the three production-path checks successfully. The native 16 KiB round trip and replay process sampling are running against the follow-up head; human confirmation remains pending. Full repository local CI remains limited by the parent task's missing native Tauri GLib libraries; this focused result does not claim a full repository gate or production TLS journey.

Stack: gateway #154 → terminal SDK #159 → CLI #163 → worker #166 → snapshot wire #167 → producer #168 → atomic claims #169 → this server. Base is #169. The separately reviewed producer #168 fix 6e7ceba13 is carried as signed 0ab2047ee because published stack history is preserved. No history rewrite, merge, or deployment is included.

This consumer adds 2,116 changed lines across 9 files, plus the carried producer fix. SDK, isolated native worker, and relay transaction primitives already have separate foundation PRs. The private IPC adapter, authority, durable journal, engine, and harness teardown must be reviewed together to prove that no admitted shell escapes their lifecycle; splitting unused private helpers would weaken that review boundary. The diff includes a 543-line HTTP/WS/journal fixture and the 472-line IPC adapter with five focused tests.

See the server contract, CLI runbook, and contained worker. Keep this PR in draft until independent review, actual combined runtime, and explicit human testing are complete.

Signed-off-by: Tee8z <tee8z@protonmail.com>
(cherry picked from commit 6e7ceba)
Signed-off-by: Tee8z <tee8z@protonmail.com>
Signed-off-by: Tee8z <tee8z@protonmail.com>
@tee8z tee8z self-assigned this Nov 10, 2026
@coderabbitai

coderabbitai Bot commented Nov 10, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@tee8z
tee8z added this pull request to stack #160 November 10, 2026 22:16
@tee8z

tee8z commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator Author

Reviewed 2dc345413 against the owner-approved relay-only terminal contract. All nine task files match the frozen source I reviewed.

The one concrete blocker found during review is fixed: admission originally checked its authority lease only after PTY startup. Slow authority/claim responses could therefore start a shell after that lease ended. Admission now requires the full bounded five-second Ready window before spawning, and the delayed-claim regression proves expired admission starts no worker and durably ends its owned claim. Its guard-removal mutation fails.

I also checked the unique first-claim receipt, durable consumed-grant journal, current signed request/approval heads, posting membership and delegation checks, generation-fenced background refresh, absolute I/O lease, final-output drain, metadata retry retention, and harness shutdown. Fatal containment errors retain priority even if audit persistence also fails. There are no plaintext terminal bytes in stored audit records.

Independent validation: all 14 focused terminal tests pass against the final test artifact. Author evidence additionally reports 1,146 ACP tests passing with three ignored, five actual native-worker tests, six guard mutations, Clippy, formatting, and metadata checks. The combined actual-relay/worker/controlling-PTY journey is being exercised separately; this comment does not claim it already passed.

No remaining concrete blocker in this layer. Scores: minimalism 9/10, elegance 9/10, correctness 9/10. Human testing is pending; keep the PR in draft.

@tee8z

tee8z commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator Author

New material evidence from the combined runtime check reopens one blocker after the source review: the active server path drops encrypted events above 32,768 bytes, but a valid SDK 16 KiB data packet encrypts to 32,860 bytes. Full-size terminal input is therefore dropped on every retry.

The exact measured boundary was 16,384 decoded bytes → 32,860 encrypted content bytes. Raise the bounded envelope allowance to the protocol's valid ciphertext budget and add a production-engine regression using an actual maximum-size SDK-encrypted packet. Keep an explicit oversized-envelope refusal before decryption. The integration check should exercise maximum-size input and output as well as the already-passing ordinary controlling-PTY flow.

This finding comes from new runtime evidence. The PR remains draft while the additive fix and workflow check run.

Signed-off-by: Tee8z <tee8z@protonmail.com>
@tee8z

tee8z commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator Author

The runtime envelope blocker is resolved at 119b065cc.

I inspected the additive fix and independently ran the three affected production-path tests. A real SDK 16 KiB encrypted packet now crosses the authenticated serve engine, reaches the spawned worker protocol peer, and returns as encrypted output. Oversized envelopes are still refused before cryptographic work. The server uses the existing shared NIP-44 envelope bound; decoded packets retain the 16 KiB limit.

The published source matches the final frozen review. The restored author suite passes 1,148 ACP tests with three ignored, and both new guard mutations fail. No remaining source-review blocker. The real native-worker 16 KiB round trip and affected combined cases are being rerun separately before final handoff. Draft state and pending human confirmation are preserved.

@tee8z

tee8z commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator Author

Runtime validation of 119b065cc9a7dfce2505034e33d1c7f8fec86948 passes in the unpublished combined integration tree at 91342b222a7ecf073c06ba15256f903deb96ab95.

The fixture uses an actual local relay, the production private ACP engine, the actual contained worker binary, and the CLI's production private attach function under a controlling PTY. Production transport factories remain unchanged.

  • Normal attach: 37×91 terminal, clean worker environment, raw Ctrl-C removes the foreground command, final output arrives, full local termios restores, and the end audit is durable.
  • Bulk transfer: a 16 KiB payload reaches the native worker and returns intact; the remote SHA-256 matches. End counters are 16,921 input bytes and 17,150 output bytes. The following Ctrl-C/exit and termios checks also pass.
  • Slow authority read: the fixture delays one real signed /query by three seconds. Three further output ticks, foreground cancellation, and new terminal input/output occur before that response completes. The terminal closes normally with a durable end audit.
  • Single use: while a completed approval still has 54 seconds of validity, the relay accepts another encrypted Open. Over 12 seconds the agent emits no readiness acknowledgement, 50-ms process samples observe no worker, and the accepted audit ID stays unchanged.
  • Revocation: deleting the live owner approval while a foreground command runs closes access, removes that process, restores full termios, and produces a durable end audit. The isolated case passes in 10.53 seconds.

The first dense matrix run hit a relay quota in the fixture's 100-ms post-close audit polling. I preserved that failure and reran revocation with a fresh, quiet fixture; the same product revision passes. No production quota was disabled.

Executables and test glue are pinned with hashes under /tmp/buzz-local-integration-runtime; results are in terminal-results-91342b222. No model calls, deployment, or staging/production mutations occurred. The outward WSS connection and explicit human testing remain outstanding; this PR stays draft. Final combined repository gates are tracked separately.

This branch has not been deployed

No deployments
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