Claros keeps a record of every check. This page is about making that record evidence: complete enough to answer “which rule, as written then, who stood behind it, who approved the exception, did it run”, and hard to change without anyone noticing. Admins download it from Evidence on Home (/app).

What each check row holds

On top of the check log fields: Who an agent acts for. A key minted by a person (in the web app, or by npx getclaros’s device sign-in) is that person’s; a web session and an MCP connector are their user’s. Only a workspace service key (made with python -m claros.auth create, tied to nobody) may name a workspace member in agent.on_behalf_of. An ask from a person’s agent goes to that person first when they may answer it themselves (they own the rule, are one of its owners, or are a workspace admin); otherwise to the rule’s owner, as before. GET /api/me/timeline is one timeline per person: their own checks and their agents’, and Your agents on Home shows what those agents were stopped or nudged on. Amounts are found by key words, not by domain: a key whose words include amount, total, subtotal, price, cost, fee, payment, refund, charge or sum, with a number or a string like $1,200.50 or 900 EUR. A currency comes from a symbol, a three-letter code next to the number, or a currency field.

Outcomes and coverage

After a checked action runs, the guard reports what happened:
  • The MCP guard posts POST /v1/check/{check_id}/outcome (status ok or error, a summary) when the wrapped server answers. A write it let through unchecked (--fail-open while Claros was unreachable) is reported too.
  • Claude Code’s PostToolUse hook (installed by npx getclaros next to PreToolUse) posts the outcome by the tool call’s tool_use_id; the server finds the check its PreToolUse made for the same id.
An outcome is recorded once per check, and only by the key that made the check. Coverage per agent = checked writes ÷ (checked writes + writes the guard saw run unchecked). A write is a call the guard classified as not a read: a non-read MCP tool, or a shell command or file edit in a coding agent. Coverage is reported only for agents whose guard sends outcomes (today: the MCP guard and Claude Code hooks); for the others it is empty, because a write that never reached Claros can’t be counted. Writes from an agent running without the guard or hooks are invisible to it. ran_after_stop counts outcomes reported for a check that said stop.

The tamper-evident log

Checks, approvals, overrides, outcomes and rule versions each get an entry in one hash chain per workspace, written in the same database transaction as the row:
prev_hash of the first entry is 64 zeros; ts is milliseconds. Closing a rule version is its own entry (rule_version_close). The ledger table refuses updates and deletes. Signed checkpoints. Every 100 entries (CLAROS_LEDGER_CHECKPOINT_EVERY) and on demand, Claros signs claros-ledger-checkpoint\n{workspace}\n{seq}\n{hash}\n{ts} with the workspace’s Ed25519 key. The private key is made on first use and kept in the server’s data directory (ledger-keys/, mode 0600); it never leaves the server. Public keys: GET /v1/ledger/pubkey. Checkpoints: GET /v1/ledger/checkpoints. Anchor them outside Claros. A checkpoint only proves something if a copy lives where Claros can’t change it. Save them and publish the file anywhere you control: a git repository, a write-once bucket, your SIEM, an email to your auditor.
getclaros verify downloads the ledger, checkpoints and public keys and re-checks everything on your machine. It exits 1 on: an edited or deleted record, a missing or reordered entry, a broken link, a bad or unknown signature, a tail cut off before a signed checkpoint, or (with --checkpoints) a log rewritten since you saved them. With an audit key (Admin → Evidence → Make an audit key: it reads the log and its records, nothing else, and only while its maker is an admin) it also compares each record’s content; with an agent key it checks the chain and signatures only. On the server: python -m claros.ledger verify [--workspace …], and GET /api/evidence/verify. Evidence export. Admin → Evidence → Evidence export (GET /api/evidence/export) downloads every entry with the record it covers, the signed checkpoints and the public keys, signed as a whole. An auditor checks it offline, every record compared, with no key and no access to Claros:
Retention. Admin → Evidence → Retention, or PUT /api/evidence/retention {"days": 365} (admins). It shows the oldest record kept and, after a prune, the signed checkpoint the chain verifies from. The floor is 183 days, six months, as EU AI Act Art 26(6) asks of deployers; lower values are refused, and no setting keeps everything. Pruning (POST /api/evidence/prune or python -m claros.ledger prune) first signs a checkpoint at the last entry it drops, then deletes the older checks, approvals, overrides and outcomes; the chain still verifies from that checkpoint. Rule versions are never deleted. Nothing prunes on a schedule yet.

Exports

Admins only (a signed-in admin, or an admin key).

SIEM ingestion

No vendor SDK: pipe the JSON lines into each tool’s HTTP intake, remembering the last seq.
  • Splunk (HTTP Event Collector): HEC takes several event objects in one POST. jq -c '{event: ., sourcetype: "claros:ledger"}' batch.jsonl | curl -s https://splunk.example.com:8088/services/collector/event -H "Authorization: Splunk $HEC_TOKEN" --data-binary @-
  • Datadog (Logs intake API v2): a JSON array, up to 1,000 entries per request. jq -s 'map(. + {ddsource: "claros", service: "claros"})' batch.jsonl | curl -s https://http-intake.logs.datadoghq.com/api/v2/logs -H "DD-API-KEY: $DD_API_KEY" -H "Content-Type: application/json" --data-binary @-
  • Elastic (_bulk): an action line before each document; the id makes re-sends idempotent. jq -c '{index: {_index: "claros", _id: "\(.workspace)-\(.seq)"}}, .' batch.jsonl | curl -s https://elastic.example.com:9200/_bulk -H "Authorization: ApiKey $ES_KEY" -H "Content-Type: application/x-ndjson" --data-binary @-
Each line keeps seq, hash and prev_hash, so the copy in your SIEM can be re-checked against the chain.

AIUC-1 evidence pack

Keyed by requirement (AIUC-1, Q4 2026 release). Each control lists what Claros holds, sample records and its gaps. It is evidence for an audit, not a certification.

Oversight quality

Per owner, over the window: A rate is empty when its denominator is zero.

Signed monthly report

Per workflow and calendar month: the rules in force (version, hash, owner, response, confirmer), check counts by result, near-misses, approvals by decision and authority, overrides by verdict, coverage by agent, oversight per owner, the chain’s verify result and a fresh signed checkpoint. The JSON is signed with the workspace’s ledger key (Ed25519 over sha256 of the report as canonical JSON); check it with python -m claros.ledger verify-report report.json. format=html is the same report as a printable page.