Hypermedia Security: Custody Chain Specification
v1.0.0Hypermedia Au
Custody Chain (the case history log, hash-linked and batch-anchored)
The custody-chain attestation: the case's history log. One event per action taken on a piece of evidence, hash-linked from genesis, strictly ordered, appended to the git commit DAG as it happens, and given independent time in batch at each seal by one external RFC 3161 token. Its signed claim (custody-chain-intact) is what the Case Provenance BOM pins via hyper-spec:custodyChainRef. Chronology, continuity and handler attribution follow ISO/IEC 27037's chain-of-custody clauses; the hash chain and ledger make the record tamper-evident by construction.
Machine attestation: /attestations/custody-chain/v1
Relationships
References
- references →Hypermedia Security: Case Provenance BOM Specification
- target-standard →Hypermedia Security: Timestamp Token Specification
- references →Hypermedia Security: Timestamp Token Specification
Referenced by
- Hypermedia Security: Artifact Entry Specification(target-standard)
- Hypermedia Security: Case Provenance BOM Specification(target-standard)
- Hypermedia Security: Case Provenance BOM Specification(references)
About this standard
- hyper-spec:artifactKind
- attestation (declarations document)
- hyper-spec:claimPredicate
- custody-chain-intact
Sources
- www.iso.org
- ISO/IEC 27037:2012 — verified against the standard text 2026-07-11: §6.1 chain-of-custody minimum field set + chronology/continuity/contemporaneous framing; §6.6 every-activity-documented + reliable/traceable time source; §5.4.1 account-for-changes principles; §5.4.4 verification function; Annex B minimum transfer documentation (who did what and when; DEFR authorization/qualifications)
- git-scm.com
- Git is content-addressed and a commit object names the hash of its tree and its parent commits — so any change to earlier history changes every later commit hash (Merkle-DAG tamper evidence for the event ledger)
- github.com
- gittuf (beta, OpenSSF incubating; v0.15.0 June 2026) — Reference State Log at refs/gittuf/reference-state-log: a hash chain of signed reference-state entries; the optional strengthening behind the MAY-level rslHead hook, not a dependency
- www.rfc-editor.org
- RFC 2119 (as clarified by RFC 8174) — requirement key words; only capitalised forms are normative
- sec.hypermedia.au
- website
prevEventHash equals the previous event's eventHash (CUST-003); sequence numbers are gapless (CUST-004); each seal covers the batch with one RFC 3161 timestamp token (CUST-005).CUST-001 Event Record MUST NOT
Every custody event MUST record: seq, action, prevEventHash, eventHash, operator, path (vault-relative), gitCommit, and created (the recorded occurrence time, ISO-8601). An event whose action is collected, derived, accessed or exported MUST additionally record artifactRef (the bom-ref of the artifact entry in the case catalog) with artifactHash. An event whose action is sealed MUST instead record catalogRef (the BOM-Link to the Case Provenance BOM version the seal produced) with catalogHash. An event MUST NOT carry any field beyond those this standard defines for its action. Events MUST be appended to the git commit DAG as the action happens and MUST NOT carry a per-event timestamp token: created is self-asserted recorded time; independent time arrives in batch at the next seal (see #batch-time-anchor). An event whose action is renewed MUST instead record recordRef (the BOM-Link to the finalised Case Provenance BOM version the Evidence Record covers) with recordHash (the digest of the record the renewal produced), and renewalKind, exactly one of timestamp or hash-tree.
This is ISO/IEC 27037 §6.1's minimum custody record realised as one event object: the unique evidence identifier (artifactRef + artifactHash), who handled it (operator), what was done (action), where it stood (path), and when (created, recorded contemporaneously — §6.1 asks that the record be a contemporaneous document). A seal is the one action not taken on a single artifact, so it names the catalog version it produced instead. The gitCommit field names the ledger commit that landed the event; commit granularity is deliberately unconstrained, because ordering lives in seq and prevEventHash, and each event carries its own recorded time regardless of how many events share a commit.
- required-fields
- seq
- required-fields
- action
- required-fields
- prevEventHash
- required-fields
- eventHash
- required-fields
- operator
- required-fields
- path
- required-fields
- gitCommit
- required-fields
- created
- artifact-action-fields
- artifactRef
- artifact-action-fields
- artifactHash
- sealed-action-fields
- catalogRef
- sealed-action-fields
- catalogHash
- renewed-action-fields
- recordRef
- renewed-action-fields
- recordHash
- renewed-action-fields
- renewalKind
- iso-basis
- ISO/IEC 27037 §6.1
CUST-002 Action Coverage MUST
The action field MUST be exactly one of: collected, derived, accessed, exported, sealed, renewed. This vocabulary is closed: no other verbs are valid in v1. Every action taken on an artifact MUST produce a custody event, every seal MUST produce one, and every Evidence Record renewal (evidence-record/v1 #renewal) MUST produce one. Nothing happens to a case off the record.
ISO/IEC 27037 §6.6: every activity taken should be documented, to ensure no details have been left out. The five artifact-and-seal verbs cover the live case: brought into the case (collected), transformed (derived — §5.4.1's account-for-changes duty), read by an analysis (accessed), taken out of the case (exported), and the case being sealed, which is not an act on any one artifact. The sixth covers the archive: a renewal is not an act on an artifact or a seal either, and it is the only event that occurs after the finalisation seal — the record's long-term proof being rebuilt, which the sidecar cannot testify to because it holds only the current record's hash and no history.
- allowed-values
- collected
- allowed-values
- derived
- allowed-values
- accessed
- allowed-values
- exported
- allowed-values
- sealed
- allowed-values
- renewed
- vocabulary
- closed
- iso-basis
- ISO/IEC 27037 §6.6, §5.4.1
CUST-003 Hash-Linked Chain MUST
Every event's prevEventHash MUST equal the eventHash of the immediately preceding event, from a genesis marker forward to the head. The genesis marker is an all-zero content of the declared algorithm's length. The chain MUST be recorded in the git commit DAG of the case repository. The ledger MUST be stored at Custody/custody-chain.json in the case repository.
Two tamper-evidence layers, one inside the other. The event chain itself: alter or remove any past event and every later prevEventHash stops matching. The ledger beneath it: git is content-addressed and a commit names the hash of its tree and its parent commits, so rewriting history changes every later commit hash. ISO/IEC 27037 §6.1 requires the custody record to trace an unbroken chronology from identification to present and to not be compromised — this requirement delivers that property by construction rather than by procedure. Where gittuf is enabled, its Reference State Log adds forge-independent append-only monotonicity via the MAY-level rslHead hook; it is a strengthening, never a dependency.
- ledger
- git-commit-DAG
- iso-basis
- ISO/IEC 27037 §6.1
CUST-004 No Gaps MUST
The seq field MUST be strictly monotonic with no gaps across the life of the case. A verifier MUST treat any gap or repetition in seq as a broken chain.
Combined with the hash link (#hash-linked-chain), gapless sequence numbers make both reordering and deletion independently detectable: the hash chain catches alteration, the sequence catches removal. Together they encode ISO/IEC 27037 §6.1's demand that the record identify the chronology of movement and handling.
- iso-basis
- ISO/IEC 27037 §6.1
CUST-005 Batch Time Anchor MUST NOT
Every custody event MUST be covered by the next seal's RFC 3161 token: one token per seal, taken over a Merkle root committing to every eventHash since the prior seal, per timestamp-token/v1 (#batch-anchor-at-seal). Between seals, events carry order (#no-gaps), tamper evidence (#hash-linked-chain) and recorded time (created), but no independent time; a verifier MUST NOT present an event's created field as proven time. A renewed event is instead covered by the Archive Timestamp inside the Evidence Record it produced (evidence-record/v1 #timestamp-sourcing), because it occurs after the case's last seal; the principle is unchanged — independent time comes from a clock the organisation does not control.
The two-layer time model, stated normatively. Recorded time (created) is what ISO/IEC 27037 §6.1 asks the custody record to capture, written contemporaneously by the operator's machine. Proven time is an upper bound from a clock the organisation does not control — the external TSA's token over the batch root. ISO §6.6 instructs the DEFR to compare a device's clock against a reliable, traceable time source; the seal anchor applies the same principle to the record itself, per batch. ISO nowhere requires third-party time per event, so the batch anchor exceeds the standard rather than compensating for a gap.
- target-standard
- https://sec.hypermedia.au/standards/timestamp-token/v1#batch-anchor-at-seal
- iso-basis
- ISO/IEC 27037 §6.1 (recorded time), §6.6 (traceable time source)
CUST-006 Collector Identity MUST
The attestation's assessors[] MUST identify the collector, and that identity MUST equal the identity in the Fulcio certificate on the attestation's signature. Every event's operator field MUST name an identified handler.
ISO/IEC 27037 requires that custody actions be attributable to a named, authorized handler — a synthesis of §6.1 (the record shows who was responsible for handling), Annex B (transfer documentation states the DEFR's authorization, training and qualifications) and §6.4 (demonstrable competency). Binding the assessor to the cryptographic signing identity is a stronger form of the same attribution: the name on the record is the identity that signed it, compared as Fulcio-verified identities, never as name strings.
- iso-basis
- handler attribution / DEFR identity — ISO/IEC 27037 §6.1 + Annex B + §6.4 (synthesis, not a quoted term)
CUST-007 Claim and Signature MUST
The attestation MUST carry exactly one claim whose target is the sealed Case Provenance BOM by BOM-Link, whose predicate is custody-chain-intact, and which cites the chain head as its evidence: the eventHash of the last event in the ledger at the citation's own created instant, content-addressed, carrying that event's sequence number. Naming the head commits to every event before it. The ledger is append-only and the attestation freezes at the seal, so the head is the head as of the citation; events appended afterwards do not invalidate it. The attestation MUST carry an enveloped JSF signature by the collector's Fulcio identity, using ES384, ES512, or ML-DSA-65 or ML-DSA-87 identified by their FIPS 204 OIDs. The claim's evidence array MUST list exactly the bom-refs of the entries in declarations.evidence: every cited bom-ref resolves to a carried entry, and every carried entry is cited.
The claim is the junction the catalog pins: the L1's hyper-spec:custodyChainRef resolves to this attestation, and this claim points back at the L1 it testifies about. The predicate is a stable machine identifier from the locked v1.0.0 vocabulary; human-facing labels map onto it and never replace it inside the signed record.
- predicate
- custody-chain-intact
CUST-008 Export Justification MUST
An event whose action is exported MUST record purpose (why the evidence left the case) and MAY record authority (the authorising party, where applicable). An event whose action is accessed MAY record purpose. No other action records purpose, and no action other than exported records authority.
ISO/IEC 27037 §6.1's minimum field set includes why the evidence was checked out — which case, the purpose, and the relevant authority if applicable. Which case is structural (every event's artifactRef resolves into the case's own catalog); purpose and authority are recorded exactly where ISO aims them — at the moment evidence leaves the preservation boundary. Automated accessed/derived events stay lean: the purpose of an access is the analysis that follows it, which the analysis-provenance attestation binds far more strongly.
- exported-required-fields
- purpose
- exported-optional-fields
- authority
- accessed-optional-fields
- purpose
- iso-basis
- ISO/IEC 27037 §6.1
