|
| 1 | +# PRML identity levels |
| 2 | + |
| 3 | +> **What this document is.** A non-normative ladder for the strength of |
| 4 | +> the binding between a PRML manifest's `producer` claim and the real-world |
| 5 | +> entity that authored it. Five levels, from "you just typed your name into |
| 6 | +> a YAML file" to "your manifest is anchored in a public transparency log |
| 7 | +> tied to an institutional identity." Each level is auditable; they differ |
| 8 | +> in how much trust the verifier must extend to the producer. |
| 9 | +> |
| 10 | +> **What this document is not.** Normative. PRML v0.1 and v0.2 accept any |
| 11 | +> identity level; the spec does not refuse a manifest because its producer |
| 12 | +> is unsigned. This document exists so that a verifier evaluating a |
| 13 | +> manifest can place it on the ladder and decide accordingly, and so that |
| 14 | +> producers can decide how high to climb. The v0.3 RFC track will lift |
| 15 | +> these levels into a normative `identity_level` field. |
| 16 | +
|
| 17 | +## The five levels |
| 18 | + |
| 19 | +### Level 0 — Unsigned local manifest |
| 20 | + |
| 21 | +The producer typed their name (or institution, or GitHub handle) into the |
| 22 | +`producer` field. The manifest is hashed and may be stored locally or |
| 23 | +shared. Nothing externally observable ties the producer string to the |
| 24 | +hash beyond the bytes themselves. |
| 25 | + |
| 26 | +```yaml |
| 27 | +producer: |
| 28 | + id: alice@example.com |
| 29 | +``` |
| 30 | +
|
| 31 | +**What this defends against:** A producer who keeps the manifest private |
| 32 | +cannot retroactively edit it without changing the hash. Useful for |
| 33 | +personal experiments and for hashing-as-discipline; useful inside an |
| 34 | +organization where the audience is colleagues. |
| 35 | +
|
| 36 | +**What this does not defend against:** Anyone holding the manifest can |
| 37 | +swap the `producer` field, re-hash, and publish under a different name. |
| 38 | +The original "alice" identity claim has no anchor. |
| 39 | + |
| 40 | +**Use when:** You are pre-registering for yourself or your immediate |
| 41 | +team and external verification is not in scope. |
| 42 | + |
| 43 | +--- |
| 44 | + |
| 45 | +### Level 1 — Public git commit or registry timestamp |
| 46 | + |
| 47 | +The manifest is committed to a public git repository, or POSTed to a |
| 48 | +public PRML registry. Either action records a server-side wall-clock |
| 49 | +timestamp and an immutable content-addressed receipt outside the |
| 50 | +producer's control. |
| 51 | + |
| 52 | +```yaml |
| 53 | +producer: |
| 54 | + id: studio-11.co |
| 55 | +# anchor: git commit a3f9c...c821 in studio-11-co/falsify on 2026-05-08 |
| 56 | +# or: registry receipt at registry.falsify.dev/<hash> |
| 57 | +``` |
| 58 | + |
| 59 | +**What this defends against:** Producer cannot back-date the manifest to |
| 60 | +a time before the commit/registry observation. The hash is mirrored in |
| 61 | +at least one external system. |
| 62 | + |
| 63 | +**What this does not defend against:** The `producer` string is still |
| 64 | +unsigned. Anyone with push access to the repository, or anyone with a |
| 65 | +manifest copy, can submit it under their own name elsewhere. Multiple |
| 66 | +"studio-11.co" producers are not distinguishable. |
| 67 | + |
| 68 | +**Use when:** You publish your manifests in a public repo and want a |
| 69 | +default audit trail. This is the level most v0.1/v0.2 manifests |
| 70 | +operate at in practice. |
| 71 | + |
| 72 | +--- |
| 73 | + |
| 74 | +### Level 2 — Signed commit or detached PGP / minisign signature |
| 75 | + |
| 76 | +The manifest carries a cryptographic signature over the canonical bytes, |
| 77 | +produced with a key whose public half is documented out-of-band (PGP |
| 78 | +key on the producer's website, minisign key in a `MAINTAINERS` file, |
| 79 | +git commit signed with a known SSH key). |
| 80 | + |
| 81 | +```yaml |
| 82 | +producer: |
| 83 | + id: studio-11.co |
| 84 | + signature: <detached signature over canonical bytes> |
| 85 | +``` |
| 86 | + |
| 87 | +**What this defends against:** A different party cannot republish under |
| 88 | +the same `producer.id` without the corresponding private key. The |
| 89 | +binding between producer string and signing key is verifiable, as |
| 90 | +strongly as the out-of-band key publication is verifiable. |
| 91 | + |
| 92 | +**What this does not defend against:** Key compromise. Key rotation |
| 93 | +mechanics. Producer identity is exactly as strong as the producer's |
| 94 | +key-management hygiene. There is no central revocation channel. |
| 95 | + |
| 96 | +**Use when:** You operate under an established public identity (an |
| 97 | +open-source project with a published key, an institution with a |
| 98 | +documented signing process) and want signature-strength binding without |
| 99 | +external dependencies. |
| 100 | + |
| 101 | +--- |
| 102 | + |
| 103 | +### Level 3 — Sigstore + Rekor transparency log |
| 104 | + |
| 105 | +The manifest is signed via Sigstore's keyless flow (`cosign sign-blob`), |
| 106 | +producing a short-lived certificate from Fulcio bound to an OIDC |
| 107 | +identity (GitHub Actions, Google, Microsoft, GitHub user) and a Rekor |
| 108 | +log entry. Both certificate and Rekor entry are public. |
| 109 | + |
| 110 | +```yaml |
| 111 | +producer: |
| 112 | + id: studio-11.co |
| 113 | + sigstore_bundle: <inline JSON bundle> |
| 114 | +# Rekor entry: https://search.sigstore.dev/?hash=<sha256> |
| 115 | +``` |
| 116 | + |
| 117 | +**What this defends against:** Producer identity is bound to an |
| 118 | +authoritative OIDC issuer (the org that runs your GitHub repo, or your |
| 119 | +Google account), not to a manually-maintained key. Rekor entries are |
| 120 | +append-only and publicly mirrored; a producer cannot delete a signature |
| 121 | +post-hoc. The timestamp on the Rekor entry is wall-clock-authoritative. |
| 122 | + |
| 123 | +**What this does not defend against:** Compromise of the underlying |
| 124 | +OIDC account. Cookbook Pattern 11 walks through the full Sigstore flow |
| 125 | +including CI-based signing. |
| 126 | + |
| 127 | +**Use when:** You want the strongest available open identity binding |
| 128 | +without running your own PKI. This is the recommended default for |
| 129 | +production audit trails. |
| 130 | + |
| 131 | +--- |
| 132 | + |
| 133 | +### Level 4 — Institutional / regulated identity |
| 134 | + |
| 135 | +The manifest is signed by an institutional key managed under a |
| 136 | +documented policy (eIDAS qualified certificate, FIPS 140-3 validated |
| 137 | +HSM, journal-issued submission credential, notified body assessment |
| 138 | +credential), and the identity binding is enforced by a registry that |
| 139 | +refuses lower-level submissions. |
| 140 | + |
| 141 | +```yaml |
| 142 | +producer: |
| 143 | + id: hospital.example.org |
| 144 | + signature: <signature from institutional HSM> |
| 145 | + key_id: sha256:<HSM-bound key fingerprint> |
| 146 | +# anchor: institutional registry entry, regulator-mirrored |
| 147 | +``` |
| 148 | + |
| 149 | +**What this defends against:** Regulatory and journal-grade scenarios |
| 150 | +where the producer must be tied to a legally-identifiable entity, key |
| 151 | +management is auditable under a published policy, and the registry |
| 152 | +itself is part of the trust chain. |
| 153 | + |
| 154 | +**What this does not defend against:** Institutional policy failures |
| 155 | +(an institution that signs everything its employees produce without |
| 156 | +review). Higher levels of trust place higher demands on the |
| 157 | +institution's internal process; PRML cannot verify those. |
| 158 | + |
| 159 | +**Use when:** Your manifest is part of a clinical-trial submission, a |
| 160 | +notified-body conformity assessment, a peer-reviewed publication with |
| 161 | +mandatory pre-registration, or any other context where the registry |
| 162 | +itself is operated by a trusted institution. |
| 163 | + |
| 164 | +--- |
| 165 | + |
| 166 | +## How to decide |
| 167 | + |
| 168 | +A producer choosing a level should ask: |
| 169 | + |
| 170 | +1. **Will the verifier know me out-of-band?** If yes, Level 0–1 may be |
| 171 | + enough. If no, you need Level 2 or higher. |
| 172 | +2. **Is the cost of mis-identification borne by me or by a third party?** |
| 173 | + Internal experiments: Level 0 fine. Public claims: Level 1 default. |
| 174 | + Regulated claims: Level 3+. |
| 175 | +3. **Can I run the higher-level mechanism reliably?** Level 3 needs OIDC |
| 176 | + plus a CI runner with `cosign`. Level 4 needs institutional support. |
| 177 | + Climbing levels you cannot maintain consistently is worse than |
| 178 | + sitting at a level you can. |
| 179 | + |
| 180 | +A verifier evaluating a manifest should ask: |
| 181 | + |
| 182 | +1. **What level does this manifest claim?** (Look for signatures, |
| 183 | + Sigstore bundles, registry anchors.) |
| 184 | +2. **What level can I independently confirm?** (Re-derive the hash; |
| 185 | + check Rekor; check git commit signatures.) |
| 186 | +3. **What level does my use case require?** (A blog post: Level 1 is |
| 187 | + often enough. An audit submission: Level 3+ is the floor.) |
| 188 | + |
| 189 | +## What changes in v0.3 |
| 190 | + |
| 191 | +The v0.3 RFC track proposes a normative `identity_level` field with |
| 192 | +values 0–4 matching this document. The field would be informative |
| 193 | +(self-declared); verifiers retain the obligation to independently |
| 194 | +confirm the level. See `spec/v0.3-backlog/02-producer-struct.md`. |
| 195 | + |
| 196 | +## Related |
| 197 | + |
| 198 | +- v0.1 §2.3.3 — `producer` field semantics (existing signature field) |
| 199 | +- v0.1 §8.1 — threat model |
| 200 | +- Cookbook Pattern 11 — PRML + Sigstore for execution integrity |
| 201 | +- v0.3 backlog item 02 — structured producer field |
0 commit comments