{
  "$schema": "https://cyclonedx.org/schema/bom-1.7.schema.json",
  "bomFormat": "CycloneDX",
  "specVersion": "1.7",
  "serialNumber": "urn:uuid:11afbbb4-8c4c-43c0-9a78-ca682c3ac01d",
  "version": 1,
  "metadata": {
    "timestamp": "2026-07-11T00:00:00Z",
    "authors": [
      {
        "name": "Hypermedia Au Security Team"
      }
    ],
    "component": {
      "type": "data",
      "name": "Custody Chain Specification",
      "version": "1.0.0"
    },
    "properties": [
      {
        "name": "cyberbench:artifact-kind",
        "value": "attestation (declarations document)"
      },
      {
        "name": "cyberbench:fullname",
        "value": "Custody Chain (the case history log, hash-linked and batch-anchored)"
      },
      {
        "name": "cyberbench:claim-predicate",
        "value": "custody-chain-intact"
      }
    ]
  },
  "definitions": {
    "standards": [
      {
        "bom-ref": "custody-chain-v1.0.0",
        "name": "Hypermedia Security: Custody Chain Specification",
        "version": "1.0.0",
        "description": "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 cyberbench: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.",
        "owner": "Hypermedia Au",
        "externalReferences": [
          {
            "type": "other",
            "url": "https://sec.hypermedia.au/attestations/custody-chain/v1",
            "comment": "The attestation schema enforcing this standard.",
            "properties": [
              {
                "name": "cyberbench:role",
                "value": "attestation-schema"
              }
            ]
          },
          {
            "type": "other",
            "url": "https://sec.hypermedia.au/standards/case-provenance/v1",
            "comment": "cyberbench:custodyChainRef",
            "properties": [
              {
                "name": "cyberbench:role",
                "value": "referenced-from"
              }
            ]
          },
          {
            "type": "documentation",
            "url": "https://www.iso.org/standard/44381.html",
            "comment": "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)"
          },
          {
            "type": "documentation",
            "url": "https://git-scm.com/book/en/v2/Git-Internals-Git-Objects",
            "comment": "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)"
          },
          {
            "type": "documentation",
            "url": "https://github.com/gittuf/gittuf",
            "comment": "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"
          },
          {
            "type": "documentation",
            "url": "https://www.rfc-editor.org/rfc/rfc2119",
            "comment": "RFC 2119 (as clarified by RFC 8174) — requirement key words; only capitalised forms are normative"
          },
          {
            "type": "website",
            "url": "https://sec.hypermedia.au"
          }
        ],
        "requirements": [
          {
            "bom-ref": "event-record",
            "identifier": "CUST-001",
            "title": "Event Record",
            "text": "Every custody event MUST record: seq, action, artifactRef (a BOM-Link into the case catalog) with artifactHash, prevEventHash, eventHash, operator, path, gitCommit, and created (the recorded occurrence time, ISO-8601). 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).",
            "descriptions": [
              "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). 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."
            ],
            "parent": "custody-chain-v1.0.0",
            "properties": [
              {
                "name": "requirement-uri",
                "value": "https://sec.hypermedia.au/standards/custody-chain/v1#event-record"
              },
              {
                "name": "validation-method",
                "value": "schema"
              },
              {
                "name": "required-fields",
                "value": "seq,action,artifactRef,artifactHash,prevEventHash,eventHash,operator,path,gitCommit,created"
              },
              {
                "name": "time-model",
                "value": "created=recorded (self-asserted, per event); proven time = batch at seal"
              },
              {
                "name": "iso-basis",
                "value": "ISO/IEC 27037 §6.1"
              }
            ]
          },
          {
            "bom-ref": "action-coverage",
            "identifier": "CUST-002",
            "title": "Action Coverage",
            "text": "The action field MUST be exactly one of: collected, derived, accessed, exported, sealed. This vocabulary is closed: no other verbs are valid in v1. Every action taken on evidence MUST produce a custody event — nothing happens to evidence off the record.",
            "descriptions": [
              "ISO/IEC 27037 §6.6: every activity taken should be documented, to ensure no details have been left out. The five verbs cover the evidence lifecycle: 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), included in a signed checkpoint (sealed)."
            ],
            "parent": "custody-chain-v1.0.0",
            "properties": [
              {
                "name": "requirement-uri",
                "value": "https://sec.hypermedia.au/standards/custody-chain/v1#action-coverage"
              },
              {
                "name": "validation-method",
                "value": "schema"
              },
              {
                "name": "allowed-values",
                "value": "collected,derived,accessed,exported,sealed"
              },
              {
                "name": "vocabulary",
                "value": "closed"
              },
              {
                "name": "iso-basis",
                "value": "ISO/IEC 27037 §6.6, §5.4.1"
              }
            ]
          },
          {
            "bom-ref": "hash-linked-chain",
            "identifier": "CUST-003",
            "title": "Hash-Linked Chain",
            "text": "Every event's prevEventHash MUST equal the eventHash of the immediately preceding event, from a genesis marker forward to the head. The chain MUST be recorded in the git commit DAG of the case repository.",
            "descriptions": [
              "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."
            ],
            "parent": "custody-chain-v1.0.0",
            "properties": [
              {
                "name": "requirement-uri",
                "value": "https://sec.hypermedia.au/standards/custody-chain/v1#hash-linked-chain"
              },
              {
                "name": "validation-method",
                "value": "chain-verification"
              },
              {
                "name": "genesis",
                "value": "prevEventHash of the first event = the genesis marker"
              },
              {
                "name": "ledger",
                "value": "git-commit-DAG (gittuf RSL optional strengthening)"
              },
              {
                "name": "iso-basis",
                "value": "ISO/IEC 27037 §6.1"
              }
            ]
          },
          {
            "bom-ref": "no-gaps",
            "identifier": "CUST-004",
            "title": "No Gaps",
            "text": "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.",
            "descriptions": [
              "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."
            ],
            "parent": "custody-chain-v1.0.0",
            "properties": [
              {
                "name": "requirement-uri",
                "value": "https://sec.hypermedia.au/standards/custody-chain/v1#no-gaps"
              },
              {
                "name": "validation-method",
                "value": "chain-verification"
              },
              {
                "name": "iso-basis",
                "value": "ISO/IEC 27037 §6.1"
              }
            ]
          },
          {
            "bom-ref": "batch-time-anchor",
            "identifier": "CUST-005",
            "title": "Batch Time Anchor",
            "text": "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.",
            "descriptions": [
              "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's own instruction to compare against a reliable, traceable time source is exactly what the seal anchor provides, on the record, per batch; ISO nowhere requires third-party time per event, so the batch anchor exceeds the standard rather than compensating for a gap."
            ],
            "parent": "custody-chain-v1.0.0",
            "properties": [
              {
                "name": "requirement-uri",
                "value": "https://sec.hypermedia.au/standards/custody-chain/v1#batch-time-anchor"
              },
              {
                "name": "validation-method",
                "value": "merkle-inclusion"
              },
              {
                "name": "target-standard",
                "value": "https://sec.hypermedia.au/standards/timestamp-token/v1#batch-anchor-at-seal"
              },
              {
                "name": "iso-basis",
                "value": "ISO/IEC 27037 §6.1 (recorded time), §6.6 (traceable time source)"
              }
            ]
          },
          {
            "bom-ref": "collector-identity",
            "identifier": "CUST-006",
            "title": "Collector Identity",
            "text": "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.",
            "descriptions": [
              "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."
            ],
            "parent": "custody-chain-v1.0.0",
            "properties": [
              {
                "name": "requirement-uri",
                "value": "https://sec.hypermedia.au/standards/custody-chain/v1#collector-identity"
              },
              {
                "name": "validation-method",
                "value": "certificate-identity-comparison"
              },
              {
                "name": "iso-basis",
                "value": "handler attribution / DEFR identity — ISO/IEC 27037 §6.1 + Annex B + §6.4 (synthesis, not a quoted term)"
              }
            ]
          },
          {
            "bom-ref": "claim-and-signature",
            "identifier": "CUST-007",
            "title": "Claim and Signature",
            "text": "The attestation MUST carry exactly one claim whose target is the Case Provenance BOM by BOM-Link, whose predicate is custody-chain-intact, and which cites the custody events as its evidence. The attestation MUST be JSF ES256 signed by the collector's Fulcio identity.",
            "descriptions": [
              "The claim is the junction the catalog pins: the L1's cyberbench: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."
            ],
            "parent": "custody-chain-v1.0.0",
            "properties": [
              {
                "name": "requirement-uri",
                "value": "https://sec.hypermedia.au/standards/custody-chain/v1#claim-and-signature"
              },
              {
                "name": "validation-method",
                "value": "cryptographic-signature"
              },
              {
                "name": "predicate",
                "value": "custody-chain-intact"
              },
              {
                "name": "claim-target",
                "value": "case-provenance L1 (BOM-Link + hash)"
              }
            ]
          },
          {
            "bom-ref": "export-justification",
            "identifier": "CUST-008",
            "title": "Export Justification",
            "text": "An event whose action is exported MUST additionally 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. Other actions carry neither field.",
            "descriptions": [
              "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."
            ],
            "parent": "custody-chain-v1.0.0",
            "properties": [
              {
                "name": "requirement-uri",
                "value": "https://sec.hypermedia.au/standards/custody-chain/v1#export-justification"
              },
              {
                "name": "validation-method",
                "value": "schema"
              },
              {
                "name": "exported-fields",
                "value": "purpose (MUST), authority (MAY)"
              },
              {
                "name": "accessed-fields",
                "value": "purpose (MAY)"
              },
              {
                "name": "iso-basis",
                "value": "ISO/IEC 27037 §6.1 (owner decision 2026-07-11, DECISION-SPEC5-ISO27037-Impact §3 Option A)"
              }
            ]
          }
        ]
      }
    ]
  }
}
