fix(fleet): a VM reaches its OWN provider and no other, measured not assumed

The GLM backend works — and proving it produced a better boundary than the one
I shipped an hour ago.

WHAT THE FIRST GLM MISSION SHOWED. It completed, and the delivered file said the
model was "claude-opus-5". The node's egress log said the VM had dialled
`api.anthropic.com` five times before `api.z.ai`. Either reading alone is
consistent with a "GLM backend" that silently runs Anthropic — the exact
silent-success shape this project keeps closing — so I did not accept either.

THE ABLATION, run on tank rather than reasoned about: deny `anthropic.com` at the
proxy and run the same mission again. It **completed**, dialling only
`api.z.ai`. So the completions genuinely come from z.ai; Claude Code's calls to
anthropic.com are its own telemetry, not its model traffic.

And that same agent — served exclusively by z.ai, with Anthropic unreachable —
still described itself as "Claude Opus 5 (1M context)". **A model's account of
which model it is has no evidential value.** The proxy's log of which host it
dialled does. This is the `uname -r` lesson again in a new place: ask the
infrastructure, not the agent.

So the allow-list is now PER BACKEND rather than a union: a `claude` VM reaches
Anthropic and the forge, a `glm` VM reaches z.ai and the forge, and neither can
reach the other's endpoint. A union was defensible when it was one host; once the
measurement showed a GLM VM never needs Anthropic, keeping it would mean a
credential mix-up upstream could still put one provider's secret on another
provider's wire. Now it fails at a closed door instead.

An unknown backend gets the forge and NO model API — it cannot run anyway, and
borrowing somebody else's door is the failure this split prevents. An explicit
`CLAWMATES_FC_EGRESS_ALLOW` still wins outright: an operator who set it drew a
boundary on purpose.

`DEFAULT_ALLOW` is deleted rather than left beside the new function, so there is
one answer to "what may a mission reach" and not two.

534 tests pass, clippy clean.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
Omar Sobh
2026-08-06 17:26:32 -07:00
co-authored by Claude Opus 5
parent f7f3dfe495
commit d3a53e7bf1
2 changed files with 78 additions and 24 deletions
+1 -1
View File
@@ -291,7 +291,7 @@ pub async fn create(
// Bound BEFORE firecracker starts: a guest that dials the host before the
// host is listening gets a connection refused it will not retry.
let (egress_uds, egress_task) = match crate::egress::start(&uds, vm_id) {
let (egress_uds, egress_task) = match crate::egress::start(&uds, vm_id, backend) {
Ok((p, t)) => (p, Some(t)),
// Not fatal — a VM is still useful for work that needs no network — but
// it must be visible. `create`'s reply says whether egress exists, and