The ProofPack format, version 1.
Every change Farbaek applies, and every check run of it, leaves a ProofPack: a record of what was approved, what changed and what the checks returned. This is how one is built, so anyone can read and check it without Farbaek.
https://farbaek.com/proofpack/v1
The statement, its digest and its signature
- Statement
- https://in-toto.io/Statement/v1An in-toto Statement v1. Its subjects are the files the change wrote, each by path and the SHA-256 of its exact content.
- Predicate type
- https://farbaek.com/proofpack/v1ProofPacks recorded before 24 October 2026 carry https://farbaek.dev/proofpack/v1, with the same fields.
- Digest
- sha256(canonical JSON)The SHA-256, in hex, of the whole statement written as RFC 8785 canonical JSON. Change one character and it no longer matches.
- Signature
- application/vnd.in-toto+jsonA DSSE envelope. Its payload is the same canonical JSON, so the payload's SHA-256 is the digest. The signature is Ed25519 over DSSE's pre-authentication encoding of the payload.
- Keys
- /.well-known/farbaek-keys.jsonFarbaek's public keys. A key id is farbaek- and the first 16 hex characters of the SHA-256 of the raw 32-byte public key.
What the predicate records
The fields inside the statement's predicate.
- schema
- Always farbaek.proofpack/v1.
- status
- verified, partially_verified, unverified or failed, from real exit codes only. A change with no checks run is unverified, never verified.
- task
- The ids of the task, its workspace and its project.
- contract
- The version and SHA-256 of the intent contract that was approved.
- proposal
- The change proposal's id and SHA-256, and the model that drafted it, or null.
- policy
- The policy decision, the policy's version and its findings, or null when none was recorded.
- approval
- Who approved, when, and the SHA-256 of what was applied. by: "policy" with autonomyLevel: 2 or 3 means the workspace's policy approved it, at that level of autonomy.
- changes
- Each file written: its path, create or edit, the revision it was based on, and the SHA-256 of its content.
- checks
- Each required check: its name, command, exit code (null when it didn't run) and passed, failed or not_run.
- execution
- sandboxed, with the sandbox provider, or review_only, with the reason checks didn't run.
- limits
- What the record doesn't prove, in plain sentences.
- createdAt
- When it was recorded, in ISO 8601 UTC.
- previous
- The digest of the project's previous ProofPack, so a project's ProofPacks form a chain. null for the first.
- verification
- Only on a ProofPack a check run recorded: the run's receipt digest, the ProofPack of the change it checked, and filesMatched: true, meaning the sandbox held exactly the applied content.
Check one without Farbaek
With a signed ProofPack downloaded from Farbaek as proofpack.json, these steps need a shell, curl, jq and OpenSSL 3. The verify page does the same in your browser.
1Take out what Farbaek signed, and hash it
Shelljq -r .dsse.payload proofpack.json | base64 -d > payload.json sha256sum payload.jsonThe hash equals the file's digest. payload.json is exactly the statement Farbaek signed, so read that one rather than the copy beside it.
2Rebuild the bytes the signature covers
Shelltype=application/vnd.in-toto+json printf 'DSSEv1 %d %s %d ' ${#type} "$type" $(wc -c < payload.json) \ > signed.bin cat payload.json >> signed.binThis is DSSE's pre-authentication encoding: the payload type and the payload, each after its length in bytes.
3Fetch Farbaek's key for that signature
Shellid=$(jq -r '.dsse.signatures[0].keyid' proofpack.json) curl -s https://www.farbaek.com/.well-known/farbaek-keys.json \ | jq -r --arg id "$id" '.keys[] | select(.keyid == $id) | .publicKey' \ | base64 -d > farbaek.key prefix='\060\052\060\005\006\003\053\145\160\003\041\000' { printf "$prefix"; cat farbaek.key; } > farbaek.derThe printf adds the standard prefix that turns a raw Ed25519 key into a key file OpenSSL reads. No key found means Farbaek doesn't publish the key that signed it.
4Check the signature
Shelljq -r '.dsse.signatures[0].sig' proofpack.json | base64 -d > sig.bin openssl pkeyutl -verify -pubin -inkey farbaek.der -keyform DER \ -rawin -in signed.bin -sigfile sig.binOpenSSL prints "Signature Verified Successfully". If any byte changed, it prints "Signature Verification Failure".
What a ProofPack proves
Nothing changed
A matching digest shows the record is exactly as it was made.
Farbaek recorded it
A valid signature shows Farbaek's server recorded it. ProofPacks recorded before signing started have none.
Not that the software is right
A ProofPack says which checks ran and what they returned. It doesn't show that other claims inside are true, or that the software has no other faults.