Profile, 9 September 2026
TR-3 is a conformance level of the Testimony Record. A record that reaches it can show that an action carrying risk was gated by a named person, and that the person was not the one who proposed the action.
It is published as a profile with a digest so that a document written by somebody else can reference it rather than restate it. That is the only reason this page exists. A rule, a contract, an insurance condition, an audit programme or a protocol can say TR-3 and both parties know what was meant before they start arguing about it.
| Profile | testimony-record/tr-3, version 2 |
|---|---|
| Digest | sha256:a132a27279dca3336713641b0bd7537237edc32c435992e2ede51f43d4581177 |
| Specification | draft-clifford-testimony-record-03 |
| Machine-readable | machinetestimony.org/tr-3/tr-3.json, byte-identical to spec/profiles/tr-3.json |
| How to check | testimony_validate.py RECORD.jsonl --require TR-3 |
| Licence | CC BY 4.0. The validator is MIT. |
Levels are cumulative, so TR-3 includes TR-1 and TR-2. Seven of the nine are verified, meaning checkable from the record itself by anybody holding it. Two are attested, meaning the producer asserts them and a reader either takes them on trust or corroborates them elsewhere. That split is part of the profile, because a profile that lists nine requirements without saying which two rest on the producer's word is selling seven as nine.
Version 2, published 13 September 2026, adds one requirement: an approval that modified the action says what it changed. Version 1 is unchanged and still resolves at its own URL with its own digest. A reference to version 1 still means what it meant, which is the whole reason versions exist here rather than edits.
| Requirement | Basis |
|---|---|
| the record contains at least one decision | verified |
| the risk class is declared to come from outside the proposing model | attested |
| a refused action did not execute | verified |
| a decision does not contradict its own outcome | verified |
| every refusal records its reason | verified |
| an executed high-risk action has an approval entry | verified |
| an approval names a person, other than the proposer, for a decision in the record | verified |
| an approval that modified the action says what it changed | verified |
| the approver's name is declared to come from authentication | attested |
The list is generated from the reference validator rather than written out beside it. If a check is added, removed or renamed, the profile changes and a test fails. A profile that says a level requires something the validator does not check is a claim about a number, made by the party who owns the number, that nobody can reproduce.
Stating this is not modesty. A profile that lists only what it establishes will be cited as an assurance claim by the second time somebody uses it.
Because the documents that would reference this do not quote prose, they reference an identifier and check it.
The digest is sha256 over the profile's canonical bytes: sorted keys, no whitespace, UTF-8, which is the same canonicalisation RFC 8785 specifies and the same one the EMILIA Protocol receipts use. It covers the profile identity, the specification, the level and the requirement list. It deliberately does not cover the prose on this page, so correcting a sentence does not invalidate every reference to the profile.
Anybody can recompute it. The generator is spec/build_profile.py and it runs with no dependencies.
Three questions decide whether anybody writes a unit into a document. Can it change under me. Can it be withdrawn. Who decides. A page that does not answer them is not offering a unit, whatever else it says.
| Frozen | The requirements of a published version never change. A change to what the level requires is a new version with a new digest. Version 1 keeps its digest and its meaning. |
|---|---|
| Resolvable | Every published version stays retrievable at its own URL. Version 1 is at /tr-3/v1.json and will still be there after version 2 exists. The list is spec/profiles/PUBLISHED.json. |
| Irrevocable | CC BY 4.0 cannot be revoked by its own terms while its conditions are followed. That is the licence's guarantee and not the author's, which is the point: it does not depend on this project continuing to exist or on anybody's goodwill. |
| Checkable | You do not have to take any of the above on trust. The digest is over the requirements, so recompute it. The ledger is verified on every build, so editing a published version fails rather than ships. |
What this is not. It is not a promise that the level is right, that it will be adopted, or that a later version will be compatible with this one. A version supersedes rather than amends, and a reader who wants the old meaning cites the old version. That is what the versioned URL is for.
The guard that enforces this had a bug on the day it was written: it compared the served file's own stated digest instead of recomputing it, so editing a requirement while leaving the digest field alone passed. Trusting an artifact's claim about its own integrity is the failure this project reports in other systems. It now recomputes.
An evidence chain that evaluates a requirement owned by the relying party needs the relying party to have one. An agreement that conditions terms on evidence sufficiency has to reference the condition somehow. An audit programme has to say what counts. A procurement question has to be answerable yes or no.
In each case the hard part is not the checking. It is that the parties need a short name that means the same thing to both of them, published by somebody who is not either of them, and checkable without asking that somebody.
That is what this is, and it is free, permanently, for the same reason the specification and the validator are. A unit of measurement that its author can withdraw is not a unit of measurement.
If a requirement here does not match what the validator does, that is a bug and it is cheap to show: run the generator. If the level itself is wrong, that is worth more than agreement and it changes this page, the digest and the version.
The digest changing is not a small event. Anything referencing version 1 by digest continues to reference version 1, which is the point of pinning it.
The readings are CC BY 4.0, which asks for attribution, so the reference is here rather than left to be composed. This block is generated from the page it sits on, so a date that moves here moves in the citation too.
Clifford, T. (2026). TR-3, a named unit for whether an action was gated by a person. Machine Testimony. https://machinetestimony.org/tr-3/
@misc{clifford2026tr3,
author = {Clifford, Troy},
title = {TR-3, a named unit for whether an action was gated by a person},
year = {2026},
note = {Machine Testimony, read 9 September 2026},
url = {https://machinetestimony.org/tr-3/},
}
This page carries no DOI. It cites its dated URL, and saying so is the point: a citation naming a deposit that does not exist is worse than one naming a page that does.