Skip to content

Add the sandbox network protocol, client and Linux network service - #346

Merged
SaladDay merged 3 commits into
feature/agent-outside-sandboxfrom
aos/network-protocol
Oct 1, 2026
Merged

SaladDay merged 3 commits into
feature/agent-outside-sandboxfrom
aos/network-protocol

Conversation

@SaladDay

@SaladDay SaladDay commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Adds the Network protocol. The agent-host gateway uses it to open TCP connections that originate in the sandbox: names resolve and connections dial from the sandbox's network namespace, inside the egress the Link grants each Network stream.

  • internal/sandboxnet/protocol.go, the protocol. One Connect{Host, Port, TimeoutMillis} per stream, answered by Connected or a typed failure. Twelve codes, each with a declared effect. The file also defines:
    • the strict codec;
    • the host grammar;
    • the egress check against the Bind's Egress;
    • the Service interface (Resolve, Dial).
  • client.go. Connect(ctx, stream, host, port, timeout) returns a *Conn, which is a net.Conn. CloseWrite sends FIN, and Close aborts with Reset unless the read side ended cleanly.
  • server.go. A generic Serve(ctx, stream, egress, svc), so the egress check and the splice are the same for every implementation:
    • it checks the port first, then the host and each resolved address;
    • it dials the first permitted address once, answers, then splices;
    • FIN becomes CloseWrite after draining, and an error or the end of the attachment resets both sides.
  • apps/sandboxio/internal/netservice (Linux). The system resolver plus an errno-mapped dialer. oac-sandbox-io now serves ServiceNetwork and advertises it in ServeHello.
  • sandboxlink.Stream gains the net.Conn deadline methods, which *yamux.Stream already implements. Conn needs them to be a real net.Conn without a type assertion.
  • Docs.
    • New: docs/sandbox-network-protocol.md.
    • AGENTS.md boundary row and repository-map row.
    • docs/sandbox-link-protocol.md: the stream deadline methods, plus a link from the Egress bullet.
    • docs/sandbox-bootstrap.md: the service also serves Network.

Review fixes (two blind-review rounds):

  • Egress: unspecified addresses are rejected after unmapping, and the dial uses the checked literal through a family-specific network.
  • Effects: EffectNone applies only to failures at socket or connect. Native dial timeouts are typed TimedOut.
  • Forwarding: client bytes wait until Connected is written.
  • Conn: reads and writes are serialized, deadlines follow net.Conn semantics, and FIN is ordered after writes.
  • Link doc: it states the two request-ID sequences on a service stream: the Link exchange, then the service protocol.
  • Network doc: it records the half-close plus link-loss residual.

Tests:

  • Codec: a golden fixture, decode rejection, the host grammar and egress rule, and FuzzDecode.
  • Through the test relay with a fake DNS server:
    • FIN in each direction delivers every byte, then EOF;
    • a destination RST arrives as an abort;
    • Denied without the listener ever accepting;
    • NameNotResolved, ConnectionRefused and TimedOut;
    • a second Connect is a protocol violation;
    • a lost answer gives EffectPossible.
  • The oac-sandbox-io end-to-end test now also echoes bytes over a Network stream restricted to one loopback address and port.

Checks:

  • go test -race: ten runs over sandboxnet and netservice, three over sandboxio.
  • link, relay and bootstrap tests
  • FuzzDecode, 30 s
  • vet and gofmt
  • darwin and windows builds
  • markdown checks
  • make build-sandbox-io

Part of the agent-outside-sandbox work, milestone M1, lane L6a.

internal/sandboxnet defines the Network protocol (one Connect per Link
stream, then raw bytes), its strict codec, host grammar and egress check,
the Connect client with a net.Conn, and the generic Serve that resolves,
checks, dials and splices with orderly half-close and abort kept apart.
apps/sandboxio/internal/netservice is the Linux resolver and dialer.
sandboxlink.Stream gains the deadline methods yamux streams already have.
Never permit an unspecified destination, which a TCP stack connects to the
sandbox itself, and dial the checked literal over tcp4 or tcp6. Give an
errno-typed dial failure EffectNone only when socket or connect returned it.
Hold bytes that arrive after a successful dial until Connected is written.
Serialize Conn reads and writes and fail calls after a passed deadline, as
net.Conn does. State the Stream deadline and concurrency contract, the two
request ID sequences on a service stream and the half-close residual.
@SaladDay
SaladDay merged commit e4fb675 into feature/agent-outside-sandbox Oct 1, 2026
@SaladDay
SaladDay deleted the aos/network-protocol branch October 1, 2026 01:09
Take the write lock for CloseWrite and the orderly Close, so no Write
lands after the FIN; Close aborts instead when a Write is in progress, which
ends the pending call. Update a deadline and its cached copy under one lock.
Type a native dial timeout as TimedOut in the Linux service, and read the
Connect's deadline from the clock, since a socket deadline can fire before
the context reports its end.
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