Predicate type URI: https://open-fab.ai/attestation/generation/v0.1
By in-toto convention a predicateType is a URI pointing to the predicate's definition. This page is that definition.
The generation predicate records how a software artifact was generated by an AI/agent pipeline — the piece existing provenance (SLSA build provenance, commit signing) does not capture: human-vs-AI authorship, the model, the prompt fingerprint, the acceptance contract, and the human sign-offs — cryptographically bound to the artifact's file digests. It is an AI Bill of Materials (AI-BOM).
The predicate is carried inside an in-toto Statement v1, wrapped in a DSSE-style signed envelope:
{
"payload_type": "application/vnd.in-toto+json",
"payload_sha256": "<sha256 of the canonical statement — the bytes the signatures cover>",
"statement": {
"_type": "https://in-toto.io/Statement/v1",
"subject": [{ "name": "<artifact>", "digest": { "sha256": "<hex>" } }],
"predicateType": "https://open-fab.ai/attestation/generation/v0.1",
"predicate": { /* the generation predicate, below */ }
},
"signatures": [
{ "keyid": "did:key:z6Mk…", "sig": "<base64 ed25519>", "algo": "ed25519", "role": "fab" },
{ "keyid": "did:key:z6Mk…", "sig": "<base64>", "algo": "ed25519", "role": "human-signoff" }
]
}
| Field | Type | Meaning |
|---|---|---|
spec_ref | string | the spec id + version this artifact fulfils, e.g. my-app#v2 |
builder | {id, base} | the OpenFab build identity + base name |
agent | {did, base, model} | the agent identity (did:key), base, and model that generated the code |
prompt_sha256 | hex | sha256 fingerprint of the generation prompt (the prompt text is deliberately not included) |
params | object | generation parameters (base, model, …) |
generated | [{path, lines, sha256, author}] | per-file / per-range human-vs-AI attribution (author ∈ "ai" | "human") + content digest |
materials | [{uri, sha256?}] | context/material inputs that fed generation |
acceptance_passed | bool | did the machine acceptance contract pass |
acceptance | [{id, check, must_pass, passed}] | the frozen acceptance contract — the exact shell checks, embedded so anyone can re-run them from a bare clone (forge-agnostic verify) |
timestamp | RFC3339 | when the attestation was produced |
signoffs | [{did, name, timestamp}] | recorded human sign-offs (N-of-M gate) |
{
"spec_ref": "fee-round#v1",
"builder": { "id": "openfab/0.1", "base": "codex-cli" },
"agent": { "did": "did:key:z6MkuX…", "base": "codex-cli", "model": "gpt-5.5" },
"prompt_sha256": "ab39…c1",
"generated": [
{ "path": "app/fee_round.py", "lines": "12-47", "sha256": "…", "author": "ai" },
{ "path": "app/fee_round.py", "lines": "1-11", "sha256": "…", "author": "human" }
],
"acceptance_passed": true,
"acceptance": [
{ "id": "a1-cap", "check": "python3 -c '...; assert round_half_even(2.5)==2'", "must_pass": true, "passed": true }
],
"timestamp": "2026-06-30T12:00:00Z",
"signoffs": [ { "did": "did:key:z6Mkja…", "name": "alice", "timestamp": "2026-06-30T12:05:00Z" } ]
}
sha256. The AI-BOM is a manifest, not a transcript: prompts carry secrets/PII, bloat the artifact, and don't aid reproduction. The full prompt is kept as local run-state; if disclosure is needed it can be linked by content-hash.parent_attestation_sha256 chaining).A verifier needs only the committed artifact (source + this attestation):
subject/generated file sha256 → integrity;signatures against their keyid (did:key) → authenticity;acceptance checks → conformance.Reference implementation: openfab verify-file --att <path> — no server, no forge API.