Help us shape the future of Go! Take the 2026 Go Developer Survey

control

package
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 9, 2026 License: MIT Imports: 15 Imported by: 0

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

View Source
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

View Source
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

func Dial

func Dial(addr string) (net.Conn, error)

Dial connects to the control channel — see dial_windows.go for why the dialer lives here.

Types

type Handler

type Handler func(env wire.Envelope) error

Handler consumes one envelope. Returning an error ends the serve loop — reserve it for channel-fatal conditions, not bad payloads.

type Host

type Host struct {
	Addr  string
	Token string
	// contains filtered or unexported fields
}

Host owns the listener and the token for one session.

func NewHost

func NewHost(logger *slog.Logger) (*Host, error)

NewHost creates the platform listener and mints the session token.

func (*Host) AwaitServant

func (h *Host) AwaitServant(ctx context.Context) (*Session, error)

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.

func (*Host) Close

func (h *Host) Close() error

Close tears the listener down.

type Session

type Session struct {
	Hello   wire.Hello
	Version int
	// contains filtered or unexported fields
}

Session is an authenticated, version-negotiated servant connection.

func (*Session) Ack

func (s *Session) Ack(ack wire.HelloAck) error

Ack completes the handshake with the caller's mode and effective config.

func (*Session) Close

func (s *Session) Close() error

Close closes the connection.

func (*Session) Request added in v0.3.0

func (s *Session) Request(ctx context.Context, typ string, payload any) (wire.Envelope, error)

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) Send

func (s *Session) Send(typ, id, re string, payload any) error

Send writes an envelope, stamping the session's protocol version.

func (*Session) Serve

func (s *Session) Serve(logger *slog.Logger, handlers map[string]Handler) error

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL