Audit
Contamination certificates
One signed file about one run: the harness receipt, the control-arm deltas, the positive-control result and the reasoning-audit findings. Whoever holds it recomputes every hash in it on their own machine, with the Go toolchain and nothing else.
BUILDING
The verifier and the format are done and committed.
pit_harness.certify assembles and signs,
cmd/certverify verifies, and the two share a golden
certificate byte for byte. Priced flat per run, with the audit
included, once the harness ships.
- CLI
- ed25519
- canonical JSON
- Go stdlib only
The artifact
The verifier, run against the committed golden certificate
This is the whole report, from cmd/certverify against
the 23,347-byte certificate committed in this repository, on
2026-08-27. The golden is unsigned, because signing it would mean
committing the key that signed it, so the signature check reports
skipped and the verdict is
verified_partial.
$ go build -o certverify ./cmd/certverify $ ./certverify verify -cert certificate.json \ -trajectory trajectory.jsonl -manifest MANIFEST.json
{
"tool": "certverify",
"certificate": {
"path": "cmd/certverify/testdata/certificate.json",
"certificate_version": 1,
"certificate_id": "3b32f95fecb55b4a",
"run_id": "53adff537d13f755",
"issued_at": "2026-08-27T00:00:00Z",
"issuer": "AQX LLC"
},
"verdict": "verified_partial",
"exit_code": 0,
"failed": [],
"skipped": [
"signature"
],
"checks": [
{
"check": "body_digest",
"status": "pass",
"expected": "sha256:0bd013bea7dd553a04aa124e48fe839fbd66f150955c263177046f28e10f75b8",
"actual": "sha256:0bd013bea7dd553a04aa124e48fe839fbd66f150955c263177046f28e10f75b8",
"form": "as-stored",
"proves": "the body has not changed since body_sha256 was written over it"
},
{
"check": "receipt_body",
"status": "pass",
"expected": "sha256:bf25b8aaa3aa5ef577ea9fb794f4fe519c9c1cceee8dc9dff79278caf7b87dd9",
"actual": "sha256:bf25b8aaa3aa5ef577ea9fb794f4fe519c9c1cceee8dc9dff79278caf7b87dd9",
"form": "as-stored",
"proves": "the embedded run receipt is the receipt the harness hashed, unedited"
},
{
"check": "signature",
"status": "skipped",
"reason": "the certificate is unsigned",
"proves": "the certificate was signed by the key it names, and has not changed since"
},
{
"check": "trajectory",
"status": "pass",
"expected": "sha256:d6d6c3e2449cc88e516484b504b582e3d3ab5227ce730ce04ca2c49271369940",
"actual": "sha256:d6d6c3e2449cc88e516484b504b582e3d3ab5227ce730ce04ca2c49271369940",
"file": "cmd/certverify/testdata/trajectory.jsonl",
"proves": "the trajectory you hold is the one the run recorded, tool call for tool call"
},
{
"check": "bundle_manifest",
"status": "pass",
"expected": "sha256:68993e15bfc367571579ffb3b664a4faf4f86d10c39c27bbdfe382b9fbef5a24",
"actual": "sha256:68993e15bfc367571579ffb3b664a4faf4f86d10c39c27bbdfe382b9fbef5a24",
"file": "cmd/certverify/testdata/MANIFEST.json",
"proves": "the run read the corpus release this manifest describes, byte for byte"
}
],
"run": {
"valid": true,
"invalidated_by": [],
"protocol_complete": true,
"protocol_gaps": []
},
"reasoning_audit": {
"status": "reserved",
"verdict": "not_run"
},
"cannot_prove": [
"that the agent reasoned from the rows rather than from memory: the control arms and the reasoning audit bound that, not the signature",
"that the corpus release is a fair test of the task the agent was given",
"that the key you verified against belongs to who you think it does; that is the key file's provenance, not this program's"
]
}
Build it rather than go run it: go run
reports its own exit 1 for any nonzero child and throws away the
class codes below. Every check carries a proves line,
and the report ends with cannot_prove.
The failure it prevents
A benchmark result nobody outside the team can check
A number in a table is a claim about a run that already finished on a machine you cannot see. Publishing the code lets a reader start their own run, which is a different run from the one the number came out of. A certificate binds the number to the run that produced it, and hands over the hashes to check that binding.
| Check | Passes when | Which means |
|---|---|---|
body_digest | sha256 over the stored body equals body_sha256 | the body has not changed since the digest was written over it |
receipt_body | sha256 over the embedded receipt equals binding.receipt_body_sha256 | the receipt inside is the one the harness hashed, unedited |
signature | ed25519 verifies over the context line and the body | the file came from the key it names |
trajectory | your trajectory's sha256 equals binding.trajectory_sha256 | the trajectory you hold is the one the run recorded, tool call for tool call |
bundle_manifest | the manifest's content_digest equals binding.bundle_content_digest | the run read the corpus release that manifest describes |
-cert and -pubkey are the two files a
reader needs. -trajectory and -manifest
check the certificate against artifacts you already hold; leave one
out and its check reports skipped.
-require-all turns a skip into exit 8.
How it works
Canonical bytes, one signature, a stated boundary
The numbers are restated from the receipt
The certificate embeds the run receipt whole and promotes the parts
a reader acts on to the top level: arm_deltas carries
every arm-by-clock return and the largest measured delta,
positive_control carries the date-recoverability probe
per arm, and reasoning_audit carries the claim-level
check. None of it is computed at certificate time. A test checks
the restatement agrees with the receipt cell for cell, so a
certificate cannot report a number the receipt does not carry.
Two certificates from one receipt are the same bytes
The file is compact canonical JSON on one line. Keys sort at every
level, floats fix at six decimals, -0.0 is written
0.0, and everything outside ASCII is escaped. The
bytes stored for body are exactly the bytes
body_sha256 covers, so a verifier hashes what it read
instead of reproducing our serialiser.
issued_at is the only wall-clock field and it sits
outside the hash.
The signature is domain-separated
The signed bytes are pit-certificate-v1\n followed by
the canonical body, so a signature over a certificate body cannot
be presented as a signature over anything else PIT signs. The
certificate carries a copy of the public key for convenience, and
certverify checks against the key file you hand it and
never against that copy. When the two disagree it fails the
signature check, which usually means you hold the wrong key file.
Exit codes say which class of thing went wrong
| Code | Class |
|---|---|
| 0 | every check that ran passed |
| 1 | usage: bad flags, or a file that would not open |
| 2 | the certificate will not parse, or is not version 1 |
| 3 | a hash over bytes inside the certificate does not match |
| 4 | the signature does not verify, or the key is unusable |
| 5 | the trajectory file is not the one the run recorded |
| 6 | the release manifest is not the one the run read |
| 7 | every check passed and the run itself is marked invalid |
| 8 | -require-all was set and a check had no file to run against |
Code 7 means the certificate is genuine and the run it certifies
was thrown out by the harness, usually because something attempted
network egress while the guard was armed.
run.invalidated_by says which.
Integration
Build one, sign it, hand it to somebody
$ python -m pit_harness.certify keygen \ --private ~/.pit/signing.pem --public pit-certificates.pub --key-id pit-cert-2026a $ python -m pit_harness.certify build --receipt receipt.json --audit findings.json \ --out certificate.json $ PIT_SIGNING_KEY=~/.pit/signing.pem python -m pit_harness.certify sign \ --cert certificate.json --pubkey pit-certificates.pub
The private key is read from the path in
PIT_SIGNING_KEY, and there is no default location to
fall back to. Signing refuses a key file that group or other can
read, and refuses an encrypted PEM rather than prompting. Verifying
in Go needs nothing but the toolchain; in Python it uses the same
library when installed and reports the signature check as
unchecked when it is not, so a report never says a
signature passed when nothing checked it.
What a signature cannot establish
A signature shows the file came from the key it names and that its body has not changed, and the hashes show you hold the same trajectory and the same corpus release the run was scored on. Those are claims about bytes, and whether the run was a fair test is a different question. The report repeats these three limits on every run:
-
The agent may have reasoned from memory. That is what
arm_deltas,positive_controlandreasoning_auditmeasure. If the run leaked, you read it there rather than in the signature check. - Whether the corpus release is a good test of the task is not scored anywhere in the certificate.
-
Whether the key you verified against belongs to PIT depends on
where you got the key file.
certverifychecks the signature; it cannot check where a file came from.
Related
What sits either side of it
Downstream
Certified Leaderboard
Where a certificate goes when you want it counted beside other people's.