Skip to main content

What Substrate promises, and where

Substrate publishes several contracts. Each one has its own consumers, its own source of truth and its own check. This page lists them, shows how they relate, and defines the confinement contract's families and facts.

The contracts at a glance​

ContractUsed byDefined inChecked by
Wire contract: HTTP and WebSocketthe Rust SDK, the command line, the MCP adapter, other callers of the daemonimmutable versioned bundles in contracts/substrate-wire/, newest 0.23.0, published as the signed OCI artifact ghcr.io/beyond10x/b10x-substrate-wirethe full gate; every response names its bundle and digest in headers
Confinement contractembedders of the b10x-substrate-host crate and b10x-substrate confine runthe ESS domain substrate.confinement in spec/confinement/cargo xtask check-ess against the interpreted reference, and each adapter's lane against the adapter
Confinement consumer surfaceRust code that calls substrate_host::confinementtests/confinement-public-items.txt in the host cratetests/confinement_public_items.rs and tests/consumer_surface.rs
Command linepeople and scripts in a shellthe ESS domain substrate.client and its ess-cli/2 binding in spec/client/cargo xtask check-ess against the generated package in spec/generated/cli
Daemon modelscontributors to the daemon and storethe ESS domains substrate.operations, substrate.workspaces, substrate.host_processes and substrate.sessions in spec/cargo xtask check-ess, and the store's own conformance run for the operation ledger

How they relate​

  • The wire contract is the daemon's public surface. A caller reaches the daemon over its socket; the daemon admits the request, records an operation and dispatches it to the host driver. The wire contract reference lists its routes.
  • The confinement contract is in process. An embedder opens an adapter with confinement::open and admits a profile against what the adapter proved. It is the host crate's API, not the wire contract: no wire bundle changes with it.
  • The linux adapter wraps the host driver the daemon dispatches to. Its families are read from the same capability facts (exec.*, workspace.*) the daemon publishes on the wire, as its driver's probe proved them when the adapter opened.
  • b10x-substrate confine run is the command line over the confinement contract, without a daemon: it builds one profile from its flags and lets the adapter admit or refuse it. The command line guide lists its flags.
  • The ESS domains are executable specifications: cargo xtask check-ess validates each, holds its synthesized suite and its generated Rust types to their regenerated bytes, and runs the suite against ESS's interpreted reference. That checks the model; the adapter lanes and the daemon's tests check the code.

The confinement contract​

An adapter declares, when it opens, the families it serves and the facts it proved. A profile names the families and facts it needs, explicitly or through its fields. Admission refuses the first family or fact the adapter lacks, by name, before anything runs: confinement.family-unserved or confinement.fact-unserved, both status 501. The adapters page shows which adapter declares what.

The ten families​

A refusal names the first missing family in this order.

FamilyWhat needs it
process_runevery start: a start is refused on an adapter that does not serve it
process_watcha profile that lists it in families; no field implies it
output_reada profile that lists it in families; no field implies it
waita profile that lists it in families; no field implies it
workspacethe profile's workspace and workdir
filesystem_viewwritable_roots, read_only_roots and read_only_files
network_egressnetwork: Egress, and network: Isolated on an adapter that proves host_network
network_ingressno adapter serves it; ingress_routes is reserved
limitsprocess_bounds and io_bounds
auditan audit sink for admission, refusal and start records

Every adapter's declared set in the specification holds process_run, process_watch, output_read, wait, workspace and audit; the specification's model-* scenario refuses each by name on an adapter that lacks it.

The thirteen facts​

A refusal names the first missing fact in this order.

FactMeaning
declared_insecurethe run is unconfined and every observation says so
paths_are_host_pathsa path the program sees is the host path, with no remapped mount
whole_tree_killa kill reaches every process of the tree
local_permittedthe host's policy permits local; without it local is refused
ipc_socket_allowlistsocket(2) families are an allowlist
ipc_signals_containedno signal reaches a process outside the tree
sealed_pathspaths inside a writable workspace stay unwritable
exec_subpathsexec is admitted by declared subpath, not only by literal program
private_tmpdira per-run TMPDIR, invisible to another run and gone after wait
host_networkthe run uses the host's network directly
image_digest_pinnedthe image runs by digest only
stdin_pipethe run's standard input is a pipe the embedder writes and closes; without it, /dev/null
output_livethe run's output reaches the embedder while it runs, in order per stream, from a bounded queue whose stall ends the run; without it, output is read from the record

Two facts are checked when an adapter opens: local, bare or inside systemd, must prove declared_insecure, and oci and pod must prove image_digest_pinned. An open without them is refused confinement.fact-unserved naming the fact.

Admission order​

Admission refuses in a fixed order: a reserved field (ingress_routes, rate_bounds), an adapter that did not open, a missing reason on a declared-insecure adapter, an unpinned image on a digest-pinning adapter, the host's policy against local, the first missing family, then the first missing fact. The profile guide gives each code and status.

Scenarios and lanes​

The specification holds 65 authored scenarios. Each is named for its adapter and the lane it runs in, and each adapter's test file runs its lane's scenarios against the real adapter.

LaneScenariosRuns against
portable20local, and the open refusals and absences any host can check
delegated20linux and systemd on a host with a delegated cgroup v2 root
macos10macos on the macos-15 CI job
oci7oci against Docker in the gate workflow
pod5pod against a pinned kind cluster in the gate workflow
interpreted3ESS's interpreted reference only

The consumer surface​

The public items of substrate_host::confinement are frozen: tests/confinement_public_items.rs fails when an item is added, removed or changes signature without the same change to tests/confinement-public-items.txt. tests/consumer_surface.rs chooses adapters by their families and facts only, as a consumer must, and runs a read-only toolchain root, a workspace writing target/, a working directory beneath it, a build into a declared writable root and a --version run of the result: on local, which refuses each filesystem view, and on linux, where every need runs.