Skip to content

spec: one mechanism for binding an external fact to an attested record (§3.1, §3.1.1) #197

Closed

Description

@imran-siddique

Spec section affected

§3.1 (Trust Record logical schema) and §3.1.1 (origin). New optional block, no change to existing required fields.

Problem

There is no way for a self-produced, hardware-attested Trust Record to reference a fact that lives outside it.

§3.1.1 gets close. origin.source_event_id is defined as "Identifier of the source event in that system, so a record traces back to it", which is exactly the shape needed. But origin is scoped to records assembled from evidence someone else produced, and the normative text is:

A record whose origin.kind is not self MUST carry runtime.platform: "software-only", and a verifier MUST reject it otherwise.

That rule is correct for what it was written for. An importer holding someone else's log has no quote to present, so a hardware platform value on such a record would be untrue. The consequence is the problem: today, the moment a record points at anything external, it stops being a hardware attested record.

This is not a one-off request. Three open items are the same shape:

Three instances means this wants one mechanism, not a field added per case.

Proposed change

Separate two things the spec currently conflates: where the evidence came from, which can lower assurance, and what else this record points at, which cannot.

Add an optional references block to §3.1. Assurance-neutral by construction.

Field Required Meaning
rel yes Relationship type. Closed set, extensible by registration. Initial values: authorized-intent (#179), approval-outcome (#191), behavior-trace.
id yes Identifier of the referenced fact in its own system.
resolver yes Identifier of the party obliged to resolve id.
retention no How long resolver undertakes to keep id resolvable.
digest no Digest of the referenced object, when the producer has it at issue time.

Normative rules:

  1. references MUST NOT affect runtime.platform. A record carrying references and no origin block is still self and still whatever its platform actually was.
  2. The record signature MUST cover references, per the canonicalisation in §3.2.2.
  3. A verifier MUST NOT reject a record because an entry in references cannot be resolved, and MUST NOT treat a resolved reference as attested evidence.
  4. A producer that cannot name a resolver MUST omit the entry rather than emit it with an empty or self-asserted resolver.

The distinction that makes rule 3 safe: what the signature attests is that this record points there, not the truth of what it points at. The pointer is inside the TEE boundary; the target is not. Conflating those is exactly what the origin MUST was written to prevent, and keeping them apart is what lets a reference be assurance-neutral rather than assurance-lowering.

Backward compatibility

  • Non-breaking (new optional field, informative addition)
  • Breaking

Existing records do not carry references and are unaffected. Existing verifiers ignore unknown fields. No change to origin, whose MUST stays exactly as it is: this proposal does not weaken it, it stops it being used for a job it was not written for.

Motivation

Immediate: it unblocks a compositional relationship between TRACE and an AAIF working group deliverable, where TRACE is the attestation layer referenced by a behavioural model rather than a competing schema. That is a better outcome for TRACE than either merging the models or duplicating them.

Structural: #179 and #191 are both currently blocked on the same missing primitive, and both will otherwise be solved by adding a bespoke field. Two bespoke fields is a pattern; three is a design failure.

The part this proposal does not settle, and should be argued here

resolver and retention are the interesting fields and I do not think one round of review will get them right. A reference is only worth the ability to look it up later, and that is not a hypothetical: in the npm keyv compromise the poisoned packages carried valid provenance logged in a transparency service, and fifteen days later the attestations could not be fetched, because the only working index was the artifact digest and unpublishing removed the metadata holding it. The log was intact and the records were unreachable.

TRACE has the same exposure through transparency. If we add references without saying who must be able to resolve them and for how long, we inherit it and so does anyone composing on top of us. I would rather that argument happen on this issue than after the field ships.

Related issues or PRs

#179, #191. Also §7 open question 3 (transparency log operators), which bears on resolver for the transparency field and probably wants resolving alongside this.

Sponsor: not yet named. Raising the technical argument first per CONTRIBUTING, which says proposals are evaluated on the argument alone.

Activity

  1. imran-siddique commented on Aug 23, 2026

    @imran-siddique
    MemberAuthor

    Delivered. #198 landed the block as §3.1.2 with all four normative rules, including the two that make it safe: references MUST NOT affect runtime.platform, and a verifier MUST NOT reject a record because an entry cannot be resolved.

    The artifact half is #199, which puts the block in schema/trace-claim.json, the v0.2 schema copy and the pydantic model. Without it both artifacts a producer validates against still reject a record the specification permits, because the schema is additionalProperties: false and TrustRecord is extra="forbid". That is in flight pending two edits.

    One deliberate divergence from this proposal, recorded so it is not read as drift: this issue described rel as a closed set extensible by registration. On #199 I ruled it an open string with the registered values documented, because §3.1.2 says "Registered rel values" while §3.1.1 says of the neighbouring field "kind is a closed set, because the value of the field is that a verifier can key on it". The two sections say different things on purpose, and closing rel would make every new relation a schema change and a spec change at once. Same intent, no schema-level membership enforcement. If the §7 registry question later settles toward enforcement, that is where it belongs.

    #179 and #191 stay open. They are the bindings that consume this, not duplicates of it, and both are now expressible without an origin block dragging the record down to software-only. Which was the point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions