hive-claude adds its variables on top of the parent's environment, so
claude inherited the daemon's store identity paths, CREDENTIALS_DIRECTORY
and queue coordinates. claude now starts as this same binary with
SWARM_REVIEW_CLASSIFIER_EXEC_CLAUDE naming the real one; main execs it
before the runtime starts, with the environment cleared down to the API
key, PATH, HOME, CLAUDE_CONFIG_DIR and claude's telemetry settings. The
exec keeps the pid, so hive-claude's cancel and idle timeout still reach
it. An integration test runs the built binary as the trampoline and
checks that a BAO_* variable does not reach the program it execs.
The leaf's key was copied by a host unit into the container's root on
host disk. nspawn now reads the cert, key and store CA as root at
container start (--load-credential) and passes them in as system
credentials; the daemon's unit loads them by bare id, as an agent's
container does with its own leaf (nix/agent-modules/bao.nix). The copy
unit is gone. Where this host mints the leaf, the container starts after
swarm-bao-pki, since nspawn refuses a missing credential source. An
assertion refuses identity paths with whitespace, which nixos-container's
unquoted extra flags would split.
A new service crate. It reads its queue client secret from the store at
start, takes try-outs on the review classifier subject in its queue
group, and for each run reads the Anthropic API key from the store,
builds the shared context (commits with full messages, diff with
lockfiles collapsed), runs one claude --print per classification with no
session, no tools, no MCP server and the key in the child's environment
only, validates the JSON answer and aggregates the rows. A missing key or
a run where no classification got an answer fails the run; one failed
classification is an excluded row with its error. One journal line per
run names the operator, repo, PR, head SHA, rows and overall verdict.
swarm-secret-client gains the two paths the service reads.