{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://thehiveryiq.com/.well-known/schemas/stream-attestation-v1.json",
  "title": "Stream Attestation v1, Foretoken streamed proof",
  "description": "Canonical schema for the Hive streamed-response proof receipt, canonical type stream.attestation, brand Foretoken. Binds a pre-commitment fixed before or at the moment the first streamed content leaves, an incremental digest chain folded over the run's units, and a terminal attestation sealed at the stream's ending, whichever kind of ending occurred. Covers only the digest of streamed content, never the content itself. final_chain_sha256 and emitted_unit_count are computed by the signer at mint time from the caller's own per-unit digest evidence, never trusted as caller-declared values, so a forged final chain cannot be minted. The signed receipt itself never carries the per-unit digest list, so its size stays fixed regardless of stream length; a party holding the same ordered per-unit digest list can independently refold it against this receipt at any later time to settle a dispute, without this receipt ever having buffered the content. It does not judge the quality of the streamed content, does not require a trusted execution environment, and a missing or absent terminal attestation for a run that has a pre-commitment is itself meaningful: it says the stream never reached a sealed ending.",
  "type": "object",
  "required": [
    "receipt_id",
    "payload_sha256",
    "sig_b64u",
    "key_id",
    "algorithm",
    "ts",
    "signed_body"
  ],
  "additionalProperties": false,
  "properties": {
    "receipt_id": {
      "type": "string",
      "pattern": "^r_stream\\.attestation_[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",
        "tenant_id",
        "pre_commitment",
        "termination",
        "boundary"
      ],
      "additionalProperties": false,
      "properties": {
        "receipt_type": { "type": "string", "const": "stream.attestation" },
        "schema": { "type": "string", "const": "r1.0.0" },
        "run_id": { "type": "string", "minLength": 1, "maxLength": 256 },
        "tenant_id": { "type": "string", "minLength": 1, "maxLength": 256 },
        "pre_commitment": {
          "type": "object",
          "description": "Fixed before, or at the same instant as, the first streamed content leaves. Binds request identity, model and build identity, and generation parameters, while the outcome is still unknown. A terminal attestation is only valid against a pre-commitment that already existed; there is no path to observe a finished response and then mint the commitment that would have covered it.",
          "required": ["committed_at", "request_sha256", "model", "chain_init_sha256"],
          "additionalProperties": false,
          "properties": {
            "committed_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": "Must not follow first_content_at when first_content_at is present."
            },
            "request_sha256": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$",
              "description": "Digest of the request that opened this run. Never the request content."
            },
            "model": {
              "type": "object",
              "required": ["model_id"],
              "additionalProperties": false,
              "properties": {
                "model_id": { "type": "string", "minLength": 1, "maxLength": 256 },
                "build_id": { "type": "string", "minLength": 1, "maxLength": 256 },
                "params_sha256": {
                  "type": "string",
                  "pattern": "^[0-9a-f]{64}$",
                  "description": "Digest of the generation parameters governing this run, for example temperature and sampling settings."
                }
              }
            },
            "chain_init_sha256": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$",
              "description": "The starting value of the incremental digest chain, fixed at pre-commitment time, before any content has been emitted. Every subsequent chain link is computed from this value."
            },
            "first_content_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 first streamed content actually left, if known and distinct from committed_at. Optional. Must not precede committed_at."
            }
          }
        },
        "chain": {
          "type": "object",
          "description": "The incremental digest chain over emitted content, folded delta by delta so the signed receipt never carries the full response. Optional at the schema level so a pre-commitment can exist on its own before any content has streamed, but required for any receipt claiming a non zero emitted_unit_count. final_chain_sha256 and emitted_unit_count are written by the signer at mint time from the caller's per-unit digest evidence, recomputed rather than accepted as declared, so neither field can be forged independently of the evidence the signer actually folded.",
          "required": ["algorithm", "unit", "final_chain_sha256", "emitted_unit_count"],
          "additionalProperties": false,
          "properties": {
            "algorithm": { "type": "string", "const": "sha256-fold-v1" },
            "unit": {
              "type": "string",
              "enum": ["token", "byte_chunk", "sse_event"],
              "description": "What each folded increment represents. Chosen by the producer; the chain is opaque to content in every case."
            },
            "final_chain_sha256": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$",
              "description": "The chain value after the last increment folded before this attestation was sealed. Computed as chain_i = SHA256(chain_(i-1) || unit_digest_i), starting from chain_init_sha256. Written by the signer from the caller's per-unit digest evidence at mint time, never accepted as a caller-declared value."
            },
            "emitted_unit_count": {
              "type": "integer",
              "minimum": 0,
              "description": "Number of units folded into final_chain_sha256. Written by the signer as the length of the caller's per-unit digest evidence at mint time, never accepted as a caller-declared value, so a truncated or extended chain cannot be declared independently of the evidence actually folded."
            },
            "evidence_sha256": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$",
              "description": "SHA-256 over the canonical JSON array of the ordered per-unit digests the signer folded to produce final_chain_sha256. The array itself is never stored in this receipt or returned by minting; the digest lets a party who later obtains the same ordered per-unit digest list from the producer's own records prove, by recomputation, that it is the same evidence set this receipt was minted from, before refolding it to check final_chain_sha256 with verifyStreamAttestationChain. Absent only for a receipt minted before this field existed."
            }
          }
        },
        "termination": {
          "type": "object",
          "description": "The sealed ending. Every kind of ending, not only a clean close, is a sealable outcome, because a stream that dies is still an event someone may have to account for.",
          "required": ["kind", "sealed_at"],
          "additionalProperties": false,
          "properties": {
            "kind": {
              "type": "string",
              "enum": ["completed", "client_cancelled", "upstream_error", "timeout"],
              "description": "completed: normal end of stream. client_cancelled: the caller ended the stream. upstream_error: the provider reported an error condition. timeout: the connection stopped without a clean close or explicit error."
            },
            "sealed_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": "Must not precede pre_commitment.committed_at."
            },
            "error_code": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "description": "Present only when kind is upstream_error."
            },
            "last_unit_index": {
              "type": "integer",
              "minimum": 0,
              "description": "Index of the last unit successfully folded before an abnormal ending. For a completed ending this equals chain.emitted_unit_count minus one when at least one unit was emitted."
            }
          }
        },
        "boundary": {
          "type": "string",
          "const": "This receipt attests that pre_commitment was fixed at committed_at, before or at first_content_at, and that chain.final_chain_sha256 and chain.emitted_unit_count, when present, were computed by the signer at mint time from the caller's ordered per-unit digest evidence, folded onto pre_commitment.chain_init_sha256 under the declared algorithm, never accepted as caller-declared values, sealed at termination.sealed_at under the declared termination.kind. It does not read, judge, or attest to the quality of the streamed content, it does not require a trusted execution environment, and it cannot be produced after the fact against content that already existed, because the pre_commitment necessarily predates the content it covers. This receipt alone does not let an independent verifier replay the fold, because the per-unit evidence is never stored in it; a party later given the same ordered per-unit digest list by the producer's own records can independently recompute the fold against chain.evidence_sha256 and chain.final_chain_sha256, and a truncated, extended, edited, or reordered unit list will not reproduce either value. A run with a pre_commitment and no terminal attestation is not silent by design; the absence itself indicates the stream never reached a sealed ending."
        }
      }
    }
  }
}
