Skip to content

ST4: worker — Go reference worker (dial Attach, run/stream/abort, dedup, dual timeout) #87

Description

@pdettori

ST4 — Worker: Go reference worker

Part of the SandboxTransport epic (see epic #89). Worker track (Go / sandbox side) — a separate contributor from the backend. Depends only on ST1 (the published sandbox/v1 proto); builds in parallel with ST2/ST3.

Spec: docs/specs/2026-07-08-sandbox-transport-grpc-design.md §7, §8.

Problem

The contract is language-neutral (ST1), but nothing yet proves it: we need one worker that a) implements the SandboxWorker.Attach client, and b) is deliberately not TypeScript — the honest proof the seam isn't secretly TS-shaped (driver #2, §2). A Go static binary drops into any sandbox image with no runtime dependency.

Goal

Ship a thin, single-purpose Go static binary that holds no LLM key and no orchestration — it only executes commands and returns bytes (what makes "central brain" trust-correct, §7). Behavior per §7:

  1. On start: read SANDBOX_ID, RELAY_ADDR, SANDBOX_TOKEN from env; dial SandboxWorker.Attach over TLS :443 (HTTP/2) with Authorization: Bearer <token>.
  2. Send Hello (id, labels, capabilities, capacity_max, trust).
  3. Loop on ServerFrame:
    • Exec → run bash -c <command> locally, feeding stdin. If streaming: emit Chunk* then End{exit_code}. Else: a single End carrying full stdout. Enforce timeout_s locally (SIGKILL on expiry).
    • Abort → SIGKILL the in-flight child for that req_id.
  4. Send Heartbeat periodically (liveness + NAT/proxy keepalive).
  5. Maintain a bounded req_id → End dedup cache; on a redelivered req_id, re-emit the cached result instead of re-running (at-least-once + dedup, §8).

Persistent-shell semantics (one long-lived bash preserving cwd/env across execs) are an internal choice; the wire only requires ordered, one-in-flight execs (§7).

Non-goals (this task)

  • The relay and GrpcRelayTransport (ST3 — backend).
  • mTLS / SPIFFE (bearer token only day-one, §9); additional-language workers (§13.4).
  • Any orchestration or credential handling in the worker.

Acceptance

  • Go contract test (Go test, real Attach against a relay, worker pointed at local bash) round-trips read/write/bash/grep, plus abort mid-stream, timeout (worker SIGKILLs child), and reconnect → dedup (redelivered req_id re-emits cached End, no re-run).
  • Static binary, no runtime deps; drops into a sandbox image.
  • Chunk size capped so a single frame stays small (backpressure, §8).

Touches

New Go module for the worker (e.g. worker/ or a dedicated repo dir), consuming ST1's generated Go stubs; a minimal container build for the static binary; Go unit + contract tests.

Next step

Join ST3 for the ST5 live gate (real worker pod → in-cluster relay on :443). Worker plan lives locally in docs/plans/, authored by the worker contributor.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions