Skip to main content
When a session is sealed, the console does two things. It appends a signed record to the workspace’s attestation chain, and, if the agent’s library evaluated at least one event, it issues a signed integrity certificate for the session. Both are signed with Ed25519 by the console’s attestation key, whose public half is published without authentication:

What the signature proves

The console signs what it received and counted. It records the library’s scores and its local chain status as the agent’s own claims, and every certificate labels which is which in its provenance block. So a valid certificate proves that this workspace received a session with these counts and times, that the agent claimed these scores, and that nothing in the document has changed since it was signed. It does not prove that the agent computed its scores honestly. Events the console scored itself are shown in the dashboard but never signed into a certificate.

Certificates

A certificate is issued when a session is sealed, whether by the library’s end request or by the console after the session went idle. Only events the library evaluated count. A session with no such events gets no certificate, and its certificate page says “No certificate issued” with the reason: “server scored only” or “no SDK evaluations”. While a session is still open, the page shows an unsigned preview.

What a certificate contains

The signature covers the whole document, fingerprint_sha256 included.

In the console

Open a certificate from the certificate icon on an ended session in Sessions, the Certificate button on the session page, or a row in Attestations. The page shows each dimension, the configuration stability row, the provenance split, the fingerprint and the signature.
  • Print and Download PDF both open the browser’s print dialog; choose Save as PDF.
  • Verify offline downloads certificate-<id>.json with the signed payload, the signature, the key id and the public key URL, for verification outside the console. Read the number-formatting warning under Verify a certificate before relying on it.

Verify a certificate

Verification needs the signed payload, the hex signature and the public key. The procedure:
  1. Fetch the public key and pick the entry whose key_id matches the certificate’s key_id. After a key rotation, older keys are listed under retired.
  2. Remove fingerprint_sha256 from the payload, serialize the rest canonically, and take the SHA-256. It must equal fingerprint_sha256.
  3. Serialize the full payload canonically and verify the Ed25519 signature over those bytes.
Canonical means Python’s json.dumps(payload, sort_keys=True, separators=(",", ":")): sorted keys, no whitespace, and non-ASCII characters escaped as \uXXXX, encoded as UTF-8.
Number formatting is part of the signed bytes. Python writes the float 1.0 as 1.0; JavaScript’s JSON.stringify writes it as 1. A payload that has been parsed and re-serialized by JavaScript, or a verifier written in another language that formats numbers differently, will fail even though the certificate is genuine. Verify with Python, from the JSON exactly as the console served it.The Verify offline file is written by the browser, so it has this problem: a certificate with a whole-number value, such as a pass rate of 1.0, does not verify from that file.
verify_certificate.py
Run it on a downloaded certificate with python verify_certificate.py certificate-<id>.json (it needs pip install cryptography).

The attestation chain

Each workspace has one chain. Every sealed session appends one record, whether or not it got a certificate. A record holds the session id, agent id, adapter, the server’s event and evaluation counts, the library’s attestation record count and chain status (null when the library did not report it), enforce mode, the end time, sealed_by: "server" when the console sealed it, the key id, and prev_hash. Its record_hash is the SHA-256 of the previous record’s hash followed by the canonical record, and the signature covers the record including record_hash. Changing, removing or reordering a record breaks every link after it.

Attestations screen

Attestations, under Assure, is the ledger: one hash-linked, signed row per sealed session, newest first, up to 100 rows. Filter it to broken chains or enforce mode. Each row opens its certificate. The numbers at the top are records, chain integrity, certificates issued in the last 24 hours, the console’s own verification and the signing key (with how many retired keys are still trusted). Note that Chain integrity, and the per-day grid beside it, show what each library reported about its own local chain. That is the agent’s claim. The console’s own check is Verify chain.

Verify the chain

Verify chain walks the whole workspace chain on the server. It recomputes every record_hash, checks every link and checks every signature, and reports how many records it checked, how many signatures it verified, how long it took, the head hash and the first break, if any. Any member can run it. The problems it can report are first_record_has_predecessor, chain_link_mismatch, record_hash_mismatch, bad_signature, no_payload, stored_hash_differs_from_payload and stored_prev_hash_differs_from_payload. Any of them means a record was changed or removed outside the console. Attestation records are not available outside the console, so the chain can only be verified there. Certificates can be verified anywhere. Attestation records and certificates are never deleted by retention.