{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://aisa.ablera.com/contracts/ledger-record.schema.json",
  "title": "Ledger record (platform seam 4 of 5)",
  "description": "Architecture § 3.2 and Trust and Data § 5: one record per action in the fixed, tool-parsable format. record_hash = SHA-256(prev_hash || canonical(record without prev_hash and record_hash)), canonical form SERDICA-JCS-1 (AI.Contracts). Payload hashes only — never payloads, never result rows, never identifiers (handles instead). Persisted as one AUDIT_LEDGER row; exported as one JSONL line per record.",
  "type": "object",
  "additionalProperties": false,
  "required": ["record_id", "kind", "occurred_on", "actor", "framework_version", "canonical_form", "prev_hash", "record_hash"],
  "properties": {
    "record_id": { "type": "string", "minLength": 8, "maxLength": 64 },
    "kind": { "type": "string", "enum": [
      "CASE_OPENED", "CASE_STATE", "CASE_ROUTED", "CASE_MERGED", "CASE_CLOSED",
      "TASK_SPAWNED", "TASK_STATE", "TURN", "MESSAGE", "TOOL_CALL", "TOOL_RESULT", "TOOL_REFUSED",
      "GATE_OPENED", "GATE_DECIDED", "GATE_ESCALATED", "GRANT_ISSUED", "GRANT_EXPIRED", "GRANT_REVOKED",
      "WRITE_INTENDED", "WRITE_EXECUTED", "WRITE_REFUSED", "WRITE_FAILED", "VERIFY", "REVERT", "PREFLIGHT",
      "SHAPE_STATE", "RISK_ACCEPTED", "RISK_WITHDRAWN",
      "PAPER_ACCESS", "MEMORY_READ", "MEMORY_WRITE", "MEMORY_STATE", "REIDENTIFY", "HANDLE_DESTROYED",
      "CONSULT", "HANDOVER", "EXIT_TO_ESTATE",
      "GOVERNANCE", "EVAL_RUN", "ROUTE_CHANGED", "FRAMEWORK_CHANGED",
      "CONNECTOR_HEALTH", "BUDGET_WARNING", "BUDGET_STOP", "ALERT", "KILL_SWITCH",
      "SEAL", "EXPORT", "RESTORE", "RETENTION", "CORRECTION"] },
    "occurred_on": { "type": "string", "format": "date-time" },
    "case_id": { "type": "string" },
    "task_id": { "type": "string" },
    "task_path": { "type": "string" },
    "actor": {
      "type": "object", "additionalProperties": false,
      "required": ["kind", "id"],
      "properties": {
        "kind": { "type": "string", "enum": ["agent", "person", "policy", "system"] },
        "id": { "type": "string", "description": "profile key + instance for agents; the subject id for persons; the policy row id for auto-confirmed decisions; the job name for system" },
        "role": { "type": "string", "description": "the platform role the person held when deciding" }
      }
    },
    "versions": {
      "type": "object", "additionalProperties": false,
      "properties": {
        "profile_key": { "type": "string" }, "profile_version": { "type": "integer" },
        "prompt_version": { "type": "integer" }, "route_key": { "type": "string" }, "route_version": { "type": "integer" }
      }
    },
    "framework_version": { "type": "string", "description": "assembly version + git sha (Agent Framework § Challenges)" },
    "lineage": {
      "type": "object", "additionalProperties": false,
      "properties": { "plan_revision_id": { "type": "string" }, "parent_decision_id": { "type": "string" }, "policy_ref": { "type": "string" }, "grant_id": { "type": "string" } }
    },
    "target": {
      "type": "object", "additionalProperties": false,
      "properties": {
        "environment": { "type": "string" }, "system": { "type": "string" }, "object": { "type": "string" },
        "mode": { "type": "string", "enum": ["read", "dry_run", "write", "send", "ddl"] }
      }
    },
    "requested_action": { "type": "string", "maxLength": 2000, "description": "the exact requested action (statement text or operation + parameters) — never result rows" },
    "actual_action": { "type": "string", "maxLength": 2000, "description": "what actually ran, as reported by the connector" },
    "row_count": { "type": "integer", "minimum": 0 },
    "verification_result": { "type": "string", "enum": ["pass", "fail", "unverifiable", "skipped"] },
    "trust_class": { "type": "string", "enum": ["trusted", "derived", "untrusted", "absent"] },
    "payload_hash": { "$ref": "#/$defs/sha256" },
    "artefact_hashes": { "type": "array", "items": { "$ref": "#/$defs/sha256" } },
    "supersedes_record_id": { "type": "string", "description": "CORRECTION only: the record this one corrects; nothing is rewritten" },
    "canonical_form": { "type": "string", "const": "SERDICA-JCS-1" },
    "prev_hash": { "$ref": "#/$defs/sha256" },
    "record_hash": { "$ref": "#/$defs/sha256" }
  },
  "allOf": [
    {"if": {"properties": {"kind": {"const": "CORRECTION"}}}, "then": {"required": ["supersedes_record_id"]}},
    {"if": {"properties": {"kind": {"const": "WRITE_EXECUTED"}}}, "then": {"required": ["case_id", "target", "requested_action", "actual_action", "lineage"], "properties": {"lineage": {"required": ["grant_id"]}}}},
    {"if": {"properties": {"kind": {"enum": ["TOOL_CALL", "TOOL_RESULT", "TOOL_REFUSED"]}}}, "then": {"required": ["case_id", "task_id", "target"]}},
    {"if": {"properties": {"kind": {"const": "GATE_DECIDED"}}}, "then": {"required": ["case_id", "lineage"], "properties": {"actor": {"properties": {"kind": {"enum": ["person", "policy"]}}}}}},
    {"if": {"properties": {"kind": {"enum": ["MESSAGE", "TURN"]}}}, "then": {"required": ["case_id", "task_id", "payload_hash", "versions"]}},
    {"if": {"properties": {"actor": {"properties": {"kind": {"const": "agent"}}}}}, "then": {"required": ["versions"]}}
  ],
  "$defs": { "sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" } }
}
