code-change predicate, v0.1
You have probably arrived here from the predicateType of a receipt someone asked you to trust. This page says what that document claims, and — more importantly — what it does not.
"predicateType": "https://provene.dev/attestation/code-change/v0.1"
The receipt is an in-toto Statement v1. Unsigned receipts (T0) are the bare Statement; signed ones are wrapped in a DSSE envelope. The normative document is RFC 0001; the machine-readable form is the JSON Schema.
Read this part first
A receipt does not assert that an agent authored a change, that the code is correct, secure or well-designed, or that unattributed regions of a diff were written by a human.
Absence of attribution means unobserved, never human. This is normative: an implementation that presents it otherwise is non-conforming.
Someone can write code by hand and record it as an agent's, or the reverse. No receipt format can distinguish typing from generating, and this one does not claim to. What it does record is what an observer saw, and who that observer was.
What it records
| Field | Claim |
|---|---|
attestation.tier | Who observed this, and therefore what it is worth. T0–T3, below. |
agent | The tool, vendor, version and model — as reported by the tool itself. modelSource says whether the runtime reported it or a config named it. An emitter that cannot tell records no model at all rather than guessing. |
binding | A SHA-256 over the git blob ids of the changed set, sorted by UTF-8 bytes, excluding .provene/**. This is what ties the receipt to specific content rather than to a commit message. |
changes.files | The changeset — every path that differs between two states of the tree, including work the developer did themselves. A verifier must be able to recompute the subject digest from this list alone. |
changes.files[].attributedTo | Optional, and a separate and weaker claim: the emitter observed this session touch this path. Absent means unobserved. |
commands | Command name, a shape if the whole command line matched a fixed allowlist, and an HMAC of the real argument vector keyed to the repository. Never the raw arguments. |
verification.runs | Test runs and their results, each carrying observedBy: local or ci. Only ci is independent. |
verification.unverifiedPaths | Changed paths no run in this receipt covers. Verification coverage over the whole changeset — this carries no attribution claim and must not be filtered by one. |
Tiers, and what each is worth
| Tier | Observed by | Worth |
|---|---|---|
T0 | the developer's machine, unsigned | local visibility; satisfies no policy |
T1 | the developer's machine, their identity | attribution among people who already trust each other. Specified; no emitter produces it |
T2 | CI, on a runner the developer does not control | verification evidence, independently observed |
T3 | the execution environment or the agent vendor | authorship. Reserved; nothing produces it yet |
If you are deciding whether to trust a receipt, this table is the decision. A T0 receipt showing a passing test suite is a statement by the person who wants the change merged. A T2 aggregate signed by a CI workload identity is a statement by a runner they did not control — that is the one that closes forged test evidence.
Privacy
Receipts carry a keyed digest of the task, never its text; a command's name and an HMAC of its arguments, never the raw vector; and no stdout, no environment variable values, and no file contents. The redaction contract is an allowlist, because argument vectors carry credentials routinely and a denylist in a trust product fails silently and permanently.
The HMAC is keyed from the repository's root commit, which anyone with the repository can read. It makes two receipts comparable without either revealing a command to a stranger holding only the receipt. It is not encryption, and short command lines are guessable.
Verifying one
npm install -g proveneio
provene verify path/to/<digest>.statement.json
provene verify-aggregate --repo owner/name --base <commit> # checks the signature
verify checks integrity and reports the tier. Signature verification is delegated to gh attestation verify, and its exit code is the trust boundary — not any parsing done by this tool.