{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://thehiveryiq.com/.well-known/schemas/custody-presentation-v1.json",
  "title": "Custody Presentation Receipt, v1",
  "description": "Canonical schema for the Hive custody presentation receipt, canonical type custody.presentation. One organization signs one presentation over the artifact commitment and the handoff terms it is prepared to release or to receive. A presentation on its own establishes no movement. It is an input to a custody.handoff receipt, which exists only when two presentations from two different keys carry the same terms.",
  "type": "object",
  "required": [
    "receipt_id",
    "payload_sha256",
    "sig_b64u",
    "key_id",
    "algorithm",
    "ts",
    "signed_body"
  ],
  "additionalProperties": false,
  "properties": {
    "receipt_id": {
      "type": "string",
      "pattern": "^r_custody[.]presentation_[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",
        "party_commitment",
        "party_role",
        "artifact_commitment",
        "artifact_digest",
        "purpose_class",
        "retention_policy_id",
        "effective_at",
        "instant",
        "boundary"
      ],
      "additionalProperties": false,
      "properties": {
        "receipt_type": {
          "type": "string",
          "const": "custody.presentation"
        },
        "schema": {
          "type": "string",
          "const": "r1.0.0"
        },
        "party_commitment": {
          "type": "string",
          "description": "Salted commitment over the presenting organization identifier. The salt is disclosed to the verifier in the request and never appears in this body.",
          "pattern": "^[0-9a-f]{64}$"
        },
        "party_role": {
          "type": "string",
          "enum": [
            "releasing",
            "receiving"
          ]
        },
        "artifact_commitment": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$"
        },
        "artifact_digest": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$"
        },
        "purpose_class": {
          "type": "string",
          "enum": [
            "care_documentation",
            "coding_review",
            "billing_submission",
            "quality_measurement",
            "records_request"
          ]
        },
        "retention_policy_id": {
          "type": "string",
          "pattern": "^rp_[0-9a-z][0-9a-z._-]{0,47}$"
        },
        "effective_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$"
        },
        "instant": {
          "type": "object",
          "description": "When this side signed its presentation, with the drift bound it declares for its own clock.",
          "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
            }
          }
        },
        "boundary": {
          "type": "string",
          "minLength": 1,
          "const": "This presentation attests only that the named signing key produced a signature over the party commitment, the party role, the artifact commitment, the artifact digest, the purpose class, the retention policy identifier, the effective instant, and the recorded instant carried in this body. It does not attest that the signing organization holds the artifact, that it was authorized to release or to receive the artifact, that the artifact content is accurate, that the counterparty presented the same terms, or that any movement occurred. A presentation on its own establishes no custody. Custody is recorded only when a second presentation signed under a different key carries the same terms and a custody.handoff receipt records the relation between the two."
        }
      }
    }
  }
}
