{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "urn:videograce:control:v2:core:draft1",
  "title": "VideoGrace Control v2 core contract (specified, not implemented)",
  "description": "Post-negotiation envelopes. Feature DTOs, authorization, duplicate JSON keys, uint64 bounds and sequence rules require additional validation. protocolOffer/protocolSelection validate login extensions, not the entire v1 login.",
  "type": "object",
  "minProperties": 1,
  "maxProperties": 1,
  "additionalProperties": false,
  "properties": {
    "control_command": {"$ref": "#/definitions/command"},
    "control_result": {"$ref": "#/definitions/result"},
    "control_event": {"$ref": "#/definitions/event"},
    "control_signal": {"$ref": "#/definitions/signal"},
    "control_media": {"$ref": "#/definitions/media"},
    "control_sync": {"$ref": "#/definitions/sync"},
    "control_snapshot": {"$ref": "#/definitions/snapshot"},
    "control_sync_result": {"$ref": "#/definitions/syncResult"}
  },
  "definitions": {
    "id": {"type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"},
    "counter": {"type": "string", "pattern": "^(0|[1-9][0-9]{0,19})$", "description": "Canonical uint64 decimal; semantic maximum 18446744073709551615."},
    "generation": {"allOf": [{"$ref": "#/definitions/counter"}, {"not": {"const": "0"}}]},
    "duration": {"type": "integer", "minimum": 1, "maximum": 2147483647},
    "object": {"type": "object"},
    "protocolOffer": {
      "type": "object", "additionalProperties": false,
      "required": ["versions", "require_version", "profiles"],
      "properties": {
        "versions": {"type": "array", "minItems": 1, "maxItems": 2, "uniqueItems": true, "items": {"enum": [1, 2]}, "contains": {"const": 2}},
        "require_version": {"enum": [1, 2]},
        "profiles": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"const": "vg.control.v2.core"}}
      }
    },
    "protocolSelection": {
      "type": "object", "additionalProperties": false,
      "required": ["version", "profile", "deployment_id", "tenant_id", "user_id", "auth_session_id", "transport_id", "limits"],
      "properties": {
        "version": {"const": 2}, "profile": {"const": "vg.control.v2.core"},
        "deployment_id": {"$ref": "#/definitions/id"}, "tenant_id": {"$ref": "#/definitions/id"},
        "user_id": {"$ref": "#/definitions/id"}, "auth_session_id": {"$ref": "#/definitions/id"}, "transport_id": {"$ref": "#/definitions/id"},
        "limits": {
          "type": "object", "additionalProperties": false,
          "required": ["max_frame_bytes", "max_inflight_commands", "max_sync_parts", "max_sync_bytes", "sync_timeout_ms", "command_retry_window_ms", "resume_grace_ms"],
          "properties": {
            "max_frame_bytes": {"type": "integer", "minimum": 1024, "maximum": 16777216},
            "max_inflight_commands": {"type": "integer", "minimum": 1, "maximum": 1024},
            "max_sync_parts": {"type": "integer", "minimum": 1, "maximum": 4096},
            "max_sync_bytes": {"type": "integer", "minimum": 1024, "maximum": 268435456},
            "sync_timeout_ms": {"$ref": "#/definitions/duration"},
            "command_retry_window_ms": {"$ref": "#/definitions/duration"},
            "resume_grace_ms": {"$ref": "#/definitions/duration"}
          }
        }
      }
    },
    "binding": {
      "type": "object", "additionalProperties": false,
      "required": ["deployment_id", "tenant_id", "logical_connection_id", "binding_generation"],
      "properties": {
        "deployment_id": {"$ref": "#/definitions/id"}, "tenant_id": {"$ref": "#/definitions/id"},
        "logical_connection_id": {"$ref": "#/definitions/id"}, "binding_generation": {"$ref": "#/definitions/generation"}
      }
    },
    "target": {
      "type": "object", "additionalProperties": false, "required": ["kind", "id"],
      "properties": {"kind": {"enum": ["account", "conference", "conference_session", "chat", "operation"]}, "id": {"$ref": "#/definitions/id"}}
    },
    "cursor": {
      "type": "object", "additionalProperties": false, "required": ["stream_id", "stream_epoch", "seq"],
      "properties": {"stream_id": {"$ref": "#/definitions/id"}, "stream_epoch": {"$ref": "#/definitions/generation"}, "seq": {"$ref": "#/definitions/counter"}}
    },
    "error": {
      "type": "object", "additionalProperties": false, "required": ["code"],
      "properties": {
        "code": {"enum": ["protocol_unsupported", "unsupported_feature", "unauthenticated", "token_expired", "account_deleted", "permission_denied", "stale_binding", "resume_rejected", "version_conflict", "idempotency_conflict", "resync_required", "temporarily_unavailable", "rate_limited", "deadline_exceeded", "outcome_unknown", "invalid_argument", "resource_exhausted", "apply_failed"]},
        "message": {"type": "string", "maxLength": 2048}, "retry_after_ms": {"$ref": "#/definitions/duration"}, "extensions": {"$ref": "#/definitions/object"}
      }
    },
    "command": {
      "type": "object", "additionalProperties": false,
      "required": ["binding", "command_id", "target", "name", "body", "ttl_ms"],
      "properties": {
        "binding": {"$ref": "#/definitions/binding"}, "command_id": {"$ref": "#/definitions/id"},
        "target": {"$ref": "#/definitions/target"}, "name": {"$ref": "#/definitions/id"}, "body": {"$ref": "#/definitions/object"},
        "expected_version": {"$ref": "#/definitions/counter"}, "ttl_ms": {"$ref": "#/definitions/duration"}, "extensions": {"$ref": "#/definitions/object"}
      }
    },
    "result": {
      "type": "object", "additionalProperties": false, "required": ["binding", "command_id", "status"],
      "properties": {
        "binding": {"$ref": "#/definitions/binding"}, "command_id": {"$ref": "#/definitions/id"},
        "status": {"enum": ["received", "committed", "applied", "rejected", "apply_failed", "outcome_unknown"]},
        "aggregate": {"$ref": "#/definitions/target"}, "aggregate_version": {"$ref": "#/definitions/counter"},
        "data": {"$ref": "#/definitions/object"}, "error": {"$ref": "#/definitions/error"}, "extensions": {"$ref": "#/definitions/object"}
      },
      "dependencies": {"aggregate_version": ["aggregate"]},
      "allOf": [
        {"if": {"properties": {"status": {"enum": ["rejected", "apply_failed", "outcome_unknown"]}}}, "then": {"required": ["error"]}, "else": {"not": {"required": ["error"]}}}
      ]
    },
    "event": {
      "type": "object", "additionalProperties": false,
      "required": ["binding", "event_id", "stream_id", "stream_epoch", "seq", "aggregate", "aggregate_version", "name", "body"],
      "properties": {
        "binding": {"$ref": "#/definitions/binding"}, "event_id": {"$ref": "#/definitions/id"}, "request_id": {"$ref": "#/definitions/id"},
        "stream_id": {"$ref": "#/definitions/id"}, "stream_epoch": {"$ref": "#/definitions/generation"}, "seq": {"$ref": "#/definitions/generation"},
        "aggregate": {"$ref": "#/definitions/target"}, "aggregate_version": {"$ref": "#/definitions/counter"},
        "name": {"$ref": "#/definitions/id"}, "body": {"$ref": "#/definitions/object"}, "extensions": {"$ref": "#/definitions/object"}
      }
    },
    "signal": {
      "type": "object", "additionalProperties": false,
      "required": ["binding", "stream_id", "stream_epoch", "source_id", "signal_seq", "ttl_ms", "name", "body"],
      "properties": {
        "binding": {"$ref": "#/definitions/binding"}, "stream_id": {"$ref": "#/definitions/id"}, "stream_epoch": {"$ref": "#/definitions/generation"},
        "source_id": {"$ref": "#/definitions/id"}, "signal_seq": {"$ref": "#/definitions/generation"}, "ttl_ms": {"$ref": "#/definitions/duration"},
        "name": {"$ref": "#/definitions/id"}, "body": {"$ref": "#/definitions/object"}
      }
    },
    "mediaRef": {
      "type": "object", "additionalProperties": false,
      "required": ["conference_session_id", "participant_instance_id", "publication_id", "route_generation", "endpoint_id", "negotiation_id", "scope", "rtc_node_id"],
      "properties": {
        "conference_session_id": {"$ref": "#/definitions/id"}, "participant_instance_id": {"$ref": "#/definitions/id"}, "publication_id": {"$ref": "#/definitions/id"},
        "route_generation": {"$ref": "#/definitions/generation"}, "endpoint_id": {"$ref": "#/definitions/id"}, "negotiation_id": {"$ref": "#/definitions/id"},
        "scope": {"enum": ["audio", "video", "audio-subscribe", "video-subscribe"]}, "rtc_node_id": {"$ref": "#/definitions/id"}
      }
    },
    "media": {
      "type": "object", "additionalProperties": false, "required": ["binding", "media", "name", "body"],
      "properties": {
        "binding": {"$ref": "#/definitions/binding"}, "media": {"$ref": "#/definitions/mediaRef"},
        "name": {"enum": ["webrtc_offer", "webrtc_answer", "webrtc_ice_candidate"]}, "body": {"$ref": "#/definitions/object"}
      }
    },
    "resume": {
      "type": "object", "additionalProperties": false, "required": ["binding", "resume_token"],
      "properties": {"binding": {"$ref": "#/definitions/binding"}, "resume_token": {"type": "string", "minLength": 32, "maxLength": 4096}, "previous_request_id": {"$ref": "#/definitions/id"}}
    },
    "sync": {
      "type": "object", "additionalProperties": false, "required": ["request_id", "control_instance_id", "mode", "cursors"],
      "properties": {
        "request_id": {"$ref": "#/definitions/id"}, "control_instance_id": {"$ref": "#/definitions/id"}, "mode": {"enum": ["fresh", "resume", "resync"]},
        "binding": {"$ref": "#/definitions/binding"}, "resume": {"$ref": "#/definitions/resume"},
        "cursors": {"type": "array", "maxItems": 1024, "items": {"$ref": "#/definitions/cursor"}}
      },
      "allOf": [
        {"if": {"properties": {"mode": {"const": "fresh"}}}, "then": {"not": {"anyOf": [{"required": ["binding"]}, {"required": ["resume"]}]}, "properties": {"cursors": {"maxItems": 0}}}},
        {"if": {"properties": {"mode": {"const": "resume"}}}, "then": {"required": ["resume"], "not": {"required": ["binding"]}}},
        {"if": {"properties": {"mode": {"const": "resync"}}}, "then": {"required": ["binding"], "not": {"required": ["resume"]}}}
      ]
    },
    "snapshot": {
      "type": "object", "additionalProperties": false,
      "required": ["request_id", "binding", "stream_id", "stream_epoch", "snapshot_id", "snapshot_seq", "part_index", "part_count", "state"],
      "properties": {
        "request_id": {"$ref": "#/definitions/id"}, "binding": {"$ref": "#/definitions/binding"},
        "stream_id": {"$ref": "#/definitions/id"}, "stream_epoch": {"$ref": "#/definitions/generation"}, "snapshot_id": {"$ref": "#/definitions/id"}, "snapshot_seq": {"$ref": "#/definitions/counter"},
        "part_index": {"type": "integer", "minimum": 0, "maximum": 4095}, "part_count": {"type": "integer", "minimum": 1, "maximum": 4096},
        "state": {"$ref": "#/definitions/object"}
      }
    },
    "syncResult": {
      "type": "object", "additionalProperties": false, "required": ["request_id", "status"],
      "properties": {
        "request_id": {"$ref": "#/definitions/id"}, "status": {"enum": ["ready", "resume_rejected", "retry_later"]},
        "binding": {"$ref": "#/definitions/binding"}, "resume_token": {"type": "string", "minLength": 32, "maxLength": 4096},
        "streams": {"type": "array", "minItems": 1, "maxItems": 1024, "items": {"$ref": "#/definitions/cursor"}},
        "error": {"$ref": "#/definitions/error"}
      },
      "allOf": [
        {"if": {"properties": {"status": {"const": "ready"}}}, "then": {"required": ["binding", "streams", "resume_token"], "not": {"required": ["error"]}}, "else": {"required": ["error"], "not": {"anyOf": [{"required": ["streams"]}, {"required": ["resume_token"]}]}}}
      ]
    }
  }
}
