{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://thehiveryiq.com/.well-known/schemas/backtest-pairing-v1.json",
  "title": "Back-test Pairing Receipt, v1",
  "description": "Canonical schema for the Hive back-test pairing receipt, canonical type backtest.pairing. It records a pairing rule fixed before the period it governs, salted commitments to the evaluation set and trade set, and the pair count, pairing digest, and distance band counts computed from those inputs under that rule. A verifier given the same inputs recomputes every finding and refuses a mismatch.",
  "type": "object",
  "required": [
    "receipt_id",
    "payload_sha256",
    "sig_b64u",
    "key_id",
    "algorithm",
    "ts",
    "signed_body"
  ],
  "additionalProperties": false,
  "properties": {
    "receipt_id": {
      "type": "string",
      "pattern": "^r_backtest[.]pairing_[0-9]{10,}_[0-9a-f]{12}$"
    },
    "payload_sha256": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}$"
    },
    "sig_b64u": {
      "type": "string",
      "pattern": "^[A-Za-z0-9_-]{86}$"
    },
    "key_id": {
      "type": "string",
      "pattern": "^did:(hive|web|key):[A-Za-z0-9._:%-]+$"
    },
    "algorithm": {
      "type": "string",
      "const": "Ed25519"
    },
    "ts": {
      "type": "integer",
      "minimum": 1000000000
    },
    "signed_body": {
      "type": "object",
      "required": [
        "receipt_type",
        "schema",
        "run_id",
        "salt_commitment",
        "pairing_rule",
        "rule_commitment",
        "period",
        "evaluation_set_commitment",
        "trade_set_commitment",
        "evaluation_count",
        "trade_count",
        "paired_count",
        "unpaired_count",
        "pairing_digest",
        "bands",
        "boundary"
      ],
      "additionalProperties": false,
      "properties": {
        "receipt_type": {
          "type": "string",
          "const": "backtest.pairing"
        },
        "schema": {
          "type": "string",
          "const": "r1.0.0"
        },
        "run_id": {
          "type": "string",
          "pattern": "^bt_[0-9a-z][0-9a-z._-]{0,47}$"
        },
        "salt_commitment": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$"
        },
        "pairing_rule": {
          "type": "object",
          "required": [
            "rule_id",
            "window_seconds",
            "size_floor",
            "band_edges_bps",
            "min_reported_group",
            "committed_at"
          ],
          "additionalProperties": false,
          "properties": {
            "rule_id": {
              "type": "string",
              "pattern": "^rule_[0-9a-z][0-9a-z._-]{0,47}$"
            },
            "window_seconds": {
              "type": "integer",
              "minimum": 0,
              "maximum": 2592000,
              "description": "Longest gap after an evaluation in which a trade may be paired. A recorded zero is accepted here and refused by RULE_BOUNDS."
            },
            "size_floor": {
              "type": "integer",
              "minimum": 0,
              "maximum": 1000000000000,
              "description": "Smallest trade size, in the recording party's size unit, that may be paired."
            },
            "band_edges_bps": {
              "type": "array",
              "minItems": 1,
              "maxItems": 32,
              "items": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1000000
              },
              "description": "Upper edges of the distance bands in basis points. Must be strictly ascending and positive, checked by RULE_BOUNDS."
            },
            "min_reported_group": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100000,
              "description": "A band with at least one and fewer than this many pairs is withheld."
            },
            "committed_at": {
              "type": "object",
              "required": [
                "utc",
                "drift_seconds"
              ],
              "additionalProperties": false,
              "properties": {
                "utc": {
                  "type": "string",
                  "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}([.][0-9]{1,9})?Z$"
                },
                "drift_seconds": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 86400
                }
              }
            }
          }
        },
        "rule_commitment": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$"
        },
        "period": {
          "type": "object",
          "required": [
            "start",
            "end"
          ],
          "additionalProperties": false,
          "properties": {
            "start": {
              "type": "object",
              "required": [
                "utc",
                "drift_seconds"
              ],
              "additionalProperties": false,
              "properties": {
                "utc": {
                  "type": "string",
                  "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}([.][0-9]{1,9})?Z$"
                },
                "drift_seconds": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 86400
                }
              }
            },
            "end": {
              "type": "object",
              "required": [
                "utc",
                "drift_seconds"
              ],
              "additionalProperties": false,
              "properties": {
                "utc": {
                  "type": "string",
                  "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}([.][0-9]{1,9})?Z$"
                },
                "drift_seconds": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 86400
                }
              }
            }
          }
        },
        "evaluation_set_commitment": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$"
        },
        "trade_set_commitment": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$"
        },
        "evaluation_count": {
          "type": "integer",
          "minimum": 0
        },
        "trade_count": {
          "type": "integer",
          "minimum": 0
        },
        "paired_count": {
          "type": "integer",
          "minimum": 0
        },
        "unpaired_count": {
          "type": "integer",
          "minimum": 0
        },
        "pairing_digest": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$"
        },
        "bands": {
          "type": "array",
          "minItems": 2,
          "maxItems": 33,
          "items": {
            "type": "object",
            "required": [
              "band_index",
              "lower_bps",
              "upper_bps",
              "count",
              "withheld"
            ],
            "additionalProperties": false,
            "properties": {
              "band_index": {
                "type": "integer",
                "minimum": 0
              },
              "lower_bps": {
                "type": "integer",
                "minimum": 0
              },
              "upper_bps": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0
              },
              "count": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0
              },
              "withheld": {
                "type": "boolean"
              }
            }
          }
        },
        "boundary": {
          "type": "string",
          "minLength": 1,
          "const": "Hive records and checks; it does not decide, block, enforce, or sit in the access path. This receipt shows that a pairing rule with the recorded window, size floor, band edges, and smallest reported group was recorded at the recorded commitment instant, before the recorded period, and that under that rule the recorded evaluation set and trade set, both presented only as salted commitments, produce the recorded pair count, unpaired count, pairing digest, and band counts, with groups smaller than the recorded floor withheld. It shows what was recorded and when, not that it was correct. It does not establish that any evaluation was accurate or fair, that the trades are complete or representative, that the rule is suitable for any purpose, or that any reader accepted the result. Prices and identifiers never enter this receipt, and the inputs are presented as reported by the recording party."
        }
      }
    }
  }
}