{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://grip.foxora.dev/schema/1.0-draft.2/receipt.schema.json",
  "title": "GRIP Receipt",
  "description": "One act, one decision, one Receipt, hash-linked to the previous Receipt in the chain. §4.3.3.",
  "allOf": [{ "$ref": "common.schema.json#/$defs/envelope" }],
  "type": "object",
  "required": ["grip", "type", "id", "iss", "actor", "act", "decision", "cost", "iat", "sig"],
  "properties": {
    "type": { "const": "receipt" },
    "prev": { "$ref": "common.schema.json#/$defs/digest", "description": "Previous Receipt in this Mandate's chain. Absent on the first Receipt." },
    "actor": { "$ref": "common.schema.json#/$defs/keyref" },
    "act": {
      "type": "object",
      "required": ["verb", "resource"],
      "properties": {
        "verb": { "$ref": "common.schema.json#/$defs/verb" },
        "resource": { "type": "string", "minLength": 1 },
        "input_digest": { "$ref": "common.schema.json#/$defs/digest" },
        "actor_sig": { "$ref": "common.schema.json#/$defs/sig", "description": "GRIP-2+: detached JWS by the actor key over (grant id ‖ canonical act). §4.3.2." }
      },
      "additionalProperties": false
    },
    "context": { "$ref": "common.schema.json#/$defs/digest", "description": "Context Envelope this model-driven act was decided from. Required at GRIP-3. §4.6 rule 7." },
    "approval": { "$ref": "common.schema.json#/$defs/sig", "description": "stop.approve only, signature mode: approver's detached JWS over (stop.id ‖ act_digest). §4.3.4." },
    "token": { "type": "string", "description": "stop.approve only, token mode: the disclosed completion token. §4.3.4." },
    "decision": {
      "type": "object",
      "required": ["result"],
      "properties": {
        "result": { "enum": ["allowed", "denied"] },
        "reason": { "type": "string", "pattern": "^GRIP_DENY_[A-Z_]+$" },
        "subcode": { "type": "string", "pattern": "^X_[A-Z0-9]+_[A-Z0-9_]+$", "description": "Required with GRIP_DENY_POLICY. §4.4." },
        "prose": { "type": "string" },
        "stop": { "$ref": "common.schema.json#/$defs/digest" },
        "crit_object": {
          "type": "object",
          "required": ["object", "path"],
          "properties": { "object": { "$ref": "common.schema.json#/$defs/digest" }, "path": { "type": "string" } },
          "additionalProperties": false,
          "description": "Required with GRIP_DENY_UNKNOWN_CRIT. §4.3.3."
        }
      },
      "additionalProperties": false,
      "allOf": [
        { "if": { "properties": { "result": { "const": "denied" } }, "required": ["result"] },
          "then": { "required": ["reason"] } },
        { "if": { "properties": { "reason": { "const": "GRIP_DENY_POLICY" } }, "required": ["reason"] },
          "then": { "required": ["subcode", "prose"] } },
        { "if": { "properties": { "reason": { "const": "GRIP_DENY_UNKNOWN_CRIT" } }, "required": ["reason"] },
          "then": { "required": ["crit_object"] } }
      ]
    },
    "gate": { "$ref": "common.schema.json#/$defs/digest", "description": "Outcome Receipts only: the paired gate Receipt. §4.3.3." },
    "outcome": {
      "type": "object",
      "required": ["status"],
      "properties": {
        "status": { "enum": ["ok", "failed", "interrupted"] },
        "effects": { "type": "array", "items": { "type": "string" } },
        "output_digest": { "$ref": "common.schema.json#/$defs/digest" },
        "resolved": {
          "oneOf": [
            { "type": "null" },
            { "type": "object",
              "required": ["provider", "model", "boundary"],
              "properties": {
                "provider": { "type": "string" },
                "model": { "type": "string" },
                "boundary": { "type": "array", "items": { "type": "string" } }
              },
              "additionalProperties": false }
          ],
          "description": "model.call outcome Receipts MUST record resolved provider, model, and matched boundary. §4.4."
        }
      },
      "additionalProperties": false
    },
    "cost": { "$ref": "common.schema.json#/$defs/budget" }
  },
  "dependentRequired": { "outcome": ["gate"] }
}
