{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://thehiveryiq.com/.well-known/schemas/directory-state-v1.json",
  "title": "Directory State Receipt, v1",
  "description": "Canonical schema for the Hive directory state receipt, canonical type directory.state.",
  "type": "object",
  "required": [
    "receipt_id",
    "payload_sha256",
    "sig_b64u",
    "key_id",
    "algorithm",
    "ts",
    "signed_body"
  ],
  "additionalProperties": false,
  "properties": {
    "receipt_id": { "type": "string", "pattern": "^r_directory\\.state_[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",
        "directory_state",
        "boundary"
      ],
      "additionalProperties": false,
      "properties": {
        "receipt_type": { "type": "string", "const": "directory.state" },
        "schema": { "type": "string", "const": "r1.0.0" },
        "directory_state": {
          "type": "object",
          "required": [
            "observation_id",
            "recorded_at",
            "directory",
            "observed_at",
            "time_reference",
            "observed_drift_ms",
            "drift_class",
            "content_digest",
            "key_identifier_count",
            "key_commitments",
            "key_identifier_set_digest",
            "queried_key_commitment",
            "presence_verdict",
            "observer_role",
            "evidence_access_class",
            "salt_commitment"
          ],
          "additionalProperties": false,
          "properties": {
            "observation_id": { "type": "string", "pattern": "^ds_[0-9a-f]{16,64}$" },
            "recorded_at": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,9})?Z$" },
            "directory": {
              "type": "object",
              "required": ["directory_id", "directory_url", "directory_class"],
              "additionalProperties": false,
              "properties": {
                "directory_id": { "type": "string", "pattern": "^dy_[0-9a-z_]{1,48}$" },
                "directory_url": { "type": "string", "pattern": "^https://[A-Za-z0-9._~:/?#@!$&'()*+,;=%-]{3,512}$" },
                "directory_class": { "type": "string", "enum": ["jwks_well_known", "payment_network_key_directory", "signature_agent_directory", "credential_provider_jwks"] }
              }
            },
            "observed_at": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,9})?Z$" },
            "time_reference": {
              "type": "object",
              "required": ["reference_id", "reference_digest", "drift_bound_ms"],
              "additionalProperties": false,
              "properties": {
                "reference_id": { "type": "string", "pattern": "^tr_[0-9a-z_]{1,48}$" },
                "reference_digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
                "drift_bound_ms": { "type": "integer", "minimum": 1, "maximum": 86400000 }
              }
            },
            "observed_drift_ms": { "type": "integer", "minimum": 0, "maximum": 86400000 },
            "drift_class": { "type": "string", "enum": ["within_declared_bound", "exceeds_declared_bound"] },
            "content_digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
            "key_identifier_count": { "type": "integer", "minimum": 0, "maximum": 4096 },
            "key_commitments": {
              "type": "array",
              "minItems": 0,
              "maxItems": 4096,
              "items": {
                "type": "object",
                "required": ["identifier_commitment", "key_commitment", "key_class"],
                "additionalProperties": false,
                "properties": {
                  "identifier_commitment": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
                  "key_commitment": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
                  "key_class": { "type": "string", "enum": ["ed25519_verification", "ecdsa_p256_verification", "rsa_verification", "unrecognised"] }
                }
              }
            },
            "key_identifier_set_digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
            "queried_key_commitment": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
            "presence_verdict": { "type": "string", "enum": ["queried_key_present", "queried_key_absent"] },
            "observer_role": { "type": "string", "const": "non_publishing_observer" },
            "evidence_access_class": { "type": "string", "enum": ["confidential_independent", "issuer_only", "public_commitment_only"] },
            "salt_commitment": { "type": "string", "pattern": "^[0-9a-f]{64}$" }
          }
        },
        "boundary": {
          "type": "string",
          "minLength": 1,
          "const": "This receipt attests only that a named observer retrieved a named directory at a named URL at an instant placed against a declared external time reference with a declared drift bound, that the retrieved content hashed to the stated content digest, that the stated set of key identifiers was present with their stated per key commitments, and that the presence or absence of one queried key identifier was recomputed by this service from the committed content rather than supplied by the caller. It does not attest that the directory content is correct. It does not attest that the publisher is entitled to publish it. It does not attest that any key in it is validly issued or under the custody of any party. It does not attest that a key absent from it does not exist elsewhere. It does not attest that the observer saw the same content another observer would have seen at the same instant. It does not attest that any signature made under any key was authorised. It does not decide whether any message should have been blocked."
        }
      }
    }
  }
}
