{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://sec.hypermedia.au/schemas/custody-chain/v1.schema.json",
  "title": "Custody Chain Ledger v1 Schema",
  "description": "Validates the custody-chain ledger: the hash-linked event log that is the authoritative home of custody events. Custody-chain attestations reference events here by BOM-Link (urn:cdx:<ledger-serial>/<version>#custody-event-<seq>); this schema is where CUST-002/003/008 event structure is enforced. Chain continuity and hash recomputation are verifier (adbom-cli) checks. Normative requirements: https://sec.hypermedia.au/standards/custody-chain/v1",
  "type": "object",
  "required": ["caseRef", "events"],
  "properties": {
    "caseRef": {
      "type": "string",
      "pattern": "^urn:cdx:.+",
      "description": "CUST-007: BOM-Link to the L1 Case Provenance BOM this ledger belongs to"
    },
    "events": {
      "type": "array",
      "minItems": 1,
      "items": { "$ref": "#/definitions/custodyEvent" },
      "description": "CUST-003: hash-linked, seq-ordered event records; genesis prevEventHash = 64 zero hex digits"
    }
  },
  "definitions": {
    "custodyEvent": {
      "type": "object",
      "required": ["seq", "action", "artifactRef", "artifactHash", "prevEventHash", "eventHash", "operator", "path", "gitCommit", "created"],
      "properties": {
        "seq": { "type": "integer", "minimum": 1 },
        "action": {
          "type": "string",
          "enum": ["collected", "derived", "accessed", "exported", "sealed"],
          "description": "CUST-002: closed vocabulary"
        },
        "artifactRef": { "type": "string", "minLength": 1 },
        "artifactHash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
        "prevEventHash": {
          "type": "string",
          "pattern": "^[a-f0-9]{64}$",
          "description": "CUST-003: the prior event's eventHash; genesis marker = 64 zero hex digits"
        },
        "eventHash": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
        "operator": { "type": "string", "minLength": 1 },
        "path": { "type": "string" },
        "gitCommit": { "type": "string", "pattern": "^[a-f0-9]{40}$|^[a-f0-9]{64}$" },
        "created": {
          "type": "string",
          "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}",
          "description": "CUST-001: recorded occurrence time (self-asserted, contemporaneous; proven time arrives at the seal)"
        },
        "purpose": { "type": "string", "minLength": 1 },
        "authority": { "type": "string", "minLength": 1 }
      },
      "allOf": [
        {
          "if": {
            "properties": { "action": { "const": "exported" } },
            "required": ["action"]
          },
          "then": {
            "required": ["purpose"],
            "description": "CUST-008: exported events must record why the evidence left the case"
          }
        },
        {
          "if": {
            "properties": { "action": { "enum": ["collected", "derived", "sealed"] } },
            "required": ["action"]
          },
          "then": {
            "not": {
              "anyOf": [
                { "required": ["purpose"] },
                { "required": ["authority"] }
              ]
            },
            "description": "CUST-008: purpose/authority only on exported (MUST/MAY) and accessed (MAY purpose)"
          }
        }
      ]
    }
  }
}
