{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://plenaverify.com/vrx1-refusal-receipt.schema.json",
  "title": "PLENA VRX-1 Refusal Receipt v1",
  "description": "Schema for VRX-1 Receipt Type 4, the Refusal Receipt. Records that an institution or a person declined a request, application, signature, payment, consent, submission, or AI output, with the reason named and a correction or appeal path stated. The receipt is self-attested by its creator and tamper-evident via SHA-256 over the canonical JSON; it is not signed by an issuer key, not externally anchored to a public timestamp, and not certified by PLENA or any third party. PLENA does not provide legal advice and does not adjudicate whether a refusal is lawful or proportionate. Acceptance is decided by the receiving party. The schema is the canonical contract for VRX-1 Refusal Receipts produced by the d19.81 reference implementation at vrx1-refusal-receipt.html.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "vrx1_version",
    "schema_version",
    "receipt_id",
    "receipt_type",
    "created_at",
    "refusal_mode",
    "refuser_name_or_role",
    "subject_of_refusal",
    "counterparty",
    "refusal_date",
    "refusal_reason_summary",
    "refusal_reason_codes",
    "privacy_level",
    "verification_url",
    "integrity_note",
    "hash"
  ],
  "properties": {
    "vrx1_version": {
      "type": "string",
      "const": "1.0-d19.81-refusal-receipt-reference",
      "description": "VRX-1 reference-implementation version string. Bound to the d19.81 reference implementation; future implementations should bump this string and the corresponding schema_version together."
    },
    "schema_version": {
      "type": "string",
      "const": "vrx1.refusal-receipt.v1",
      "description": "Stable schema identifier for VRX-1 Refusal Receipt v1. A later major revision would publish a v2 schema at a distinct identifier."
    },
    "receipt_id": {
      "type": "string",
      "pattern": "^PLENA-RFR-[0-9]{8}-[A-F0-9]{4}$",
      "description": "Unique identifier for this receipt. Format: PLENA-RFR-<YYYYMMDD>-<4 uppercase hex>. The date segment uses UTC at receipt creation. The hex suffix is generated by the creating device. Note: this RFR namespace is distinct from the legacy PLENA-RR-* namespace used by founder-activation candidate receipts; the two namespaces do not collide."
    },
    "receipt_type": {
      "type": "string",
      "const": "REFUSAL_RECEIPT",
      "description": "Receipt type discriminator. Always REFUSAL_RECEIPT for this schema."
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "description": "ISO-8601 date-time string from the device that built the receipt. The timestamp is not anchored to an external clock or registry."
    },
    "refusal_mode": {
      "type": "string",
      "enum": ["institutional", "personal"],
      "description": "Refusal mode discriminator. 'institutional' = an organisation refuses a request or application. 'personal' = a person refuses to sign, pay, consent, submit, agree, delete, share, or accept. These correspond to the two locked outputs of the Rights, Risk & Protection Suite: Institutional Refusal Receipt and Personal Refusal Receipt."
    },
    "refuser_name_or_role": {
      "type": "string",
      "minLength": 1,
      "description": "Name or role of the refusing party. A role title or pseudonym may be used when the public receipt should not name the refuser directly."
    },
    "refuser_org_or_context": {
      "type": ["string", "null"],
      "description": "Refuser's institution or context. Optional. For institutional refusals, typically the organisation name. For personal refusals, may be set to null or to 'personal capacity'."
    },
    "subject_of_refusal": {
      "type": "string",
      "minLength": 1,
      "description": "Free-text description of what was refused. Example: 'Application for admission to the 2026 intake.' or 'Request to sign NDA dated 2026-05-10.' or 'AI-generated screening recommendation.'"
    },
    "counterparty": {
      "type": "string",
      "minLength": 1,
      "description": "Free-text identifier for the person, institution, or party affected by the refusal. May be a pseudonymous reference when the public receipt should not name the counterparty directly."
    },
    "refusal_date": {
      "type": "string",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
      "description": "ISO-8601 date string (YYYY-MM-DD) for the date the refusal occurred."
    },
    "refusal_reason_summary": {
      "type": "string",
      "minLength": 1,
      "description": "One-sentence summary of why the refusal occurred. The receipt does not assert that the reason is sound; it only records what the refuser attested."
    },
    "refusal_reason_codes": {
      "type": "array",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "type": "string",
        "enum": [
          "MISSING_EVIDENCE",
          "EXPIRED_DOCUMENT",
          "UNSUPPORTED_CLAIM",
          "UNCLEAR_CONSENT",
          "UNSAFE_REQUEST",
          "INSUFFICIENT_AUTHORITY",
          "AI_OUTPUT_NOT_ACCEPTED",
          "CROSS_BORDER_DOCUMENT_NOT_READY",
          "INCOMPLETE_APPLICATION",
          "UNRESOLVED_COUNTERPARTY_RISK",
          "UNCLEAR_SERVICE_OBLIGATION",
          "SUSPICIOUS_CONTRACT",
          "EXPLOITATIVE_REQUEST",
          "AI_AGENT_OVERREACH",
          "OTHER"
        ]
      },
      "description": "One or more structured reason codes for the refusal. Codes are drawn from the locked Part 2.13 use-case list in the d19.75 strategic architecture lock. Multiple codes may apply to a single refusal. Use 'OTHER' when no listed code fits; the prose summary should then explain the reason in detail."
    },
    "missing_or_required_items": {
      "type": "array",
      "items": { "type": "string", "minLength": 1 },
      "description": "Ordered list of items that, if supplied or corrected, would change the outcome. Each item is a free-text description. The array may be empty when no specific missing items apply."
    },
    "correction_path": {
      "type": ["string", "null"],
      "description": "Free-text description of what the counterparty can do to address the refusal. Per round-practice the receipt should provide either a correction_path or an appeal_path (or both); enforcement of that requirement is left to the application layer."
    },
    "appeal_path": {
      "type": ["string", "null"],
      "description": "Free-text description of how the counterparty can appeal. Should include a contact address, deadline window, and process step where applicable. Per round-practice the receipt should provide either a correction_path or an appeal_path (or both)."
    },
    "escalation_path": {
      "type": ["string", "null"],
      "description": "Optional further escalation route beyond the first-instance appeal. For example, an ombudsperson, regulator complaint route, or external dispute-resolution body."
    },
    "linked_submission_receipt_id": {
      "type": ["string", "null"],
      "description": "Optional cross-reference to a prior VRX-1 Submission Receipt the refusal addresses. Format: PLENA-SUB-<YYYYMMDD>-<4 hex> when present."
    },
    "linked_human_review_receipt_id": {
      "type": ["string", "null"],
      "description": "Optional cross-reference to a prior VRX-1 Human Review Receipt that documents the review behind the refusal. Format: PLENA-HRR-<YYYYMMDD>-<4 hex> when present. Recommended when an institutional refusal follows a documented human-review process."
    },
    "refuser_notes": {
      "type": ["string", "null"],
      "description": "Optional free-text notes from the refusing party."
    },
    "privacy_level": {
      "type": "string",
      "enum": ["restricted", "private", "public"],
      "description": "Privacy classification of the receipt body. 'restricted' = share by link, not publicly listed. 'private' = for personal/institutional records only. 'public' = safe for a public log when no private data is inside."
    },
    "supersedes": {
      "type": ["string", "null"],
      "description": "Optional receipt_id of a prior receipt that this one corrects or replaces."
    },
    "verification_url": {
      "type": "string",
      "minLength": 1,
      "description": "URL where the receipt can be opened in the VRX-1 Refusal Receipt reference implementation Verify panel. Typically ends with vrx1-refusal-receipt.html#verify."
    },
    "integrity_note": {
      "type": "string",
      "minLength": 1,
      "description": "Plain-language statement of the receipt's truth boundary. Asserts that the receipt is self-attested by its creator and tamper-evident via SHA-256, and explicitly denies signing, external anchoring, or third-party certification."
    },
    "hash": {
      "type": "string",
      "pattern": "^sha256:[0-9a-f]{64}$",
      "description": "SHA-256 hex digest, prefixed with 'sha256:', computed over the canonical JSON of all receipt fields except the 'hash' field itself. Canonicalisation: object keys are recursively sorted; no whitespace; strings are JSON-encoded; numbers use JSON number form; null is rendered as the literal null; non-finite numbers are rendered as null."
    }
  }
}
