{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "schemas/callback_owner_enforcement.schema.json",
  "title": "dispatch.callback_owner_enforcement.v1",
  "description": "task-2553+49 §2/§3 — executor self-collector / self-dispatch / self-adjudication structural-block enforcement result + owner-bound callback 4-tuple. normal/fallback callback owner MUST be an independent ANU key (collector_role=ANU, owner_key != executor_key). executor_key==collector_key, owner==executor, collector_role!=ANU, prompt-says-ANU-but-owner-is-executor, invalid 4-tuple, or an unrecognised cron-direct entry path => verdict FAIL with the §3 classification(s) RECORDED (never a silent skip, §2 line 21). +47 idempotency LOW is hardened by audit_writeback_binding_conflict: a COMPLETED record sharing the (dispatch_id, chat_id, normal_collector_cron_id) idempotency key but a DIFFERENT role/fallback binding => WRITEBACK_BINDING_CONFLICT (FAIL, recorded). byte-0 carve-out (9-R / §5): the +44 callback_4tuple_registry and +32 executor_completion_contract stay byte-0 (pinned by the existing +44/+48 FROZEN_SHA256 autouse invariant); the §2 owner fields are carried by THIS schema's owner_4tuple, not by mutating the frozen legacy record.",
  "type": "object",
  "oneOf": [
    { "$ref": "#/definitions/enforcement_result" },
    { "$ref": "#/definitions/owner_4tuple" },
    { "$ref": "#/definitions/self_action_guard_result" },
    { "$ref": "#/definitions/writeback_binding_audit_result" }
  ],
  "definitions": {
    "classification": {
      "type": "string",
      "enum": [
        "SELF_COLLECTOR_FORBIDDEN",
        "EXECUTOR_SELF_ADJUDICATION_FORBIDDEN",
        "SELF_DISPATCH_FORBIDDEN",
        "CALLBACK_OWNER_MISMATCH",
        "CALLBACK_COLLECTOR_NOT_ANU",
        "CALLBACK_4TUPLE_INVALID",
        "DISPATCH_PATH_BYPASSED_CONTRACT",
        "WRITEBACK_BINDING_CONFLICT"
      ]
    },
    "verdict": {
      "type": "string",
      "enum": ["PASS", "FAIL", "HOLD_FOR_CHAIR"]
    },
    "enforcement_result": {
      "type": "object",
      "required": [
        "schema",
        "verdict",
        "classifications",
        "task_id",
        "executor_key",
        "collector_key",
        "collector_owner_key",
        "collector_role",
        "normal_collector_cron_id",
        "fallback_callback_cron_id",
        "dispatch_cron_id",
        "entry_path",
        "owner_is_independent_anu",
        "reasons"
      ],
      "properties": {
        "schema": {
          "type": "string",
          "const": "dispatch.callback_owner_enforcement.v1"
        },
        "verdict": { "$ref": "#/definitions/verdict" },
        "classifications": {
          "type": "array",
          "items": { "$ref": "#/definitions/classification" }
        },
        "primary_classification": {
          "oneOf": [
            { "type": "null" },
            { "$ref": "#/definitions/classification" }
          ]
        },
        "task_id": { "type": "string", "minLength": 1 },
        "executor_key": { "type": "string" },
        "collector_key": { "type": "string" },
        "collector_owner_key": { "type": "string" },
        "collector_role": { "type": "string" },
        "normal_collector_cron_id": {
          "type": ["string", "null"],
          "description": "MANDATORY independent-ANU normal completion callback lifecycle signal. Null/empty => CALLBACK_4TUPLE_INVALID; NO-CRON does NOT exempt it."
        },
        "fallback_callback_cron_id": { "type": ["string", "null"] },
        "dispatch_cron_id": { "type": "string" },
        "normal_collector_cron_id_role": { "type": "string" },
        "fallback_cron_id_role": { "type": "string" },
        "entry_path": { "type": "string" },
        "prompt_claims_anu_collector": { "type": "boolean" },
        "owner_is_independent_anu": {
          "type": "boolean",
          "description": "True iff owner is a configured independent ANU key AND owner != executor_key AND collector_role==ANU. A FAIL/HOLD verdict always has this false."
        },
        "reasons": { "type": "array", "items": { "type": "string" } }
      },
      "additionalProperties": false
    },
    "owner_4tuple": {
      "type": "object",
      "required": [
        "schema",
        "task_id",
        "dispatch_cron_id",
        "normal_collector_cron_id",
        "fallback_callback_cron_id",
        "executor_key",
        "collector_key",
        "collector_owner_key",
        "collector_role"
      ],
      "properties": {
        "schema": {
          "type": "string",
          "const": "dispatch.callback_owner_4tuple.v1"
        },
        "task_id": { "type": "string", "minLength": 1 },
        "dispatch_cron_id": { "type": "string", "minLength": 1 },
        "normal_collector_cron_id": {
          "type": ["string", "null"],
          "description": "MANDATORY (non-null on a valid binding)."
        },
        "fallback_callback_cron_id": { "type": ["string", "null"] },
        "executor_key": { "type": "string", "minLength": 1 },
        "collector_key": { "type": "string", "minLength": 1 },
        "collector_owner_key": {
          "type": "string",
          "minLength": 1,
          "description": "MUST be an independent ANU key, never the executor self key (§2/§10)."
        },
        "collector_role": {
          "type": "string",
          "const": "ANU",
          "description": "The completion collector MUST run as an independent ANU collector session (§2 / regression 5)."
        },
        "chat_id": { "type": "string" },
        "normal_collector_cron_id_role": { "type": "string" },
        "fallback_cron_id_role": { "type": "string" },
        "no_fallback": { "type": "boolean" }
      },
      "additionalProperties": false
    },
    "self_action_guard_result": {
      "type": "object",
      "required": [
        "schema",
        "verdict",
        "classification",
        "is_executor_self_session",
        "reasons"
      ],
      "properties": {
        "schema": {
          "type": "string",
          "const": "dispatch.callback_owner_enforcement.v1"
        },
        "verdict": { "$ref": "#/definitions/verdict" },
        "classification": {
          "oneOf": [
            { "type": "null" },
            { "$ref": "#/definitions/classification" }
          ]
        },
        "is_executor_self_session": { "type": "boolean" },
        "reasons": { "type": "array", "items": { "type": "string" } }
      },
      "additionalProperties": false
    },
    "writeback_binding_audit_result": {
      "type": "object",
      "required": [
        "schema",
        "verdict",
        "classification",
        "task_id",
        "conflict",
        "matched_idempotency_key",
        "conflicting_fields",
        "reasons"
      ],
      "properties": {
        "schema": {
          "type": "string",
          "const": "dispatch.callback_owner_enforcement.v1"
        },
        "verdict": { "$ref": "#/definitions/verdict" },
        "classification": {
          "type": "string",
          "enum": [
            "WRITEBACK_NO_CONFLICT",
            "WRITEBACK_IDEMPOTENT_SKIP",
            "WRITEBACK_BINDING_CONFLICT"
          ]
        },
        "task_id": { "type": "string", "minLength": 1 },
        "conflict": { "type": "boolean" },
        "matched_idempotency_key": { "type": "boolean" },
        "conflicting_fields": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Non-empty ONLY on WRITEBACK_BINDING_CONFLICT (role/fallback binding mismatch under a shared +47 idempotency key). Recorded, never a silent skip (§2 line 21)."
        },
        "reasons": { "type": "array", "items": { "type": "string" } }
      },
      "additionalProperties": false
    }
  }
}
