{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://thehiveryiq.com/.well-known/schemas/absence-scope-v1.json",
  "title": "Scoped Absence Assertion v1",
  "description": "Scoped Absence Assertion receipt. Saying a document does not contain something is only meaningful if you say where you looked, what you looked for, with what engine, and at what threshold, so all of that is inside the signed body, bounded to one box in the pixel space of a committed render profile. The service recomputes the predicate digest over the canonical predicate and its version. A party that evaluates the same box at a different threshold gets an off threshold indeterminate result rather than a result that contradicts the assertion. It does not run the search; negative_independently_reproduced_by_service is fixed to false, and the assertion is scoped to the committed box and never to the whole document.",
  "type": "object",
  "required": [
    "receipt_id",
    "payload_sha256",
    "sig_b64u",
    "key_id",
    "algorithm",
    "ts",
    "signed_body"
  ],
  "additionalProperties": false,
  "properties": {
    "receipt_id": {
      "type": "string",
      "pattern": "^r_absence\\.scope_[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",
        "assertion_id",
        "evidence_digest_sha256",
        "recorded_at",
        "verdict",
        "boundary",
        "render_profile_digest_sha256",
        "page_index",
        "box_x",
        "box_y",
        "box_width",
        "box_height",
        "predicate_kind",
        "predicate_canonical_form",
        "predicate_version",
        "predicate_digest_sha256",
        "extraction_engine_ref",
        "model_version_commitment_sha256",
        "detection_threshold",
        "threshold_scale_ref",
        "searched_at",
        "result"
      ],
      "additionalProperties": false,
      "properties": {
        "receipt_type": {
          "type": "string",
          "const": "absence.scope"
        },
        "schema": {
          "type": "string",
          "const": "r1.0.0"
        },
        "assertion_id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256,
          "pattern": "^[A-Za-z0-9._:-]{1,256}$"
        },
        "evidence_digest_sha256": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$",
          "description": "SHA-256 of the caller-held evidence bundle this receipt attests was recorded. The service never receives or inspects the underlying evidence, only its digest."
        },
        "recorded_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$"
        },
        "verdict": {
          "type": "object",
          "description": "Service-computed honesty boundary fields. Never caller overridable; recomputed and checked at verify time.",
          "required": [
            "negative_independently_reproduced_by_service",
            "assertion_scoped_to_committed_box",
            "predicate_digest_recomputed",
            "predicate_digest_recomputes",
            "box_area_pixels",
            "search_precedes_this_receipt",
            "negative_asserted"
          ],
          "additionalProperties": false,
          "properties": {
            "negative_independently_reproduced_by_service": {
              "type": "boolean",
              "const": false
            },
            "assertion_scoped_to_committed_box": {
              "type": "boolean",
              "const": true
            },
            "predicate_digest_recomputed": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$",
              "description": "Digest the service recomputed over the canonical predicate, its kind, and its version."
            },
            "predicate_digest_recomputes": {
              "type": "boolean"
            },
            "box_area_pixels": {
              "type": "integer",
              "minimum": 0
            },
            "search_precedes_this_receipt": {
              "type": "boolean"
            },
            "negative_asserted": {
              "type": "boolean"
            }
          }
        },
        "boundary": {
          "type": "string",
          "const": "Scoped Absence Assertion receipt. Saying a document does not contain something is only meaningful if you say where you looked, what you looked for, with what engine, and at what threshold, so all of that is inside the signed body, bounded to one box in the pixel space of a committed render profile. The service recomputes the predicate digest over the canonical predicate and its version. A party that evaluates the same box at a different threshold gets an off threshold indeterminate result rather than a result that contradicts the assertion. It does not run the search; negative_independently_reproduced_by_service is fixed to false, and the assertion is scoped to the committed box and never to the whole document."
        },
        "render_profile_digest_sha256": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$",
          "description": "Profile the box coordinates are expressed against."
        },
        "page_index": {
          "type": "integer",
          "minimum": 0,
          "maximum": 65535
        },
        "box_x": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1000000
        },
        "box_y": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1000000
        },
        "box_width": {
          "type": "integer",
          "minimum": 1,
          "maximum": 1000000
        },
        "box_height": {
          "type": "integer",
          "minimum": 1,
          "maximum": 1000000
        },
        "predicate_kind": {
          "type": "string",
          "enum": [
            "literal_pattern",
            "regular_expression",
            "field_class",
            "signature_mark",
            "stamp_class"
          ]
        },
        "predicate_canonical_form": {
          "type": "string",
          "minLength": 1,
          "maxLength": 4096,
          "description": "Canonical form of what was searched for."
        },
        "predicate_version": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256,
          "description": "Version that defines how the canonical form is interpreted."
        },
        "predicate_digest_sha256": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$",
          "description": "Digest the caller declares over the canonical predicate, its kind, and its version."
        },
        "extraction_engine_ref": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256,
          "description": "Engine that performed the search."
        },
        "model_version_commitment_sha256": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$",
          "description": "Commitment to the model version of that engine."
        },
        "detection_threshold": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "Threshold at or above which the engine would have reported a match."
        },
        "threshold_scale_ref": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256,
          "description": "Named and versioned scale for that threshold."
        },
        "searched_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": "Instant the search ran."
        },
        "result": {
          "type": "string",
          "enum": [
            "no_match_found",
            "match_found",
            "indeterminate"
          ]
        }
      }
    }
  }
}
