anonrouter-verify
The command both SDK packages install. It prints one JSON document and exits nonzero unless the assurance you asked for was established, so it can gate a deploy rather than only inform one.
Get it from the GitHub release
anonrouter-verify comes with either SDK package, and neither package is on
npm or PyPI yet. Install the tarball or wheel from
v0.1.0
— see the SDK overview — and the command lands on your PATH.
Installing either SDK package installs anonrouter-verify. It answers one
question from a terminal — did this route establish the assurance I require? —
and answers it with an exit code, so it can gate a deploy or a CI job rather
than only inform one.
Both languages ship the same command. A cross-language parity gate runs both real executables over the same inputs and requires the JSON they print and the codes they exit with to be identical, so it does not matter which one you have.
Three subcommands
# Hop 1 only: is this data plane the reviewed build, in a TDX CVM, bound to a
# fresh nonce and this origin? Credential-free.
anonrouter-verify gateway --origin https://api.anonrouter.ai
# Both hops, cross-bound to a route. Needs an API key for hop 2.
anonrouter-verify route --origin https://api.anonrouter.ai \
--control-origin https://control.anonrouter.ai \
--provider venice --model venice-uncensored
# What can this machine establish at all? Contacts nothing unless --origin is given.
anonrouter-verify doctor --origin https://api.anonrouter.ai`gateway` needs no credential
Hop 1 is credential-free by design: a client should be able to verify the plane before it trusts that endpoint with anything. You can run it against a deployment you have no account on.
Exit codes
| Code | Meaning |
|---|---|
0 | the requested assurance was established |
1 | it was not — including "we could not look" |
2 | the command or its inputs were wrong |
That third code exists so a typo cannot be mistaken for a verification failure,
and the second covers unavailable as well as untrusted: a deployment that does
not expose attestation has not passed anything.
anonrouter-verify gateway --origin https://api.anonrouter.ai --dcap \
--require hardware_verified
echo $? # 0 met, 1 not met, 2 the command itself was wrongGating a deploy
--require sets the minimum state that exits 0. The default is
cryptographically_checked.
#!/usr/bin/env bash
set -euo pipefail
anonrouter-verify gateway \
--origin https://api.anonrouter.ai \
--dcap --require hardware_verified --compact
echo "plane established; proceeding with deploy"With set -e, a plane that stopped matching the reviewed pin stops the deploy.
See the five states for what each level of
--require actually proves.
Reaching hardware_verified
--dcap chains the quote's signature to Intel's roots using the reviewed engine.
It is required to reach hardware_verified; without it the honest ceiling is
cryptographically_checked, and the command refuses --require hardware_verified
rather than quietly returning a weaker result.
anonrouter-verify doctor # is an engine installed? which one? what digest?doctor reports what this machine can establish — the engine, its digest, the
host target, and whether a pin ships for the origin — before you depend on it in
CI.
| Flag | What it is for |
|---|---|
--dcap | chain the quote to Intel's roots with the reviewed engine |
--dcap-binary <path> | use this engine explicitly instead of discovering one |
--dcap-sha256 <hex> | refuse to run an engine whose SHA-256 differs |
--collateral <file> | supply Intel collateral instead of fetching it |
--no-collateral-fetch | refuse to fetch collateral (needs --collateral) |
Pinning the policy yourself
Without --policy, the command holds the plane to the pin the package ships for
that origin. Supply your own to pin a release you reviewed yourself, or to verify
a plane the package ships no pin for.
anonrouter-verify gateway --origin https://your-cvm.example \
--policy ./reviewed-policy.json --dcap --require hardware_verified--allow-candidate accepts a shipped pin whose status is candidate — a
reviewed but pre-release plane whose measurements are expected to move. It is off
by default, so a default invocation can never quietly pass against a plane the
operator has not released.
`v0.1.0`'s shipped pin is older than the running plane
The content plane has been released since v0.1.0 was tagged, so the pin the
package ships names the previous build. Against production today that means
exit 1 on compose_hash_pinned and release_pinned — a stale pin failing
closed, which is the behaviour you want, but not a passing gate. Until a
refreshed pin ships, supply --policy with a policy you reviewed against the
compose_hash and release_id in the live
/v1/gateway/attestation document.
Credentials and output
- The API key for
routeis read only from an environment variable, never fromargv, where it would be visible in the process table. Change which variable with--api-key-env. - The command prints one JSON document on stdout (
--compactfor one line) and diagnostics on stderr, so a caller can branch on the exit code and still read why. - It never prints a key, a ticket, request content, or the raw evidence body. The gateway document alone is tens of kilobytes of internal build detail; the command reports a verdict over it rather than dumping it.
anonrouter-verify gateway --origin https://api.anonrouter.ai --compact \
| jq '{schema, state: .gateway.state, reason: .gateway.reason}'Every document carries a schema field (anonrouter-verify/1), so a consumer can
detect a format change rather than silently misparse one.
Full options
anonrouter-verify --help| Option | Default |
|---|---|
--origin <url> | required for gateway / route |
--control-origin <url> | --origin; production uses https://control.anonrouter.ai |
--require <state> | cryptographically_checked |
--api-key-env <NAME> | ANONROUTER_API_KEY |
--timeout <ms> | 30000 |
--no-tls-check | off — TLS observation is on by default |
--compact | off |
`--control-origin` does not split verification from content
It only moves the content-free, API-key operations to the identity origin. Both
attestation hops and any request content stay on --origin. The SDK deliberately
offers no way to verify one inference origin while sending content to another —
a verdict about a plane that did not carry your prompt proves nothing about the
one that did.