{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/BichengWang/ai-decision-system/schema/decisioncontrol/record.v3.json",
  "title": "decision-control exported decision record, schema 3",
  "$comment": "sha256 covers /record, canonicalized as python-json-v1 (json.dumps sort_keys, separators (',',':'), ensure_ascii=False, UTF-8). record.policy_sha256 covers record.policy with the same canonicalization. Not expressible here: the replay rules (recomputed verdict, lifecycle consistency, event times, reviewer authorization against the frozen policy, proposer cannot review or cancel a REVIEW decision, review destinations subset of allowed destinations).",
  "type": "object",
  "properties": {
    "record": {
      "type": "object",
      "properties": {
        "schema_version": {
          "const": 3
        },
        "id": {
          "$ref": "#/$defs/uuid"
        },
        "created_at": {
          "$ref": "#/$defs/timestamp"
        },
        "recommendation": {
          "$ref": "#/$defs/recommendation"
        },
        "ticket": {
          "$ref": "#/$defs/ticket"
        },
        "policy": {
          "$ref": "#/$defs/policy"
        },
        "evaluation": {
          "$ref": "#/$defs/evaluation"
        },
        "status": {
          "enum": [
            "READY",
            "PENDING_REVIEW",
            "DENIED",
            "ABSTAINED",
            "REJECTED",
            "CANCELLED",
            "EXECUTED",
            "STALE"
          ]
        },
        "review": {
          "oneOf": [
            {
              "type": "null"
            },
            {
              "$ref": "#/$defs/review"
            }
          ]
        },
        "result": {
          "oneOf": [
            {
              "type": "null"
            },
            {
              "$ref": "#/$defs/ticket"
            }
          ]
        },
        "events": {
          "type": "array",
          "minItems": 1,
          "prefixItems": [
            {
              "$ref": "#/$defs/event_submitted"
            }
          ],
          "items": {
            "anyOf": [
              {
                "$ref": "#/$defs/event_transition"
              },
              {
                "$ref": "#/$defs/event_cancelled"
              }
            ]
          }
        },
        "produced_by": {
          "type": "object",
          "properties": {
            "name": {
              "const": "decisioncontrol"
            },
            "version": {
              "$ref": "#/$defs/text"
            }
          },
          "required": [
            "name",
            "version"
          ],
          "additionalProperties": false
        },
        "proposed_by": {
          "$ref": "#/$defs/text"
        },
        "policy_sha256": {
          "$ref": "#/$defs/sha256"
        }
      },
      "required": [
        "schema_version",
        "id",
        "created_at",
        "recommendation",
        "ticket",
        "policy",
        "evaluation",
        "status",
        "review",
        "result",
        "events",
        "produced_by",
        "proposed_by",
        "policy_sha256"
      ],
      "additionalProperties": false
    },
    "sha256": {
      "$ref": "#/$defs/sha256"
    }
  },
  "required": [
    "record",
    "sha256"
  ],
  "additionalProperties": false,
  "$defs": {
    "string": {
      "type": "string",
      "pattern": "^[^\\ud800-\\udfff]*$",
      "description": "Any string without an unpaired surrogate (which has no UTF-8 encoding)."
    },
    "text": {
      "type": "string",
      "allOf": [
        {
          "pattern": "^[^\\ud800-\\udfff]*$"
        },
        {
          "pattern": "^(?:\\S|\\S[\\s\\S]*\\S)(?![\\s\\S])"
        }
      ],
      "description": "Nonempty, no leading or trailing whitespace, no unpaired surrogate."
    },
    "sha256": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}(?![\\s\\S])"
    },
    "uuid": {
      "$comment": "Deliberately stricter than the reader. Producers write str(uuid4()), the hyphenated 8-4-4-4-12 form, and this pattern describes that form. The reader of schemas 1-3 (released in 0.1.0 and kept unchanged) accepts anything uuid.UUID() parses: braces, a urn:uuid: prefix, missing or repeated hyphens and, depending on the Python version, further spellings. A pattern cannot mirror that parser, so such ids are valid for replay but not for this schema. Schemas 4 and 5 require the canonical lowercase form, which their schemas match exactly.",
      "type": "string",
      "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}(?![\\s\\S])"
    },
    "timestamp": {
      "type": "string",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\\.[0-9]+)?(?:Z|[+-]00:00)(?![\\s\\S])",
      "description": "ISO 8601 timestamp at UTC offset zero."
    },
    "names": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/text"
      },
      "uniqueItems": true
    },
    "verdict": {
      "enum": [
        "ALLOW",
        "DENY",
        "REVIEW",
        "ABSTAIN"
      ]
    },
    "evaluation": {
      "type": "object",
      "properties": {
        "verdict": {
          "$ref": "#/$defs/verdict"
        },
        "reasons": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/text"
          },
          "uniqueItems": true,
          "minItems": 1
        }
      },
      "required": [
        "verdict",
        "reasons"
      ],
      "additionalProperties": false
    },
    "probability": {
      "type": "number",
      "minimum": 0,
      "maximum": 1
    },
    "ticket": {
      "type": "object",
      "properties": {
        "id": {
          "$ref": "#/$defs/text"
        },
        "department": {
          "$ref": "#/$defs/text"
        },
        "revision": {
          "type": "integer",
          "minimum": 0
        }
      },
      "required": [
        "id",
        "department",
        "revision"
      ],
      "additionalProperties": false
    },
    "recommendation": {
      "type": "object",
      "properties": {
        "action": {
          "$ref": "#/$defs/text"
        },
        "ticket_id": {
          "$ref": "#/$defs/text"
        },
        "destination": {
          "$ref": "#/$defs/text"
        },
        "probability": {
          "oneOf": [
            {
              "type": "null"
            },
            {
              "$ref": "#/$defs/probability"
            }
          ]
        },
        "model": {
          "$ref": "#/$defs/text"
        },
        "question_version": {
          "$ref": "#/$defs/text"
        },
        "refused": {
          "type": "boolean"
        }
      },
      "required": [
        "action",
        "ticket_id",
        "destination",
        "model",
        "question_version"
      ],
      "additionalProperties": false
    },
    "policy": {
      "type": "object",
      "properties": {
        "version": {
          "$ref": "#/$defs/text"
        },
        "allowed_destinations": {
          "allOf": [
            {
              "$ref": "#/$defs/names"
            },
            {
              "minItems": 1
            }
          ]
        },
        "review_destinations": {
          "$ref": "#/$defs/names"
        },
        "reviewers": {
          "allOf": [
            {
              "$ref": "#/$defs/names"
            },
            {
              "minItems": 1
            }
          ]
        },
        "min_probability": {
          "$ref": "#/$defs/probability"
        }
      },
      "required": [
        "version",
        "allowed_destinations",
        "review_destinations",
        "reviewers"
      ],
      "additionalProperties": false
    },
    "event_submitted": {
      "type": "object",
      "properties": {
        "event": {
          "const": "SUBMITTED"
        },
        "at": {
          "$ref": "#/$defs/timestamp"
        }
      },
      "required": [
        "event",
        "at"
      ],
      "additionalProperties": false
    },
    "event_transition": {
      "type": "object",
      "properties": {
        "event": {
          "enum": [
            "APPROVED",
            "REJECTED",
            "EXECUTED",
            "STALE"
          ]
        },
        "at": {
          "$ref": "#/$defs/timestamp"
        }
      },
      "required": [
        "event",
        "at"
      ],
      "additionalProperties": false
    },
    "event_cancelled": {
      "type": "object",
      "properties": {
        "event": {
          "const": "CANCELLED"
        },
        "at": {
          "$ref": "#/$defs/timestamp"
        },
        "reviewer": {
          "$ref": "#/$defs/string"
        },
        "note": {
          "type": "string",
          "allOf": [
            {
              "pattern": "^[^\\ud800-\\udfff]*$"
            },
            {
              "pattern": "\\S"
            }
          ]
        }
      },
      "required": [
        "event",
        "at",
        "reviewer",
        "note"
      ],
      "additionalProperties": false
    },
    "review": {
      "type": "object",
      "properties": {
        "decision": {
          "enum": [
            "APPROVED",
            "REJECTED"
          ]
        },
        "reviewer": {
          "$ref": "#/$defs/string"
        },
        "note": {
          "$ref": "#/$defs/string"
        },
        "at": {
          "$ref": "#/$defs/timestamp"
        }
      },
      "required": [
        "decision",
        "reviewer",
        "note",
        "at"
      ],
      "additionalProperties": false
    }
  }
}
