OpenFab · Open Standard (draft)

Generation Predicate — v0.1

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.

Status: draft open standard. Intended to be proposed as a neutral in-toto / SLSA predicate type under neutral, community governance.

Purpose

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).

Envelope

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" }
  ]
}

Predicate fields

FieldTypeMeaning
spec_refstringthe 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_sha256hexsha256 fingerprint of the generation prompt (the prompt text is deliberately not included)
paramsobjectgeneration 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_passedbooldid 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)
timestampRFC3339when the attestation was produced
signoffs[{did, name, timestamp}]recorded human sign-offs (N-of-M gate)

Example predicate

{
  "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" } ]
}

Deliberately NOT in the predicate

Verification

A verifier needs only the committed artifact (source + this attestation):

  1. recompute each subject/generated file sha256integrity;
  2. verify the ed25519 signatures against their keyid (did:key) → authenticity;
  3. re-run the embedded acceptance checks → conformance.

Reference implementation: openfab verify-file --att <path> — no server, no forge API.