{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://thehiveryiq.com/.well-known/schemas/model-change-v1.json",
  "title": "Model Change Notice Receipt, v1",
  "description": "Canonical schema for the Hive model change notice receipt, canonical type model.change. The receipt records that the configuration serving requests changed and how that serving configuration relates to the configuration a linked evaluation ran against.",
  "type": "object",
  "required": [
    "receipt_id",
    "payload_sha256",
    "sig_b64u",
    "key_id",
    "algorithm",
    "ts",
    "signed_body"
  ],
  "additionalProperties": false,
  "properties": {
    "receipt_id": { "type": "string", "pattern": "^r_model\\.change_[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",
        "notice_id",
        "profile",
        "serving",
        "announced_at",
        "deployment_scope",
        "notifier_commitment",
        "verdict",
        "salt_commitment",
        "boundary"
      ],
      "additionalProperties": false,
      "properties": {
        "receipt_type": { "type": "string", "const": "model.change" },
        "schema": { "type": "string", "const": "r1.0.0" },
        "notice_id": { "type": "string", "pattern": "^mc_[0-9a-f]{16,64}$" },
        "profile": {
          "type": "string",
          "description": "general is the ordinary form. care_setting additionally requires the evaluation binding, and is refused without it.",
          "enum": ["general", "care_setting"]
        },
        "serving": {
          "type": "object",
          "description": "The configuration that was serving requests before and after the recorded change.",
          "required": [
            "previous_configuration_commitment",
            "current_configuration_commitment",
            "changed_at",
            "change_class",
            "notice_class"
          ],
          "additionalProperties": false,
          "properties": {
            "previous_configuration_commitment": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
            "current_configuration_commitment": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
            "changed_at": {
              "type": "object",
              "required": ["utc", "drift_seconds"],
              "additionalProperties": false,
              "properties": {
                "utc": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,9})?Z$" },
                "drift_seconds": { "type": "integer", "minimum": 0, "maximum": 86400 }
              }
            },
            "change_class": {
              "type": "string",
              "enum": [
                "weights_changed",
                "decoding_changed",
                "prompt_scaffold_changed",
                "retrieval_corpus_changed",
                "tooling_changed",
                "routing_changed",
                "rollback"
              ]
            },
            "notice_class": {
              "type": "string",
              "description": "Recomputed by the service from announced_at against serving.changed_at under both declared drift bounds.",
              "enum": [
                "announced_before_change",
                "announced_after_change",
                "announced_without_instant"
              ]
            }
          }
        },
        "announced_at": {
          "type": "object",
          "description": "The instant the notice was presented. utc is null when the notifier recorded no instant.",
          "required": ["utc", "drift_seconds"],
          "additionalProperties": false,
          "properties": {
            "utc": {
              "type": ["string", "null"],
              "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,9})?Z$"
            },
            "drift_seconds": { "type": "integer", "minimum": 0, "maximum": 86400 }
          }
        },
        "validation_binding": {
          "type": "object",
          "description": "The evaluation receipt this change notice binds to, and the configuration that evaluation actually ran against. Required when profile is care_setting, optional when profile is general. When profile is care_setting the linked receipt must be of type eval.administration and its own gates are run at linked evidence depth 1.",
          "required": [
            "evaluation_receipt",
            "validated_configuration_commitment",
            "validated_against_commitment"
          ],
          "additionalProperties": false,
          "properties": {
            "evaluation_receipt": {
              "type": "object",
              "required": ["receipt_id", "receipt_type", "envelope_sha256", "issuance_instant"],
              "additionalProperties": false,
              "properties": {
                "receipt_id": { "type": "string", "pattern": "^r_[a-z0-9]+(\\.[a-z0-9]+)*_[0-9]{10,}_[0-9a-f]{12}$" },
                "receipt_type": { "type": "string", "pattern": "^eval(\\.[a-z0-9]+)+$" },
                "envelope_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
                "issuance_instant": {
                  "type": "object",
                  "required": ["utc", "drift_seconds"],
                  "additionalProperties": false,
                  "properties": {
                    "utc": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,9})?Z$" },
                    "drift_seconds": { "type": "integer", "minimum": 0, "maximum": 86400 }
                  }
                }
              }
            },
            "validated_configuration_commitment": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
            "asserted_independence_class": {
              "type": "string",
              "description": "Optional. The independence class the notifier asserts for the bound evaluation. When it is present the service compares it against the class recomputed from the linked evaluation receipt itself and refuses the notice when the two differ. When it is absent the class is reported from the linked receipt and nothing is asserted by the notice.",
              "enum": [
                "self_administered",
                "affiliated",
                "contracted",
                "independent",
                "undisclosed"
              ]
            },
            "validated_against_commitment": {
              "type": "string",
              "description": "Recomputed by the service from serving.current_configuration_commitment against validated_configuration_commitment.",
              "enum": [
                "serving_matches_validated",
                "serving_differs_from_validated",
                "validation_not_bound"
              ]
            }
          }
        },
        "deployment_scope": {
          "type": "object",
          "description": "The reach of the change, as presented by the notifier. The scope descriptor itself is carried only as a salted commitment.",
          "required": ["scope_commitment", "surface_count", "scope_class"],
          "additionalProperties": false,
          "properties": {
            "scope_commitment": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
            "surface_count": { "type": "integer", "minimum": 1 },
            "scope_class": {
              "type": "string",
              "enum": ["all_surfaces", "named_surfaces", "single_surface"]
            }
          }
        },
        "notifier_commitment": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
        "verdict": {
          "type": "string",
          "description": "Recomputed by the service from the notice class and the evaluation binding relation.",
          "enum": [
            "change_announced_and_evaluation_bound",
            "change_announced_evaluation_stale",
            "change_announced_evaluation_not_bound",
            "change_not_announced_before_serving"
          ]
        },
        "salt_commitment": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
        "boundary": {
          "type": "string",
          "minLength": 1,
          "const": "This receipt attests only that a party identified by a salted commitment recorded a change to the configuration serving requests, that the previous and the current configuration are distinct under their recorded commitments, how the recorded notice instant is placed against the recorded change instant under both declared drift bounds, and, when an evaluation receipt is bound to the notice, whether the configuration now serving is the same configuration that evaluation ran against. It does not attest that the current configuration performs better or worse than the previous one, that the evaluation was well designed, that the evaluation result was favorable, that the change was reviewed or approved by anyone, or that any output produced after the change was correct. The change class, the deployment scope, and the surface count are recorded as presented by the notifier and are not checked against any serving fleet here."
        }
      }
    }
  }
}
