Documentation
¶
Overview ¶
Package control is the harness side of the control channel: it hosts the local listener the governed server's servant dials, authenticates the first message against the bootstrap token, negotiates a protocol version, and then dispatches envelopes.
The transport is platform-split: a named pipe with an SDDL admitting only the current user and SYSTEM on Windows, a mode-0700-dir unix socket elsewhere (which is also what CI's ubuntu leg exercises). The bootstrap contract is two environment variables on the child: AGENTWEAVE_CONTROL_PIPE (the address) and AGENTWEAVE_CONTROL_TOKEN (32 random bytes, hex), which the server must read and scrub before any tool can observe them.
Index ¶
- Constants
- Variables
- func Dial(addr string) (net.Conn, error)
- type Handler
- type Host
- type Session
- func (s *Session) Ack(ack wire.HelloAck) error
- func (s *Session) Close() error
- func (s *Session) Request(ctx context.Context, typ string, payload any) (wire.Envelope, error)
- func (s *Session) Send(typ, id, re string, payload any) error
- func (s *Session) Serve(logger *slog.Logger, handlers map[string]Handler) error
Constants ¶
const ( EnvPipe = "AGENTWEAVE_CONTROL_PIPE" // EnvToken names the env var carrying the bootstrap token; the name is // not itself a secret. EnvToken = "AGENTWEAVE_CONTROL_TOKEN" //nolint:gosec // G101: env var name, not a credential )
Env var names of the bootstrap contract.
Variables ¶
var ( // ErrBadToken reports a hello whose token does not match. The caller must // treat this as fatal for the child. ErrBadToken = errors.New("control: hello token mismatch") // ErrNotHello reports a first message that is not a hello. ErrNotHello = errors.New("control: first message is not hello") // ErrNoCommonVersion reports disjoint protocol ranges. The session must // be refused, never run degraded. ErrNoCommonVersion = errors.New("control: no common protocol version") // ErrChannelClosed reports a Request left in flight when the channel ended. ErrChannelClosed = errors.New("control: channel closed") )
Control-channel errors.
Functions ¶
Types ¶
type Handler ¶
Handler consumes one envelope. Returning an error ends the serve loop — reserve it for channel-fatal conditions, not bad payloads.
type Host ¶
Host owns the listener and the token for one session.
func (*Host) AwaitServant ¶
AwaitServant accepts one connection and runs the hello exchange. It does NOT send hello.ack — the caller decides mode and effective config and completes the handshake with Session.Ack. A token mismatch returns ErrBadToken and the caller must kill the child: an unauthenticated peer on the channel means the bootstrap secret leaked or the wrong process dialed.
type Session ¶
Session is an authenticated, version-negotiated servant connection.
func (*Session) Request ¶ added in v0.3.0
Request sends a harness-originated request and waits for the servant's correlated response, which Serve delivers by matching its `re` to this request's id. Serve must be running concurrently — it owns the read loop — or the response is never routed. A response whose payload is a `{"error":...}` object is returned as-is for the caller to interpret.
func (*Session) Serve ¶
Serve reads envelopes until the channel closes, dispatching by type.
Tolerance is deliberate and asymmetric, per docs/wire-protocol.md: an unknown *notification* type is logged and ignored (a newer servant may emit types this harness predates), but an unknown *request* — an envelope carrying an id, expecting an answer — gets an error reply so the peer fails loudly instead of hanging. io.EOF is a clean channel end.