{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://thehiveryiq.com/.well-known/schemas/proof-state-transition-v1.json",
  "title": "Proof State Transition v1, proof state transition container",
  "description": "Canonical schema for the Hive proof state transition container, canonical type proof.transition. Binds a predeclared transition table and its digest, an issuer registry digest, the independently signed admissible input receipts that triggered a run, the deterministic sequence of state transitions those inputs produced, an effect gate that names what was authorized to happen as a result, and a final state, into one Ed25519 signature over a recomputable payload_sha256. The receipt attests that the recorded transition sequence is exactly what the predeclared table would produce from the named inputs. It does not attest that the transition table itself encodes correct business logic, and it does not attest that any downstream effect actually occurred. This container's own size grows linearly with the number of admitted inputs; a fixed shape, bandwidth bounded proof of just the final state is available separately as the portable transition proof.",
  "type": "object",
  "required": [
    "receipt_id",
    "payload_sha256",
    "sig_b64u",
    "key_id",
    "algorithm",
    "ts",
    "signed_body"
  ],
  "additionalProperties": false,
  "properties": {
    "receipt_id": {
      "type": "string",
      "pattern": "^r_proof\\.transition_[0-9]{10,}_[0-9a-f]{12}$",
      "description": "Receipt identifier, r_proof.transition_<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."
    },
    "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 that assembled this container."
    },
    "algorithm": {
      "type": "string",
      "const": "Ed25519"
    },
    "ts": {
      "type": "integer",
      "minimum": 1000000000,
      "description": "Unix seconds at issuance. Covered by the signature."
    },
    "signed_body": {
      "type": "object",
      "description": "The signed transition record. Every field here is covered by payload_sha256.",
      "required": [
        "receipt_type",
        "schema",
        "run_id",
        "tenant_id",
        "transition_table",
        "issuer_registry",
        "inputs",
        "transitions",
        "final_state",
        "effect_gate",
        "boundary"
      ],
      "additionalProperties": false,
      "properties": {
        "receipt_type": { "type": "string", "const": "proof.transition" },
        "schema": { "type": "string", "const": "r1.0.0" },
        "run_id": { "type": "string", "minLength": 1, "maxLength": 256 },
        "tenant_id": { "type": "string", "minLength": 1, "maxLength": 256 },
        "transition_table": {
          "type": "object",
          "description": "The predeclared, fixed transition table this run was bound to before any input was admitted.",
          "required": ["table_id", "table_sha256", "states", "rules"],
          "additionalProperties": false,
          "properties": {
            "table_id": { "type": "string", "minLength": 1, "maxLength": 256 },
            "table_sha256": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$",
              "description": "Digest over the canonical serialisation of the full table, states plus rules, computed the same way payload_sha256 is computed."
            },
            "states": {
              "type": "array",
              "minItems": 2,
              "maxItems": 256,
              "items": { "type": "string", "minLength": 1, "maxLength": 128 }
            },
            "rules": {
              "type": "array",
              "minItems": 1,
              "maxItems": 4096,
              "description": "Deterministic rules. Each rule maps one from_state and one trigger to exactly one to_state. No two rules in this array may share the same from_state and trigger.",
              "items": {
                "type": "object",
                "required": ["from_state", "trigger", "to_state"],
                "additionalProperties": false,
                "properties": {
                  "from_state": { "type": "string", "minLength": 1, "maxLength": 128 },
                  "trigger": { "type": "string", "minLength": 1, "maxLength": 128 },
                  "to_state": { "type": "string", "minLength": 1, "maxLength": 128 }
                }
              }
            }
          }
        },
        "initial_state": { "type": "string", "minLength": 1, "maxLength": 128 },
        "issuer_registry": {
          "type": "object",
          "description": "Binds this run to the exact set of issuer keys and roles that were admissible when inputs were accepted. registry_sha256 is a canonical digest over admitted_issuers, so a verifier holding the same registry state can confirm this run used it, and a run cannot silently admit an issuer or role that was not declared here.",
          "required": ["registry_id", "registry_sha256", "admitted_issuers"],
          "additionalProperties": false,
          "properties": {
            "registry_id": { "type": "string", "minLength": 1, "maxLength": 256 },
            "registry_sha256": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$",
              "description": "Canonical digest over admitted_issuers, computed the same way payload_sha256 is computed."
            },
            "admitted_issuers": {
              "type": "array",
              "minItems": 1,
              "maxItems": 4096,
              "description": "Every key_id admitted to issue an input for this run, with the role it is admitted under.",
              "items": {
                "type": "object",
                "required": ["key_id", "role"],
                "additionalProperties": false,
                "properties": {
                  "key_id": { "type": "string", "pattern": "^did:(hive|web|key):[A-Za-z0-9._:%-]+$" },
                  "role": { "type": "string", "minLength": 1, "maxLength": 128 }
                }
              }
            }
          }
        },
        "inputs": {
          "type": "array",
          "minItems": 1,
          "maxItems": 4096,
          "description": "The admissible input receipts that drove this run, in the order they were applied. Each entry names an independently signed receipt rather than embedding one. This container's own size still grows linearly with the number of admitted inputs, since one array entry is recorded per input; a caller who needs a fixed size, bandwidth bounded artifact should request the separately exportable portable final state proof instead, which never grows with input count.",
          "items": {
            "type": "object",
            "required": ["input_id", "issuer_key_id", "admitted_role", "trigger", "receipt_sha256"],
            "additionalProperties": false,
            "properties": {
              "input_id": { "type": "string", "minLength": 1, "maxLength": 256 },
              "issuer_key_id": {
                "type": "string",
                "pattern": "^did:(hive|web|key):[A-Za-z0-9._:%-]+$",
                "description": "The key_id of the receipt that admitted this input. Distinct inputs are not required to share an issuer. Full verification checks that this key_id and admitted_role appear together in issuer_registry.admitted_issuers."
              },
              "admitted_role": {
                "type": "string",
                "minLength": 1,
                "maxLength": 128,
                "description": "The role this issuer was admitted under for this input. Must match a role registered for issuer_key_id in issuer_registry.admitted_issuers."
              },
              "trigger": { "type": "string", "minLength": 1, "maxLength": 128 },
              "receipt_sha256": {
                "type": "string",
                "pattern": "^[0-9a-f]{64}$",
                "description": "payload_sha256 of the independently signed admissible input receipt, binding this run to that exact receipt without embedding it. Full verification requires the caller to also supply the actual receipt envelope with this payload_sha256, signed by issuer_key_id, and checks its signature through the trust resolver; portable proof verification and schema level verification do not have access to that envelope and cannot make this check."
              }
            }
          }
        },
        "transitions": {
          "type": "array",
          "minItems": 1,
          "maxItems": 4096,
          "description": "The realised sequence of state transitions, one per input, in input order.",
          "items": {
            "type": "object",
            "required": ["input_id", "from_state", "trigger", "to_state"],
            "additionalProperties": false,
            "properties": {
              "input_id": { "type": "string", "minLength": 1, "maxLength": 256 },
              "from_state": { "type": "string", "minLength": 1, "maxLength": 128 },
              "trigger": { "type": "string", "minLength": 1, "maxLength": 128 },
              "to_state": { "type": "string", "minLength": 1, "maxLength": 128 }
            }
          }
        },
        "final_state": { "type": "string", "minLength": 1, "maxLength": 128 },
        "effect_gate": {
          "type": "object",
          "description": "What the final state authorizes to happen next. A closed gate authorizes nothing.",
          "required": ["status"],
          "additionalProperties": false,
          "properties": {
            "status": {
              "type": "string",
              "enum": ["open", "closed"],
              "description": "open means final_state authorizes the named effect. closed means no effect is authorized regardless of final_state."
            },
            "effect_id": { "type": "string", "minLength": 1, "maxLength": 256 },
            "authorized_for_state": { "type": "string", "minLength": 1, "maxLength": 128 }
          }
        },
        "boundary": {
          "type": "string",
          "const": "This receipt attests that the recorded transition sequence in signed_body is exactly what the predeclared transition table would produce from the named admissible input receipts, applied in the stated order, and that each input's issuer_key_id and admitted_role were declared in issuer_registry at the time this run was minted. Schema level and portable proof verification check the digest bindings only. Full verification additionally requires the caller to supply the actual input receipt envelopes and cryptographically verifies each one through the trust resolver before accepting it. This receipt does not attest that the transition table encodes correct business logic, that an input receipt not supplied for full verification is itself valid, or that any downstream effect named by effect_gate actually occurred. It also does not attest that issuer_registry is the complete or current set of issuers trusted outside this run, only the set this run declares itself bound to."
        }
      }
    }
  }
}
