A client tool is three moves: read the connection from the
environment, make one HTTP call carrying the bearer and the contract
header, and print either the answer as one JSON line or the one error
shape — then exit with the code that says which happened. Common is
those three moves, so no client reimplements them and all clients
fail identically: `Config::from_env` (`RHEMA_URL`, `RHEMA_TOKEN`),
the `Client` call with the contract envelope, `print`/`fail` and
the `ToolError` exit codes.
The HTTP client is `ureq`, blocking, no TLS: the contract speaks to
a loopback or otherwise trusted daemon, and a remote TLS endpoint is
a stated non-goal in v1 — a thin client stays thin.
The client tools need one shared definition of what a tool may do,
and the daemon needs to enforce exactly that definition, not a
hand-copied copy of it. This crate is that definition, pure: no HTTP
client, no process — the allowlist as data, the version header as
constants, the request/response and error types, and the conformance
suite that drives any transport through the checks the contract
promises (the bearer gate, the version handshake, the allowlist's
denials, round-trips through every allowed route, one error shape).
`agent_allowed` is the whole security surface in one function:
method and path segments with `*` and `**`, exact otherwise — a
daemon's middleware asks it and nothing else, so the claw's scoping
and the tools' expectations cannot drift apart. The suite runs
against a mock router in this crate's tests and against the daemon's
real axum router in the claw's; same results is the definition of
implementing the contract.