anthropics/axt-verify
Go
Captured source
source ↗anthropics/axt-verify
Language: Go
License: Apache-2.0
Stars: 0
Forks: 0
Open issues: 2
Created: 2026-08-31T22:22:46Z
Pushed: 2026-08-31T22:28:12Z
Default branch: main
Fork: no
Archived: no
README:
axt-verify
axt-verify lets an organization enrolled in Anthropic Access Transparency check, on its own machines and without trusting Anthropic's serving path, that:
1. the transparency log Anthropic serves for the organization is signed by the key this release carries and has only ever been appended to; and 2. every Access Transparency event the Compliance API serves — each record of Anthropic personnel accessing or preserving the organization's data — is committed in that log, byte for byte.
If Anthropic (or anyone in between) rewrote or back-dated an event it serves, re-served one it had already shown you with different content or at a different position in the log — for as long as the feed keeps listing that event, plus the overlap window — or served the organization a rolled-back or forked history, a run fails. What the tool cannot do is prove the feed showed you every leaf your log holds: it checks what you are served against what the log committed, so an event simply left out of the feed is not something an inclusion proof can speak for.
The log format is the open C2SP tlog-tiles standard; this tool adds the Access Transparency specifics — the event canonicalization and the Compliance API transport — on top of the standard golang.org/x/mod/sumdb/note and github.com/transparency-dev/{formats,merkle} libraries. See *How verification works* below and the Transparency Log section of the Compliance API reference.
> Maintenance status: actively maintained. We triage issues and review pull requests; see CONTRIBUTING.md.
Install
Requires Go 1.26 or newer.
go install github.com/anthropics/axt-verify/cmd/axt-verify@latest
or build from a checkout with go build ./cmd/axt-verify. The binary has no runtime dependencies.
Setup
Two inputs, both supplied on the command line or in the environment:
| Input | What it is | |---|---| | ANTHROPIC_COMPLIANCE_ACCESS_KEY | A Compliance Access Key with the read:compliance_activities scope — the same key you use for the Compliance API Activity Feed (see "Set up the Compliance API" in the Claude docs). Read from the environment only, never from a file or a flag. | | --org | Your organization's UUID — the value the Activity Feed serves as organization_uuid (not the org_… tagged id). |
export ANTHROPIC_COMPLIANCE_ACCESS_KEY=… axt-verify --org 25f6429a-3293-49bf-afed-cb312911554b checkpoint
The log's public key ships inside this release, so nothing is fetched and nothing is read from disk to decide what to trust. (The tool does write: run and checkpoint keep their progress in a state file, and --save writes a checkpoint archive — see --state below.)
The table below is the key this release carries, and it doubles as the published record to check a build against. Your log's origin is axt.anthropic.com/, and every checkpoint must carry exactly that line:
| Origin prefix | SHA-256 of the public key | |---|---| | axt.anthropic.com | 1dff5fe420d49743fe444a04fc17f818eea856699dec2ebbc24df15602c74a58 |
Overrides
| Flag | Meaning | |---|---| | --log-key | Trust this note-verifier key instead of the one built into this release — for an announced key rotation before you can upgrade. The key's own name is the origin every checkpoint must then carry, and it has to end in /, so the key and the log it verifies cannot disagree. Also read from $AXT_VERIFY_LOG_KEY; the flag wins. | | --state | Where to keep the state file. Defaults to axt-verify.state in the current directory — pass an explicit path from cron. |
Keys rotate by release. A checkpoint that does not verify under the shipped key is a hard failure, never an occasion to go and fetch a different key: if Anthropic announces a rotation, upgrade axt-verify, or pass the new key with --log-key until you can. Such a failure prints the key hashes the served checkpoint claims, alongside the hash of the key this run trusts. The signatures did not verify, so those are claims rather than proof: a claimed hash that is not in Anthropic's published key table is a security finding, and one that is in the table points at a rotation you have not upgraded to — upgrade, or pass --log-key, and run again. If it still fails, treat it as a security finding, because anyone who can serve you a checkpoint that does not verify can also put a published key's hash on it.
Only the newest key is needed. A checkpoint commits to the whole history, so once one checkpoint signed by the new key verifies, and a consistency proof from the checkpoint you last saved leads to it, that proof re-establishes every entry before the rotation as well — the old key is not needed to verify what it once signed. The one exception is an archived checkpoint you hold that the old key signed: --from verifies its signature and would refuse it under the new key, so pass such a file with --from-trusted, which takes its tree size and root hash as your own record without checking the signature. The origin is still enforced.
Commands
| Command | What it does | |---|---| | run | The one to put in cron: verify the latest checkpoint, prove the log only appended since your last run, then page through your Access Transparency events and prove each is committed in the log. | | checkpoint | Verify the latest checkpoint and the append-only property, without reading the event feed. Cheap enough for a tighter schedule than the full run; give it its own --state file. | | events FILE | Verify events you already hold, read from a file or - for stdin — a JSON object, an array, a {"data":[…]} page, or one JSON object per line. Proves each against the log without touching the feed. Rows that are not Access Transparency records — other activity types in the same page or export — are ignored and counted, not failed. Each object is otherwise verified as given: unlike run, this does not collapse two copies of one event id, so a page captured while the log was first stamping indexes can list the same id twice — once as *not logged* and once verified. | | version | Print the version. Needs no credential and makes no request. |
--from, --from-trusted, --prev-size/--prev-hash and --save work with run...
Excerpt shown — open the source for the full document.