/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(statusokorerror, a summary) when the wrapped server answers. A write it let through unchecked (--fail-openwhile Claros was unreachable) is reported too. - Claude Code’s
PostToolUsehook (installed bynpx getclarosnext toPreToolUse) posts the outcome by the tool call’stool_use_id; the server finds the check itsPreToolUsemade for the same id.
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:
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 anadmin key).
SIEM ingestion
No vendor SDK: pipe the JSON lines into each tool’s HTTP intake, remembering the lastseq.
- 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 @-
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 withpython -m claros.ledger verify-report report.json. format=html is the same report as a printable page.