Documentation
¶
Overview ¶
Package sandbox implements the WASM connector runtime.
Per ADR-0005, every connector runs under an isolation boundary the runtime enforces. v1 targets WASI Preview 1 plus Aileron-specific host imports (`aileron_http_request`, `aileron_log`); the WASI Preview 2 / Component Model surface ratified by ADR-0005 lights up when Wazero supports it. The capability enforcement, resource limits, structured errors, and per-call lifecycle in this package satisfy issue #359's acceptance criteria without depending on P2.
The package exposes a small interface — Runtime and Connector — so the engine is swappable. The default implementation is Wazero; tests substitute fakes where they want to exercise the host-side policy independently.
Index ¶
- Constants
- Variables
- func SandboxAvailable() error
- type Boundary
- type Call
- type Connector
- type Error
- type FailureClass
- type HTTPDoer
- type HostPolicy
- type LimitKind
- type Limits
- type LogLine
- type ProxyEndpoint
- type Result
- type RunHelpResult
- type Runtime
- type RuntimeOption
- type SpawnEnvelope
- type SpawnExecutor
- type SpawnLimits
- type SpawnPolicy
- type SpawnProxy
- type SpawnResult
- type WazeroRuntime
Constants ¶
const ( // DefaultMemoryBytes is the default per-instance memory cap. DefaultMemoryBytes uint64 = 64 * 1024 * 1024 // MaxMemoryBytes is the hard ceiling — manifest requests above this // are clamped. MaxMemoryBytes uint64 = 1024 * 1024 * 1024 // DefaultWallTime is the default per-call wall time. DefaultWallTime = 30 * time.Second // MaxWallTime is the hard ceiling for per-call overrides. MaxWallTime = 5 * time.Minute )
ADR-0005 §"Resource limits are enforced and bounded" defaults and hard ceilings. The connector manifest may request a higher cap, up to the ceiling; the action manifest may override per-call wall time, up to the ceiling. Field-level overrides on the action manifest are not part of the v1 schema and are deferred (see plan).
const HelpTimeout = 5 * time.Second
HelpTimeout caps how long RunHelp waits for `<binary> --help` to produce output before killing the subprocess. Five seconds matches the existing unsandboxed runner the manual `aileron action wrap` flow uses (internal/wrap.HelpRunnerExec), so the introspection deadline is the same whether the caller asks for the sandboxed or unsandboxed variant.
Variables ¶
ErrSpawnUnavailable is returned by SpawnExecutor.Spawn when the running platform does not support the spawn primitive's enforcement requirements. The host function translates this into a structured spawn_sandbox_unavailable error class.
Functions ¶
func SandboxAvailable ¶
func SandboxAvailable() error
SandboxAvailable reports whether the spawn primitive's platform sandbox is usable on this host. Returns nil when the runtime can install the confinement layers ADR-0014 commits to (FS scoping, network egress denial, process scoping); returns a wrapped ErrSpawnUnavailable with an actionable remediation hint otherwise.
Intended for install-time use so a user installing a spawn- using connector on a host without kernel-level confinement gets a clear error before any binary is fetched or stored — per ADR-0014's "Graceful unavailability" section and #719's cross-platform checklist.
Implementation lives in build-tagged sibling files: each platform probes the OS-specific primitives the runtime would need at spawn time:
- Linux: `unprivileged_userns_clone` sysctl.
- macOS: presence of `/usr/bin/sandbox-exec`.
- Windows: open + close a session handle on the Windows Filtering Platform engine (validates BFE is running and the daemon has the rights to install filters).
- Other (BSD, illumos, etc.): the fallback returns ErrSpawnUnavailable unconditionally; ADR-0014 designates those platforms as deny-spawn.
Types ¶
type Boundary ¶
type Boundary string
Boundary identifies the layer that produced a failure (per ADR-0010). The sandbox always emits "sandbox" — the kernel/WASM-engine boundary — regardless of which class is raised. Action-boundary and connector-manifest-boundary denials live in their respective packages (`internal/action` and `internal/cstore`) and emit their own values.
const ( // BoundarySandbox names the WASM sandbox layer. BoundarySandbox Boundary = "sandbox" )
type Call ¶
type Call struct {
Op string
Args map[string]any
Limits Limits
AllowedAuthority []string
CredentialResolver credential.Resolver
// AllowedSpawnPrograms is the action manifest's declared subset of
// programs the connector may invoke via aileron_host.spawn. Each
// entry is an absolute (or ~/-anchored) program path matching the
// connector manifest's [capabilities.spawn].programs declaration.
// Empty means the action did not narrow the connector's grant; the
// connector manifest's policy is the only spawn gate.
AllowedSpawnPrograms []string
}
Call describes one connector operation invocation.
`Op` and `Args` correspond to the action manifest's `[[execute]]` step fields (per ADR-0003) — the executor builds a Call from each step and hands it to the corresponding connector. `Limits` overrides the per-runtime defaults; the zero value uses ADR-0005 defaults (64 MiB / 30 s).
`AllowedAuthority` is the invoking action's declared subset of the connector's capabilities; the network host import checks this in addition to the connector manifest's grant (ADR-0003 §"defense in depth"). When empty, only the connector manifest gates network access.
`CredentialResolver` is the per-invocation handle the host uses to resolve a bound credential when the connector emits an outbound request that references its declared `[capabilities.credential]` (per ADR-0005 credential mediation). Nil means no binding is wired for this call; the host returns `binding_required` if the connector tries to use the credential path. Resolver lifetime is the single Invoke; per-call hostState drops the reference on completion so the connector cannot stash it across calls.
type Connector ¶
type Connector interface {
// Invoke runs `call` in a freshly-instantiated sandbox. Returns a
// structured *Error on capability denial or resource-limit
// termination per ADR-0010.
Invoke(ctx context.Context, call Call) (Result, error)
// Close releases the compiled-module cache. Outstanding Invoke
// calls may complete; calling Invoke after Close is a programming
// error.
Close(ctx context.Context) error
}
Connector is a compiled, ready-to-instantiate connector binary. Each [Connector.Invoke] call creates a fresh sandbox instance, runs the call, and tears it down — per-invocation isolation per ADR-0005's "Connector instances are scoped to a single invocation" requirement.
type Error ¶
type Error struct {
Class FailureClass
Message string
Boundary Boundary
Retriable bool
Details map[string]any
}
Error is a structured sandbox-layer error per ADR-0010. The `Details` map carries class-specific structured context (e.g. denied host:port for capability_denied; named limit for resource_limit_exceeded).
type FailureClass ¶
type FailureClass string
FailureClass is the closed-set classification of sandbox failures. The taxonomy is the subset of ADR-0010's closed set produced at the sandbox boundary; new classes require an ADR amendment.
const ( // ClassCapabilityDenied is the canonical class for any operation // the connector attempted that exceeds its declared grants. The // `Boundary` field disambiguates whether the WASM sandbox itself, // the connector manifest, or the action manifest produced the // denial — see ADR-0010 §"capable_denied" for the full taxonomy. ClassCapabilityDenied FailureClass = "capability_denied" // ClassResourceLimitExceeded is the canonical class for a sandbox // instance that hit a memory, wall-time, or fuel limit. The // `Limit` detail names which one. ClassResourceLimitExceeded FailureClass = "resource_limit_exceeded" // ClassConnectorRuntimeError is the canonical class for a connector // that failed inside its own code path (panicked, returned a // non-zero status, produced a malformed output payload). ClassConnectorRuntimeError FailureClass = "connector_runtime_error" // ClassConnectorLoadFailed is a hard fail at compile or // instantiation time: the WASM module is malformed, refuses to // instantiate, or imports a host function the runtime did not // register. Per ADR-0005 §"WASI host imports are gated by the // connector's `[capabilities.runtime]` declaration", out-of-grant // imports refuse at instantiation. ClassConnectorLoadFailed FailureClass = "connector_load_failed" // ClassBindingRequired is the canonical class for an outbound // request that referenced a credential capability the action did // not bind. The runtime mediates every credential use per ADR-0005; // when the connector emits an `http_request` with a `credential` // field but the action has no `[[bindings]]` entry that points at a // vault path with the expected kind, the host returns this class. // Mirrors `failure.BindingRequired` in the executor's surface. ClassBindingRequired FailureClass = "binding_required" )
type HTTPDoer ¶
HTTPDoer is the narrow HTTP-client surface the sandbox needs. It matches `*http.Client.Do`'s signature so tests can substitute an in-memory client without HTTP. The runtime injects a Doer per invocation; default is a stock `*http.Client`.
type HostPolicy ¶
type HostPolicy struct {
// contains filtered or unexported fields
}
HostPolicy enforces the connector manifest's `[capabilities.network]` declaration: outbound calls to undeclared hosts are denied at the syscall layer per ADR-0005 acceptance criterion #3.
Hosts are pinned `host:port` pairs (per ADR-0002 §"network access"); no wildcards are honored. The match is exact on both the host and the port.
func NewHostPolicy ¶
func NewHostPolicy(m *cstore.Manifest) *HostPolicy
NewHostPolicy builds a HostPolicy from a connector manifest. A nil or missing `[capabilities.network]` block produces a deny-all policy — the connector did not declare network access and may not dial out.
func (*HostPolicy) AllowedHosts ¶
func (p *HostPolicy) AllowedHosts() []string
AllowedHosts returns a sorted-stable copy of the policy's grant for auditing/error-detail purposes.
func (*HostPolicy) CheckHostPort ¶
func (p *HostPolicy) CheckHostPort(hostPort string) error
CheckHostPort verifies a `host:port` string is in the allowed set. Mirrors HostPolicy.CheckURL's contract for the spawn-proxy path, where the proxy receives a host:port directly from the CONNECT request and does not have a full URL to parse.
Returns a structured `*Error` of class `capability_denied` and boundary `sandbox` when the call is refused.
func (*HostPolicy) CheckURL ¶
func (p *HostPolicy) CheckURL(rawURL string) error
CheckURL parses `rawURL` and verifies its host:port is in the allowed set. Returns a structured *Error of class `capability_denied` and boundary `sandbox` when the call is refused.
HTTPS URLs default to port 443; HTTP URLs default to port 80; URLs with explicit ports use those. Schemes other than http/https are rejected — the connector ABI exposes HTTP only in v1, and any other scheme is a misuse of the host import.
type LimitKind ¶
type LimitKind string
LimitKind names which resource limit was exceeded. Used in the `Details["limit"]` field of a Error when [Error.Class] is ClassResourceLimitExceeded (per ADR-0010's "specific limit named" requirement).
type Limits ¶
Limits configure resource ceilings per ADR-0005's "Resource limits are enforced and bounded" table. The zero value means "use ADR defaults".
MemoryBytes default is 64 MiB; the connector manifest may request a higher cap up to a hard ceiling of 1 GiB. WallTime default is 30 s, per-call override capped at 5 minutes.
func (Limits) MemoryPages ¶
MemoryPages converts MemoryBytes to WebAssembly memory pages (64 KiB each), rounding *up* so the cap is never less than what the caller requested. Wazero's memory-limit API works in pages, not bytes.
func (Limits) Resolve ¶
Resolve takes the caller-supplied limits, the connector manifest's declared overrides (if any), and produces the effective per-call limits. Zero values fall back to ADR defaults; values above the hard ceilings are clamped.
Precedence (highest wins):
- Caller's explicit non-zero limit (e.g. action manifest override).
- Connector manifest's declared cap.
- ADR-0005 default.
type ProxyEndpoint ¶
type ProxyEndpoint struct {
// TCPAddr is the host:port the proxy is listening on for
// non-Linux platforms. Empty on Linux.
TCPAddr string
// UDSPath is the host filesystem path of the Unix-domain
// socket the proxy is listening on for Linux. Empty on
// non-Linux platforms.
UDSPath string
}
ProxyEndpoint describes where a per-spawn CONNECT proxy is listening. macOS and Windows ([SBPL] / [WFP]) permit the wrapped CLI to reach a TCP loopback port directly, so [TCPAddr] is the `HTTPS_PROXY` value the runtime sets on the subprocess. Linux puts the wrapped CLI in a new network namespace under `CLONE_NEWNET`, where the host's TCP loopback is unreachable; the proxy binds on a Unix-domain socket whose path is in [UDSPath], and the in-namespace spawn helper bridges TCP from inside the namespace to that socket.
Exactly one of TCPAddr or UDSPath is populated for a given platform. The runtime's [processSpawn] selects which to set on the wrapped CLI's environment vs. on the helper request based on which field is non-empty.
type Result ¶
Result is what the sandbox produced. Successful runs surface their `Output` map; the executor encodes it into the tool-result content the LLM observes. `Logs` is the connector's structured log emissions during the call (via `aileron_log`).
type RunHelpResult ¶
RunHelpResult is the captured outcome of a single sandboxed `<binary> --help` invocation. Both Stdout and Stderr may be populated regardless of ExitCode; many CLIs write usage to stderr while still exiting non-zero (notably `curl`), and callers parse whichever stream contains the help text.
func RunHelp ¶
func RunHelp(ctx context.Context, programPath, cwd string, subcommandPath ...string) (RunHelpResult, error)
RunHelp invokes `<programPath> --help` under the platform spawn sandbox the runtime uses for declared connector actions. Confinement matches what would apply to a hub-published connector calling spawn at runtime:
- fs_read scoped to `cwd` only (the directory the user invoked the CLI from). No `$HOME`, no user-config dirs.
- fs_write denied entirely.
- network egress denied entirely (no [capabilities.network] declared, so the sandbox engages without a proxy port).
- HelpTimeout (5s) deadline; the subprocess is killed if it hasn't exited by then.
- stdout / stderr capped to cstore.DefaultMaxStdoutBytes and cstore.DefaultMaxStderrBytes; output beyond the cap is dropped with a structured truncation marker per ADR-0014.
`subcommandPath` is the verb chain prepended before `--help`. Nil/empty yields `<programPath> --help` (the root-help call); `["issues", "create"]` yields `<programPath> issues create --help` so the introspector can walk Cobra-style nested verb trees. Each call is its own sandboxed invocation — callers running many paths in sequence pay the per-call sandbox-startup cost N times.
`programPath` must be absolute. RunHelp returns the ErrSpawnUnavailable wrapper from SandboxAvailable when the host can't honor the confinement the docstring promises — callers should treat that as a hard install-time failure rather than fall back to unsandboxed exec.
Intended caller: the `aileron cli add` introspector (issue #749), which parses the captured stdout via internal/wrap's `--help` parser. Generalizable to any other one-shot sandboxed invocation that doesn't need a fully-formed connector manifest on disk first.
type Runtime ¶
type Runtime interface {
// Compile prepares a connector for invocation. Compilation is
// typically expensive (Wazero parses, validates, and ahead-of-time
// translates the WASM module); instances produced from the compiled
// form are cheap.
//
// `manifest` is the connector's parsed `manifest.toml` — the runtime
// uses its `[capabilities.network]` and resource declarations to
// gate calls and configure limits per ADR-0002 / ADR-0005.
// `binary` is the raw `.wasm` bytes from the content-addressed
// store.
Compile(ctx context.Context, manifest *cstore.Manifest, binary []byte) (Connector, error)
// Close releases the runtime and any compiled connectors. Calling
// Compile after Close is a programming error.
Close(ctx context.Context) error
}
Runtime is the engine that compiles connector binaries and produces invokable Connector handles. A Runtime is goroutine-safe; multiple Connectors compiled from a single Runtime may be invoked in parallel.
type RuntimeOption ¶
type RuntimeOption func(*WazeroRuntime)
RuntimeOption configures a WazeroRuntime at construction.
func WithHTTPDoer ¶
func WithHTTPDoer(d HTTPDoer) RuntimeOption
WithHTTPDoer overrides the HTTP client the sandbox uses for `aileron_host.http_request`. Defaults to http.DefaultClient; tests substitute fake doers to exercise the host policy without network.
func WithLogger ¶
func WithLogger(log *slog.Logger) RuntimeOption
WithLogger sets the slog.Logger used to emit connector log lines and runtime diagnostics.
func WithSpawnExecutor ¶
func WithSpawnExecutor(e SpawnExecutor) RuntimeOption
WithSpawnExecutor overrides the executor the runtime uses for `aileron_host.spawn`. Defaults to the production defaultSpawnExecutor; tests substitute fake executors to exercise the gate and the host-function plumbing without forking real processes.
type SpawnEnvelope ¶
type SpawnEnvelope struct {
Program string `json:"program"`
Argv []string `json:"argv"`
Env map[string]string `json:"env,omitempty"`
Cwd string `json:"cwd,omitempty"`
Stdin string `json:"stdin,omitempty"`
CredentialEnvKeys []string `json:"credential_env_keys,omitempty"`
}
SpawnEnvelope is the JSON shape connectors marshal as input to `aileron_host.spawn`. Designed to be ergonomic across language ABIs; the runtime parses it host-side.
Fields:
- Program: absolute path or ~/-anchored path of the binary to invoke.
- Argv: the full argument vector starting with argv[0]. The runtime compares the argv (after placeholder elision) against the manifest's argv_patterns.
- Env: the environment to set on the subprocess. Each key must be in the manifest's env_passthrough; values are caller-supplied except for keys in CredentialEnvKeys, which the runtime resolves and injects.
- Cwd: optional working directory. Must match the manifest's cwd (when set) and lie within fs_read.
- Stdin: optional bytes piped to the subprocess on stdin.
- CredentialEnvKeys: optional list of env keys whose values the runtime should resolve from the connector's bound credential and inject. The connector never holds the credential bytes.
type SpawnExecutor ¶
type SpawnExecutor interface {
Spawn(ctx context.Context, env SpawnEnvelope, limits SpawnLimits) (SpawnResult, error)
}
SpawnExecutor is the narrow surface the host functions use to actually invoke a subprocess. Tests substitute fakes; the production implementation forks an os/exec.Cmd with the platform's sandbox applied (per ADR-0014).
The executor is invoked only after CheckSpawn has approved. It is responsible for the second-line enforcement (FS scoping, network denial, process scoping) on the platforms it supports, and for honoring the runtime-supplied SpawnLimits when capturing the subprocess's stdout and stderr. On unsupported platforms it returns ErrSpawnUnavailable so the host function emits a structured spawn_sandbox_unavailable error.
type SpawnLimits ¶
type SpawnLimits struct {
// MaxStdoutBytes caps the bytes the executor returns in
// [SpawnResult.Stdout]. Output past this point is dropped and
// a structured truncation marker is appended to the captured
// bytes.
MaxStdoutBytes int64
// MaxStderrBytes caps the bytes the executor returns in
// [SpawnResult.Stderr]. Same truncation semantics as
// MaxStdoutBytes.
MaxStderrBytes int64
// FSRead is the manifest's declared read-scope (per
// [cstore.ManifestSpawn.FSRead]). The platform sandbox
// translates these into kernel-enforced filesystem confinement
// (Linux Landlock + mount namespace, macOS SBPL `file-read*`
// rules, Windows ACL adjustments).
FSRead []string
// FSWrite is the manifest's declared write-scope (per
// [cstore.ManifestSpawn.FSWrite]). Same role as FSRead but
// for writes.
FSWrite []string
// ProxyAddr is the per-invocation proxy endpoint the platform
// sandbox permits loopback access to. Empty when the connector
// did not declare `[capabilities.network]` or when the proxy
// is reachable only via [ProxyUDSPath] (Linux + helper bridge).
// Format is `host:port`, typically `127.0.0.1:<ephemeral>`.
// macOS reads this for the SBPL `(allow network*)` rule;
// Windows for the WFP filter.
ProxyAddr string
// ProxyUDSPath is the host-filesystem path of a Unix-domain
// socket the per-invocation CONNECT proxy is listening on.
// Linux populates this when the wrapped CLI runs inside a
// `CLONE_NEWNET` namespace where the host's TCP loopback is
// unreachable; the in-namespace spawn helper bridges from a
// namespace-local TCP loopback to this socket via
// [RunSpawnShim]. Empty on macOS, Windows, and on Linux for
// connectors that don't trigger the helper rewire.
ProxyUDSPath string
}
SpawnLimits carries the runtime-decided per-invocation parameters the executor needs in addition to the connector-supplied envelope. Originally just byte caps for captured output, the struct now carries the resolved filesystem scopes and proxy endpoint the platform sandbox uses to construct its per-OS confinement (per ADR-0014's "Network confinement: daemon-mediated proxy" and the per-platform sandbox sections).
The runtime resolves every field from the manifest plus per-spawn state (proxy port) before calling the executor. Connectors never set these directly.
func (SpawnLimits) PlatformSandboxRequested ¶
func (l SpawnLimits) PlatformSandboxRequested() bool
PlatformSandboxRequested reports whether the manifest carried any platform-sandbox-relevant declaration (FS scope, network proxy). Used by each platform's [applyPlatformSandbox] to decide whether to engage the OS-level confinement. A zero-value SpawnLimits (legacy spawn with no manifest scopes) returns false so tests and pre-sandbox callers keep running unchanged.
type SpawnPolicy ¶
type SpawnPolicy struct {
// contains filtered or unexported fields
}
SpawnPolicy enforces a connector manifest's `[capabilities.spawn]` declaration (per ADR-0002 spawn primitive, ADR-0014 sandbox tech). Built once per connector and consulted on every spawn host-function call before any process is created.
SpawnPolicy is the gate; the platform sandbox in `spawnExecutor` is the second-line enforcement. Both must agree for a call to proceed.
The policy also carries the per-stream output caps the runtime applies to subprocess stdout and stderr (per cstore.ManifestSpawnLimits and ADR-0014's output-cap consequences). The caps are derived once from the manifest at policy construction and consulted on every spawn invocation.
func NewSpawnPolicy ¶
func NewSpawnPolicy(m *cstore.Manifest) *SpawnPolicy
NewSpawnPolicy builds a SpawnPolicy from a connector manifest. A nil or absent `[capabilities.spawn]` block produces a deny-all policy: the connector did not declare spawn and may not invoke a subprocess.
func (*SpawnPolicy) BuildEnvelopeFromOp ¶
func (p *SpawnPolicy) BuildEnvelopeFromOp(opName string, args map[string]string, getEnv func(string) string) (SpawnEnvelope, *Error)
BuildEnvelopeFromOp resolves `opName` against the manifest's [capabilities.spawn.operations] table, substitutes `{name}` placeholders in the operation's argv pattern from `args`, and returns a fully-formed SpawnEnvelope ready for CheckSpawn / processSpawn.
`getEnv` resolves the values for the manifest's env_passthrough keys from a source the caller chooses (e.g. os.Getenv in production; a fake in tests). Empty values are omitted from the envelope.
Returns a structured *Error of class capability_denied when:
- The op name is not declared in the manifest's operations table (boundary_detail: connector_manifest).
- A placeholder in the operation's argv has no matching arg (boundary_detail: envelope, set by argvPattern.Substitute).
- The policy has no primary program (no programs declared).
func (*SpawnPolicy) CheckSpawn ¶
func (p *SpawnPolicy) CheckSpawn(env SpawnEnvelope) error
CheckSpawn validates an incoming SpawnEnvelope against the connector manifest's [capabilities.spawn] declaration. Returns a structured *Error of class capability_denied (boundary=sandbox) when the envelope falls outside the grant.
The check is the first gate; the action-boundary subset (when supplied) and the platform sandbox apply additional enforcement. Mirrors HostPolicy.CheckURL's role for network capabilities.
func (*SpawnPolicy) StderrCap ¶
func (p *SpawnPolicy) StderrCap() int64
StderrCap returns the resolved stderr byte cap.
func (*SpawnPolicy) StdoutCap ¶
func (p *SpawnPolicy) StdoutCap() int64
StdoutCap returns the resolved stdout byte cap. Always positive when the policy was constructed from a valid manifest.
type SpawnProxy ¶
type SpawnProxy struct {
// contains filtered or unexported fields
}
SpawnProxy is the per-invocation HTTP CONNECT proxy that mediates a spawned subprocess's outbound network. The proxy is the single enforcement seam for `[capabilities.network]` on spawn connectors (per ADR-0014's "Network confinement: daemon-mediated proxy" section). One proxy is created per spawn call, served on a local-only listener the runtime hands in (TCP loopback on macOS/Windows; Unix-domain socket on Linux), then closed when the spawn completes.
The proxy operates at the CONNECT method only. It does not terminate TLS, so it sees host:port plus tunneled bytes but never the request URL, headers, or body. Allowlist evaluation reuses HostPolicy from the WASM network gate; both gates check against the same `host:port` set.
func NewSpawnProxy ¶
func NewSpawnProxy(policy *HostPolicy, logger *slog.Logger, fqn string) *SpawnProxy
NewSpawnProxy constructs a proxy that enforces `policy` and emits audit attributes naming `fqn`. The proxy is not started until SpawnProxy.Serve is called. `logger` is optional; nil suppresses audit emission (useful in tests).
func (*SpawnProxy) Close ¶
func (p *SpawnProxy) Close() error
Close shuts down the proxy. Outstanding CONNECTs are allowed to finish; new accepts unblock with net.ErrClosed. Safe to call from any goroutine. Idempotent.
func (*SpawnProxy) Serve ¶
Serve accepts connections on `ln` until the listener returns net.ErrClosed (typically via SpawnProxy.Close). Each accepted connection is handled in its own goroutine. Serve blocks until the listener is closed and all in-flight CONNECTs have drained.
Returns nil on a clean shutdown via Close; returns the underlying accept error otherwise.
func (*SpawnProxy) SetDialer ¶
func (p *SpawnProxy) SetDialer(dial func(ctx context.Context, network, addr string) (net.Conn, error))
SetDialer overrides the function the proxy uses to reach upstream hosts. The runtime never calls this; tests inject fakes to avoid dialing real network endpoints. Must be called before [Serve].
type SpawnResult ¶
SpawnResult is the captured outcome of a single subprocess invocation returned to the connector through the host-function read path.
type WazeroRuntime ¶
type WazeroRuntime struct {
// contains filtered or unexported fields
}
WazeroRuntime is the default Runtime implementation, backed by Wazero (the only viable pure-Go WASM engine in v1; see the plan file at /Users/alr/.claude/plans/are-there-alternatives-to-stateless-starfish.md).
One WazeroRuntime supports many [Connector]s, instantiated lazily as connectors are compiled. Each Connector compiles its WASM bytes once and caches the result; per-call invocation creates a fresh module instance from the cached compilation, runs `_start`, and tears the instance down — the per-invocation isolation required by ADR-0005's acceptance criterion #8.
func NewWazeroRuntime ¶
func NewWazeroRuntime(ctx context.Context, opts ...RuntimeOption) (*WazeroRuntime, error)
NewWazeroRuntime builds a Wazero-backed runtime with the supplied options. Callers must Close() the returned runtime when finished.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package forwarder embeds the shared spawn-forwarder WASM into the Aileron daemon binary.
|
Package forwarder embeds the shared spawn-forwarder WASM into the Aileron daemon binary. |
|
Package sandboxtest provides reusable test helpers for the spawn primitive (per ADR-0002, ADR-0014).
|
Package sandboxtest provides reusable test helpers for the spawn primitive (per ADR-0002, ADR-0014). |
|
Package spawnhelper defines the post-namespace setup step that runs inside the spawn-sandbox namespace before the wrapped CLI exec's.
|
Package spawnhelper defines the post-namespace setup step that runs inside the spawn-sandbox namespace before the wrapped CLI exec's. |