{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://sec.hypermedia.au/schemas/timestamp-token/v1.schema.json",
  "title": "Timestamp Sidecar Index v1 Schema",
  "description": "Validates Timestamps/index.json, the sidecar join between sealed documents and the RFC 3161 tokens that cover them. NOT a CycloneDX document. Shape-only: that a token verifies, that its genTime falls inside the signing certificate's window, that a Merkle root covers the events it claims, and that every stored token appears here are verifier (adbom-cli) checks. The case is the vault root, so the case identifier is derivable from this file's location and is not repeated. Token paths are derivable from the identity of what they cover and are not stored. Normative requirements: https://sec.hypermedia.au/standards/timestamp-token/v1",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "tokens"
  ],
  "properties": {
    "tokens": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "kind",
          "hash"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "seal",
              "event",
              "batch"
            ],
            "description": "TST-006: seal tokens under Timestamps/seals/, event tokens under Timestamps/events/, fallback batch tokens under Timestamps/batch/"
          },
          "serialNumber": {
            "type": "string",
            "pattern": "^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
          },
          "version": {
            "type": "integer",
            "minimum": 1
          },
          "seq": {
            "type": "integer",
            "minimum": 1
          },
          "fromSeq": {
            "type": "integer",
            "minimum": 1
          },
          "toSeq": {
            "type": "integer",
            "minimum": 1
          },
          "hash": {
            "$ref": "#/definitions/hashEntry"
          }
        },
        "allOf": [
          {
            "if": {
              "properties": {
                "kind": {
                  "const": "seal"
                }
              },
              "required": [
                "kind"
              ]
            },
            "then": {
              "required": [
                "serialNumber",
                "version"
              ],
              "not": {
                "anyOf": [
                  {
                    "required": [
                      "seq"
                    ]
                  },
                  {
                    "required": [
                      "fromSeq"
                    ]
                  },
                  {
                    "required": [
                      "toSeq"
                    ]
                  }
                ]
              }
            },
            "description": "TST-005: a seal token is keyed by the sealed BOM's serialNumber and version"
          },
          {
            "if": {
              "properties": {
                "kind": {
                  "const": "event"
                }
              },
              "required": [
                "kind"
              ]
            },
            "then": {
              "required": [
                "seq"
              ],
              "not": {
                "anyOf": [
                  {
                    "required": [
                      "serialNumber"
                    ]
                  },
                  {
                    "required": [
                      "version"
                    ]
                  },
                  {
                    "required": [
                      "fromSeq"
                    ]
                  },
                  {
                    "required": [
                      "toSeq"
                    ]
                  }
                ]
              }
            },
            "description": "TST-006: a per-event token is keyed by the custody event's seq"
          },
          {
            "if": {
              "properties": {
                "kind": {
                  "const": "batch"
                }
              },
              "required": [
                "kind"
              ]
            },
            "then": {
              "required": [
                "fromSeq",
                "toSeq"
              ],
              "not": {
                "anyOf": [
                  {
                    "required": [
                      "serialNumber"
                    ]
                  },
                  {
                    "required": [
                      "version"
                    ]
                  },
                  {
                    "required": [
                      "seq"
                    ]
                  }
                ]
              }
            },
            "description": "TST-006: a fallback batch token is keyed by the custody event range it covers"
          }
        ]
      }
    },
    "evidenceRecord": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "serialNumber",
        "version",
        "hash"
      ],
      "properties": {
        "serialNumber": {
          "type": "string",
          "pattern": "^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
        },
        "version": {
          "type": "integer",
          "minimum": 1
        },
        "hash": {
          "$ref": "#/definitions/hashEntry"
        }
      },
      "description": "ERS-004: the Evidence Record's hash, keyed by the finalised BOM's serialNumber and version. Optional because ERS-003 creates it only at the finalisation seal."
    }
  },
  "definitions": {
    "hashEntry": {
      "type": "object",
      "required": [
        "alg",
        "content"
      ],
      "properties": {
        "alg": {
          "type": "string",
          "enum": [
            "SHA-384",
            "SHA-512"
          ]
        },
        "content": {
          "type": "string",
          "pattern": "^[a-f0-9]{96}$|^[a-f0-9]{128}$"
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "alg": {
                "const": "SHA-384"
              }
            },
            "required": [
              "alg"
            ]
          },
          "then": {
            "properties": {
              "content": {
                "pattern": "^[a-f0-9]{96}$"
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "alg": {
                "const": "SHA-512"
              }
            },
            "required": [
              "alg"
            ]
          },
          "then": {
            "properties": {
              "content": {
                "pattern": "^[a-f0-9]{128}$"
              }
            }
          }
        }
      ]
    }
  }
}