Release Channel Adapters#
Purpose#
The channel adapters let the release rail call external build and proof machines without storing reach details in the repository. The rail owns request and response validation; the adapters only move bytes, run the rail-approved commands, and write the JSON files the rail already parses.
Adapter entry points:
scripts/channel_adapters/adapter_common.pyscripts/channel_adapters/build_host_macos.pyscripts/channel_adapters/proof_host.py
Safety Contract#
Do not put real host names, users, addresses, ports, key paths, signing session names, or machine-local working paths in source, tests, docs, or commit messages. Operator-specific values belong only in the JSON config file.
The repo-wide scrub gate is scripts/check_channel_adapter_scrub.py.
It scans tracked UTF-8 text files; tracked NUL-binary and undecodable paths are
skipped and reported by count. Tracked symlink target strings are scanned as
text at the symlink path. A tracked file that cannot be read is a finding, not a
silent skip.
The gate permits only documented, non-reachable fixtures. Reserved hostnames are covered by a reserved-host rule for RFC-reserved example/test/invalid/local names. Other fixture user-host values must be individually listed with comments that explain the source and why the exact value is not channel reach data.
Config Location#
By default, the adapters read:
$XDG_CONFIG_HOME/solstone/channel-adapters.json~/.config/solstone/channel-adapters.jsonwhenXDG_CONFIG_HOMEis unset
RELEASE_CHANNEL_ADAPTER_CONFIG overrides the config path only. It does not
override individual fields.
Schema#
The config is a JSON object with schema_version, build, and proof keys.
The build lane and every proof target known to the rail must be present.
{
"schema_version": 1,
"build": {
"macos-arm64": {
"mode": "ssh",
"host": "build-host.example",
"port": 2222,
"user": "builder",
"identity_file": "~/.ssh/solstone-channel-adapter-build",
"extra_ssh_options": ["-o", "BatchMode=yes"],
"remote_python": "python3",
"remote_work_prefix": "/tmp/solstone-channel-adapter",
"remote_run_wrapper": "operator-session-wrapper",
"tmux_window": "adapter:build",
"unlock_workdir": "~/projects/build-worktree"
}
},
"proof": {
"linux-x86_64-musl": {
"mode": "local"
},
"linux-aarch64-musl": {
"mode": "ssh",
"host": "proof-aarch64.example",
"user": "proof",
"remote_python": "python3",
"remote_work_prefix": "/tmp/solstone-channel-adapter"
},
"macos-arm64": {
"mode": "ssh",
"host": "proof-macos.example",
"user": "proof",
"remote_python": "python3",
"remote_work_prefix": "/tmp/solstone-channel-adapter"
}
}
}
Lane Modes#
mode: "ssh" requires host. port, user, identity_file,
extra_ssh_options, remote_python, and remote_work_prefix are optional.
mode: "local" means run in-process with no SSH or SCP. It is valid only for
the linux-x86_64-musl proof lane.
The macOS build lane also requires remote_run_wrapper, tmux_window, and
unlock_workdir; these name the operator-provided command wrapper and the
already-prepared operator session used to run the existing build target.
Proof Lane Payload#
A proof lane produces a receipt pair per target from a single host round-trip: the install/smoke proof and a challenge-bound nvattest proof. The request therefore carries, in addition to the candidate wheels and ledger, the locked support-wheel set, the canonical nvattest authority bytes, and the challenge. The response carries two explicit proof descriptors rather than one.
Two names sit close together and mean different things. The channel seam the
rail calls is run_target_proofs; it returns both receipt paths. The install
prover the adapter harness invokes remains
scripts.release_install_smoke.run_install_proof and is unchanged. The harness
invokes that prover and scripts.release_nvattest_proof.run_nvattest_proof
side by side, writing one output file for each.
The authority appears in the request twice by design, mirroring how candidate wheels are carried: as a descriptor of its digest and byte count, and as a staged file path. Support wheels are staged, copied, and re-hashed after the copy exactly as candidate wheels are, and the staged support directory is covered by the same directory-identity guards. Cleanup still always runs, local and remote.
Tool Evidence#
The macOS build adapter derives expected tool evidence from the rail pins. For
host-variant tools it emits the real observed banner and validates that the
parsed version identity matches the pin. Every emitted evidence string is passed
through the public-evidence validator before response.json is written.
Failure Modes#
Config validation happens before network or filesystem side effects. Missing or
unknown keys fail closed and name the config path plus
RELEASE_CHANNEL_ADAPTER_CONFIG.
Remote sentinel checks require both exit status zero and the expected success token. Missing tokens fail the adapter even when the subprocess exits zero.
Retrieved build artifacts and proof files are checked for regular-file presence, non-empty bytes, and the digest/byte count reported by the remote harness before the response is written. Missing, malformed, duplicate, unexpected, or invalid artifact digest lines fail closed.
Operator Checklist#
Create the config file outside the repository, keep its values out of shell history and commits, and run the scrub gate before handing a branch to the rail.
When adding or changing proof targets in the rail, update the config at the same time. Adapter tests assert that the configured lane set derives from the rail's target map.