spec: add an assurance-neutral references block (#197) - #198
Conversation
Closes the gap where a self-produced, hardware-attested Trust Record had no way to point at a fact outside itself. origin.source_event_id is the right shape but origin is scoped to assembled evidence, and a record whose origin.kind is not self MUST carry runtime.platform software-only. So pointing outward cost the attestation. Adds an optional references block in a new section 3.1.2, with three registered rel values covering the three cases that are currently the same shape: authorized-intent (#179), approval-outcome (#191), and behavior-trace, raised by the AAIF Observability and Traceability WG. The rule that makes it safe: the signature attests that this record points somewhere, not the truth of what it points at. So references MUST NOT affect runtime.platform, a verifier MUST NOT reject a record for an unresolvable reference, and MUST NOT treat a resolved one as attested evidence. section 3.1.1 is unchanged. This does not weaken its MUST, it stops that MUST being applied to a job it was not written for. Names retention as unsettled and unenforced rather than implying otherwise, and points at open question 3 as the same problem for transparency. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013EQx4N5BzTQbY8kvXUsdkY
lywinged
left a comment
There was a problem hiding this comment.
Two things that are checkable, and one design question that I think decides the shape of the block.
schema/trace-claim.json is additionalProperties: false at the top level and this branch does not touch it, so a record carrying references does not validate. Measured on examples/tpm2.json, which validates as committed and fails with Additional properties are not allowed ('references' was unexpected) once an entry from the field table is added. Rule 2 requires the signature to cover the block, so as it stands there is no conformant record that can carry it. The suite is green at 496 passed because nothing connects the section 3.1 field table to the schema.
The shape is unstated as well. The section says "a references entry" and "an entry in references" throughout, which reads as a collection, but neither it nor the field table says whether that is an array or an object. Section 3.1.1 does not state origin's shape either, because the schema does it there. With no schema entry there is nowhere that says what a producer emits, and canonicalisation under section 3.2.2 differs between the two. The same gap leaves duplicates undefined: whether two authorized-intent entries are legal, and what a verifier does with them.
On the design. Section 3.3.2 answers the same question for external execution evidence and answers it the other way. There, a verifier configured with the issuer key MUST reject the Trust Record when the signature or the digest check fails, and a verifier without the key treats the receipt as unverified rather than invalid and SHOULD surface an advisory status rather than silently ignoring it. Rule 3 here says MUST NOT reject and MUST NOT count, with nothing surfaced. Two sections apart, the same question has two answers and no text reconciling them.
That difference lands hardest on digest. An entry carrying one is checkable in the way an external receipt is checkable, and rule 3 forbids the check from mattering. So the question I would want settled: what is a verifier permitted to do after resolving an entry and matching its digest? If the answer is nothing, digest is decorative and could come out. If it is anything at all, rule 3 needs that exception written down, and appraisal is additionalProperties: false over status, verifier, policy_ref, timestamp and provenance_depth_verified, so there is nowhere for a verifier to record that it happened.
Smaller, and worth settling now rather than at the fourth value: rel is a closed set, on the same reasoning section 3.1.1 gives for origin.kind, but there is no rule for a value a verifier does not recognise. Without one, adding a fourth rel is a breaking change for a strict verifier, which the backward-compatibility note does not cover.
Implements the proposal in #197. Normative change, so please read that issue first for the argument.
What this fixes
A self-produced, hardware-attested Trust Record has no way to reference a fact outside itself.
origin.source_event_idis the right shape, defined as "Identifier of the source event in that system, so a record traces back to it". But §3.1.1 scopesoriginto records assembled from someone else's evidence, and requires that a record whoseorigin.kindis notselfMUST carryruntime.platform: "software-only", with verifiers rejecting it otherwise.So today, the moment a record points outward, it stops being a hardware attested record.
Why one mechanism rather than a third field
Three open items are the same shape:
Two bespoke fields is a pattern. Three is a design failure. Each becomes a registered
relvalue here instead.The rule that makes it safe
The signature attests that this record points somewhere. It does not attest the truth of what it points at. The pointer is produced inside the boundary that produced the record; the target is not.
That gives three normative consequences, all in the diff:
referencesMUST NOT affectruntime.platformWithout the second rule, whoever controls the target could invalidate evidence they do not hold. Without the third, this becomes the assurance laundering §3.1.1 exists to prevent.
§3.1.1 is untouched
This does not weaken that MUST. It stops it being applied to a job it was not written for. Records assembled from third-party evidence still take
software-only, exactly as now.Backward compatibility
Non-breaking. New optional field, existing records do not carry it, existing verifiers ignore unknown fields. No wire format or algorithm change. Per CONTRIBUTING a schema PR must track a merged spec change, so the schema and conformance vectors follow once the shape here is agreed rather than in this PR.
What I have deliberately left unresolved
resolverandretentionare the interesting fields and I do not expect one round of review to get them right.A reference is worth only the ability to resolve it later. That is not hypothetical: in the npm keyv compromise the poisoned packages carried valid provenance logged in a transparency service, and fifteen days on the attestations could not be fetched, because the only working index was the artifact digest and unpublishing removed the metadata holding it. Log intact, records unreachable.
TRACE has the same exposure through
transparency. §7 open question 3 is the same problem for that field and I think the two want resolving together. The spec text saysretentionis an undertaking that nothing here enforces, rather than implying otherwise.Sponsor
Not yet named. CONTRIBUTING says proposals are evaluated on the technical argument alone and that a normative PR without a sponsor is not rejected on that basis, so raising it this way deliberately. Happy to have a maintainer carry it, or to name a sponsor if reviewers would rather.