What you can check yourself, and what we still owe you.
No live counters, no endpoint you have to trust us to keep up. Everything below either verifies offline against a published key, or is named as open with no date attached to it.
01Keys
- Keys in the published JWKS
-
tanilo-2026-10-ed25519-7d885da9— current. Tanilo's signing key, in use since 2026-10-02. Its receipt-signing paths are/evaluateand/v1/verify-facts, both of which run the check themselves; it has no path that signs a verdict supplied by the caller. Those receipts name issuertanilo.ioand this page's key set. It also signs the separately identified key-continuity statement. Its JWKS entry declaresrole: evaluated, and every receipt it signs carriesrole: evaluatedin the protected header.ao-composed-2026-06-ed25519-c3abfce3— retired 2026-10-02, when Tanilo's key went live. It signed/evaluateand/v1/verify-factsreceipts onagentoracle.co, both of which run the check themselves; neither signs a verdict supplied by the caller. It stays published so existing signatures under it can still be checked; rotation alone does not invalidate them, and receipt validity, freshness and relying-party acceptance remain separate checks. From 23 June to 28 August 2026 it also signed bytes supplied by the caller through/v1/signand/v1/sign/batch, and stub verdicts through that host's/v1/composeand/v1/v_gate. Since 28 August the sign routes refuse to sign and the stub routes don't issue. A forged payload could carry any timestamp, so no signature under this key shows on its own that the service issued the payload. It carries norole: it signed both kinds of bytes, so neither role value is true of every signature under it, and under the issuance-path role rule, signatures under it resolve to roleunknown. That is separate from signature validity, and a relying party that requires an established issuance path treatsunknownas its own fail.ao-composed-2026-07-ed25519-3d44ba27— retired; withdrawn 24 September 2026, when its private key was deleted. Its only signing path was the API gateway's/v1/compose(27 July to 24 September), which signed verdicts the caller supplied and whose handler returns 410 since 28 September 2026 (unauthenticated requests are refused with 401 before reaching it). Its signatures prove the bytes are unchanged, not that anything was evaluated. Its JWKS entry declaresrole: bytes_attested.ao-receipt-2026-04-ed25519-f2753b7c— legacy. Published 29 April 2026 for the v0.1 receipt format. It signed the attached sample receipt in the spec repo. We found no signing path for it in the current service code. We haven't established where its private key is held or whether it still exists, so we say so here instead of guessing. Norole: its full signing history is not established.ao-fixture-detached-rfc7797-2026-07-ed25519-0f8bf2a5— test fixture only. Its private key is published in the spec repo (examples/jwks-fixture-detached.json) so the fixture can be reproduced. Anyone can sign with it, so a signature from it proves nothing about issuance. Norole. - Algorithm
- Ed25519 (RFC 8032), canonicalized per RFC 8785 (JCS) before signing
- Published keys
- tanilo.io/.well-known/jwks.json — the same key set is served at api.tanilo.io/.well-known/jwks.json and agentoracle.co/.well-known/jwks.json. Each key carries a
tanilo_statusmember (current, retired, legacy or fixture),tanilo_retired_atwhere it applies, and, where the key's history supports it, arolemember (evaluatedorbytes_attested) declaring what signatures under that key attest. - Key continuity
- tanilo.io/.well-known/key-continuity.json — a statement listing every key above with its status, signed on 2026-10-02 by both the retiring key
ao-composed-2026-06-ed25519-c3abfce3andtanilo-2026-10-ed25519-7d885da9. It ties the older kids to this publisher, so the signature on a receipt issued under a retired key can still be checked with key material from tanilo.io. It does not establish that any older payload was evaluated. - Rotation policy
- New signing key at least every 12 months, or immediately if a private key may have been exposed. Retired keys stay published in the JWKS so existing signatures under them can still be checked; rotation alone does not invalidate them, and receipt validity, freshness and relying-party acceptance remain separate checks.
Tanilo signs with tanilo-2026-10-ed25519-7d885da9 since 2026-10-02, a new key with no signing history before Tanilo; ao-composed-2026-06-ed25519-c3abfce3 is not used for new issuance. Retired and legacy keys stay published so existing signatures under them can still be checked; rotation alone does not invalidate them, and receipt validity, freshness and relying-party acceptance remain separate checks. Receipts issued before 2026-10-02 are not re-signed: they are exactly as issued. Full account of both signing paths: /incidents/2026-08-25-canned-verdicts ↗.
02Second implementation
A byte-identical second implementation, built by a different party from the published text. AgentTrust implemented the verification envelope from the specification; the fixtures and vectors that prove it landed in argentum-core/examples/conformance/agenttrust-v1 (PR #33, merged 2026-07-16).
03Verify a receipt yourself
Same commands as the homepage. Nothing here requires calling Tanilo — only the published key.
This is the same receipt as the homepage, issued by /evaluate on 2026-09-30. Until 2026-09-30 this section showed a receipt signed through the gateway route withdrawn on 24 September 2026, over a verdict the caller supplied; see the incident record.
Node and browser verifiers use the same JCS + Ed25519 semantics and produce the same canonical hash byte-for-byte. Full registry entry: /receipt-registry.
04What's still open
Issuance-path assertion
A receipt doesn't say which route produced it. Before 2026-10-02, c3abfce3 remained the receipt-signing key after its caller-supplied signing paths closed on 28 August; at cutover it stops new receipt issuance; 3d44ba27 signed only caller-supplied verdicts and was withdrawn on 24 September 2026. A receipt shows its key ID, but not what that key was used for; that mapping is stated here, not in the receipt. The fix is a role parameter in the JWS protected header, checked against a role member on the signing key in the published JWKS. The role-in-header design is Pote's (poteshniy, AgentTrust); it is not yet normative text in the filed -02 draft. Update 2026-10-02: the issuer side is live. The Tanilo key's JWKS entry declares role: evaluated and every receipt it signs carries role: evaluated in the protected header; 3d44ba27 is declared bytes_attested; c3abfce3 carries no role, so under the issuance-path role rule, signatures under it resolve to role unknown. That is separate from signature validity, and a relying party that requires an established issuance path treats unknown as its own fail. The values are evaluated and bytes_attested, as agreed with Pote on 2 September 2026. Under the proposed issuance-path role rule, absence of a role gives an issuance-path resolution of unknown; it does not by itself make the receipt malformed. Existing signed bytes are unchanged, and signature validity, freshness and relying-party acceptance remain separate. Issuer-side annotation is live; verifier-side role resolution (role_resolution in tanilo-receipt-verify) and the draft format text remain unshipped, with no date, so this item stays open until both ship.
Kid separation
Giving evaluation receipts and sign-only receipts distinct key identifiers was the first fix proposed for the same-kid conflation above. It's still worth doing operationally, but the issuance-path assertion is the durable fix — it survives key rotation and doesn't require a verifier to keep a mapping table current.
instrument_failure emission
The -02 IETF draft defines instrument_failure so a non-evaluation can be signed and recorded instead of producing no receipt at all. The running service hasn't been updated to emit it yet.
05Filed specification
The receipt format is filed as an IETF Internet-Draft: draft-krausz-verification-state (current revision -02). It defines the on-wire semantics — act/halt verdict, canonicalization, signer binding, and the reason-code vocabulary referenced above.