{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://thehiveryiq.com/.well-known/schemas/perf-budget-v1.json",
  "title": "Bonded Performance Attestation, budget leg, v1",
  "description": "Canonical schema for the Hive performance budget receipt, canonical type perf.budget. This is the first of the two receipts that make up a Bonded Performance Attestation. It records a performance budget for a named subject and dimension, declared before the measurement window opens, and binds the thresholds, the minimum sample count, and the window into one Ed25519 signature over a recomputable payload_sha256. The budget alone asserts nothing about the outcome. It becomes evidence only when a perf.attestation receipt links to it by receipt_id and payload_sha256. The receipt does not create or confirm insurance coverage.",
  "type": "object",
  "required": [
    "receipt_id",
    "payload_sha256",
    "sig_b64u",
    "key_id",
    "algorithm",
    "ts",
    "signed_body"
  ],
  "additionalProperties": false,
  "properties": {
    "receipt_id": {
      "type": "string",
      "pattern": "^r_perf\\.budget_[0-9]{10,}_[0-9a-f]{12}$",
      "description": "Receipt identifier, r_perf.budget_<unix_seconds>_<12 hex chars>."
    },
    "payload_sha256": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}$",
      "description": "Lowercase hex SHA-256 over the canonical serialisation of signed_body. Canonical form is JSON with keys sorted and no whitespace, encoded UTF-8. A perf.attestation receipt binds to this exact value."
    },
    "sig_b64u": {
      "type": "string",
      "pattern": "^[A-Za-z0-9_-]{86}$",
      "description": "Base64url Ed25519 signature, no padding, over the ASCII string 'hive-receipt <receipt_id> <payload_sha256> <ts>'."
    },
    "key_id": {
      "type": "string",
      "pattern": "^did:(hive|web|key):[A-Za-z0-9._:%-]+$",
      "description": "Decentralised identifier of the signing key."
    },
    "algorithm": {
      "type": "string",
      "const": "Ed25519",
      "description": "Signature algorithm. Ed25519 for this schema version."
    },
    "ts": {
      "type": "integer",
      "minimum": 1000000000,
      "description": "Unix seconds at issuance. Covered by the signature."
    },
    "signed_body": {
      "type": "object",
      "description": "The signed budget declaration. Every field here is covered by payload_sha256.",
      "required": [
        "receipt_type",
        "schema",
        "budget_id",
        "tenant_id",
        "run_id",
        "subject",
        "dimension",
        "unit",
        "thresholds",
        "min_samples",
        "measurement_window",
        "declared_at",
        "boundary"
      ],
      "additionalProperties": false,
      "properties": {
        "receipt_type": {
          "type": "string",
          "const": "perf.budget"
        },
        "schema": {
          "type": "string",
          "enum": [
            "r1.0.0",
            "r1.1.0"
          ]
        },
        "budget_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256,
          "description": "Caller assigned identifier for this budget."
        },
        "tenant_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256
        },
        "run_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256,
          "description": "Identifier for the run this budget governs. The linked perf.attestation must carry the same run_id."
        },
        "subject": {
          "type": "object",
          "description": "The model or system the budget applies to.",
          "required": [
            "model_id",
            "provider"
          ],
          "additionalProperties": false,
          "properties": {
            "model_id": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256
            },
            "provider": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "endpoint": {
              "type": "string",
              "minLength": 1,
              "maxLength": 512
            },
            "cohort": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            }
          }
        },
        "dimension": {
          "type": "string",
          "enum": [
            "latency_ms_total",
            "time_to_first_token_ms",
            "latency_ms_per_output_token",
            "throughput_tokens_per_s",
            "error_rate",
            "false_positive_rate",
            "false_negative_rate",
            "unsupported_claim_rate",
            "refusal_rate",
            "availability"
          ],
          "description": "The single measured dimension this budget governs. The linked perf.attestation must declare the same dimension."
        },
        "unit": {
          "type": "string",
          "enum": [
            "ms",
            "tokens_per_s",
            "ratio"
          ],
          "description": "Unit for every threshold limit. Must be ms for the three latency dimensions and tokens_per_s for throughput_tokens_per_s."
        },
        "thresholds": {
          "type": "array",
          "minItems": 1,
          "maxItems": 8,
          "description": "One or more threshold clauses over the measured distribution. Every clause is evaluated and all must hold for the attestation outcome to be pass.",
          "items": {
            "type": "object",
            "required": [
              "metric",
              "comparator",
              "limit"
            ],
            "additionalProperties": false,
            "properties": {
              "metric": {
                "type": "string",
                "enum": [
                  "p50",
                  "p95",
                  "p99",
                  "max",
                  "mean"
                ]
              },
              "comparator": {
                "type": "string",
                "enum": [
                  "lte",
                  "gte"
                ],
                "description": "lte means the observed value must be at most limit. gte means at least limit."
              },
              "limit": {
                "type": "number"
              }
            }
          }
        },
        "min_samples": {
          "type": "integer",
          "minimum": 1,
          "description": "Minimum number of measurements required for the comparison to be decidable. An attestation with fewer samples must report indeterminate rather than pass or fail."
        },
        "measurement_window": {
          "type": "object",
          "description": "The window inside which measurements count. closes_at must not precede opens_at, and declared_at must not follow opens_at.",
          "required": [
            "opens_at",
            "closes_at"
          ],
          "additionalProperties": false,
          "properties": {
            "opens_at": {
              "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$"
            },
            "closes_at": {
              "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$"
            }
          }
        },
        "declared_at": {
          "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$",
          "description": "When the budget was declared. Must not follow measurement_window.opens_at. A budget declared after its own window opens is rejected."
        },
        "boundary": {
          "type": "string",
          "const": "This receipt records a performance budget declared before its measurement window opens. It does not assert that the budget was met, does not create or confirm insurance coverage, and does not attest that any output was correct."
        }
      }
    }
  }
}
