Skip to content

test: measure first-party egress paths and route Git over SSH through the turn proxy - #2644

Merged
schlessera merged 6 commits into
feat/1665-durable-egress-records-r2from
feat/1665-egress-measurement-044
Oct 22, 2026
Merged

schlessera merged 6 commits into
feat/1665-durable-egress-records-r2from
feat/1665-egress-measurement-044

Conversation

@schlessera

@schlessera schlessera commented Oct 22, 2026 •

Copy link
Copy Markdown
Owner

Refs #1665

Second layer of the #1665 stack. Parent: #2399 (feat/1665-durable-egress-records-r2). Child: #2645.

What changed

Git's SSH transport now works from an egress worker. The trusted worker bootstrap sets a first-party CONNECT helper (egress-connect.ts) as Git's ProxyCommand, unless the caller already chose GIT_SSH_COMMAND. The proxy sees only host, port and opaque bytes.

The new tests/egress-first-party-paths.test.ts is the gate's measurement. It runs Git over HTTPS and SSH, curl, the brain CLI's Gemini embedding provider and headless Chromium in real governed workers through the turn proxy. The fixture runs in its own network namespace with a fixture /etc/hosts and /run, so every upstream is a loopback fixture; a loopback sshd serves the SSH clone. The socket walk covers each mask root completely and the rest of the visible filesystem under a deadline. It fails if any socket outside the masks accepts a connection.

The measurement table is in docs/hosting/agent-workers.md, and the decision record notes the result.

Why this shape

#1665 makes the measurement the gate, and the decision record calls for a ProxyCommand CONNECT helper for SSH. A helper that dials the bind-mounted proxy socket directly needs no extra tool in the worker. The whole fixture runs in a private namespace, so the proxy's real DNS resolution can reach a named fixture host without touching a public name.

Proof

Head 547795928, parent 8406e0062 (#2399 refreshed onto origin/main 4ba50d824). Round 3 merged the refreshed parent in cleanly (4958d6aa3), reran the socket walk with #2657's all-/var mask (66e3072be), and merged the parent again after #2671 landed (547795928, clean).

Socket walk, round 3. With all of /var masked, the walk passes in both profiles. It covers the visible filesystem completely (complete: true) and finds no socket outside the masks (reachable: {}). The test now asserts EGRESS_SOCKET_WALK_NO_REACHABLE_HOST_SOCKET, and the measurement table and decision record say the walk passes.

  • Mutation: HOST_MASKS reverted to the pre-fix(ui-sdk): mask all host /var in worker profiles #2657 /var/run + /var/lib. Both profiles fail EGRESS_SOCKET_WALK_NO_REACHABLE_HOST_SOCKET with /var/snap/cups/common/run/cups.sock reachable (5 pass / 2 fail). Restored byte-for-byte; 7/7 green.
bun run check:pr --base feat/1665-durable-egress-records-r2

Result on 547795928: passed (exit 0). Lint, metadata and the fast phase pass (770 tests), and import-graph feedback passes 7/7 (tests/egress-first-party-paths.test.ts).

The receipts below were taken on round 1's head 290f8fe3c. The later merges change none of the files they guard.

  • All five paths pass, each with a completed opaque CONNECT recorded to the fixture origin. The socket walk passes in both profiles: no socket below a mask, and the fixture /run and home sockets are unreachable. Including the existing egress runtime, proxy, relay and citation suites, the focused set passes 73 tests.
  • Mutations (restored, then re-run green 7/7):
    • Bootstrap GIT_SSH_COMMAND set to plain ssh: the git over SSH through the CONNECT helper row fails with ssh: connect to host ithaca.odysseus.test port …: Connection refused (exit 128 ≠ 0).
    • /home removed from HOST_MASKS: EGRESS_HOST_HOME_SOCKET_UNREACHABLE fails in both profiles.
    • Removing /run breaks the egress bind at launch setup, so it is not used as a receipt.

Checklist

  • Focused local preflight/behavioral receipts and complete selected hosted proof passed; actual head/base/job checkout evidence is in Proof. (Local preflight above; hosted proof is the coordinator's.)
  • Acceptance criteria from the issue are all met, or the gap is named below.
  • The PR and completed/advanced issues have verified release milestones under docs/process/github.md.
  • A changeset is included, or this changes nothing a consumer can see.
  • No personal data anywhere in the diff — the leakage gate covers the whole tree.
  • The integration contract index or relevant component is updated in this same commit, or nothing in the machine surface moved.
  • Docs under docs/ reflect the change, or nothing documented moved.
  • Provider history stays append-only (docs/decisions/provider-history.md): the provider-history guard passes, or nothing on a turn's path changed.

Anything left open

🤖 Generated with Claude Code

schlessera and others added 2 commits October 22, 2026 13:27
SSH has no proxy variable, so an egress worker's Git SSH transport had no
way out of its private network namespace. The trusted worker bootstrap now
sets a first-party CONNECT helper as Git's ProxyCommand, unless the caller
already chose GIT_SSH_COMMAND. The proxy sees only host, port and opaque
bytes, as for any other CONNECT.

Refs #1665

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Run Git over HTTPS and SSH, curl, the brain CLI's embedding provider and
headless Chromium in real governed workers through the turn proxy, inside
a private network namespace whose fixture /etc/hosts and /run hold the only
reachable origin and host sockets. Walk every mask root completely and the
rest of the visible filesystem under a deadline.

All five paths pass. The walk finds no socket below a mask and cannot reach
the fixture /run and home sockets, but host sockets outside today's masks
stay visible (a CUPS socket under /var/snap accepted a connection), so the
gate does not pass and ordinary turns keep their current network. The
measurement table and the gap are recorded in agent-workers.md and the
decision record.

Refs #1665

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@schlessera
schlessera added this pull request to stack #2646 October 22, 2026 12:19
@schlessera schlessera added this to the 0.44.0 milestone Oct 22, 2026
@schlessera schlessera changed the title feat/1665 egress measurement 044 test: measure first-party egress paths and route Git over SSH through the turn proxy Oct 22, 2026
@schlessera schlessera added type: test Coverage, harness or proof work with no behaviour change. area: ui-sdk Wire protocol, runtime schemas, the server and client SDK surfaces. security Auth, isolation, egress, secrets, or anything in the threat model. labels Oct 22, 2026
@schlessera
schlessera marked this pull request as ready for review October 22, 2026 13:12
@schlessera
schlessera marked this pull request as draft October 22, 2026 13:12
…ess-measurement-044

# Conflicts:
#	docs/hosting/agent-workers.md
schlessera added a commit that referenced this pull request Oct 22, 2026
)

For an upper layer of a native stack, `edited` events report the stack's
base (`main`) as `github.base_ref`, so the contract gate diffed the layer
against `main` and blamed it for its parent's contract-doc edit (#2644).

The gate now reads the PR's declared base from `pulls/N` with the
read-only token on every trigger and diffs against that remote-tracking
ref. A missing PR number, a refused or failed lookup, a foreign or invalid
base, or an unfetched base fails the gate (exit 2) instead of falling back
to `main`. The event's value is logged only to show a disagreement.

The workflow lint refuses a contract step that takes its base from event
context, and a workflow-level harness executes the installed step against a
loopback PR lookup for every trigger, stacked, ordinary and failure cases.

Closes #2650
Refs #2141

Co-authored-by: Claude Opus 5.5 <[email protected]>
@schlessera
schlessera marked this pull request as ready for review October 22, 2026 17:21
@schlessera
schlessera marked this pull request as draft October 22, 2026 17:22
schlessera and others added 3 commits October 22, 2026 19:22
With all of /var masked (#2657), the walk of the visible filesystem finds no
host socket outside the masks in either profile. Assert that no socket there
accepts a connection, and record the passing walk in the measurement table
and decision record.

Refs #1665

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ui-sdk Wire protocol, runtime schemas, the server and client SDK surfaces. security Auth, isolation, egress, secrets, or anything in the threat model. type: test Coverage, harness or proof work with no behaviour change.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ui-sdk: governed and strict workers can still reach host sockets under /var outside today's masks

1 participant