Provene Writing Predicate Source npm

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

FieldClaim
attestation.tierWho observed this, and therefore what it is worth. T0T3, below.
agentThe 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.
bindingA 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.filesThe 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[].attributedToOptional, and a separate and weaker claim: the emitter observed this session touch this path. Absent means unobserved.
commandsCommand 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.runsTest runs and their results, each carrying observedBy: local or ci. Only ci is independent.
verification.unverifiedPathsChanged 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

TierObserved byWorth
T0the developer's machine, unsignedlocal visibility; satisfies no policy
T1the developer's machine, their identityattribution among people who already trust each other. Specified; no emitter produces it
T2CI, on a runner the developer does not controlverification evidence, independently observed
T3the execution environment or the agent vendorauthorship. 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.