{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://trove.local/schemas/protocol-message.schema.json",
  "title": "Trove Wire Protocol Message v1",
  "oneOf": [
    { "$ref": "#/$defs/hello" },
    { "$ref": "#/$defs/welcome" },
    { "$ref": "#/$defs/ready" },
    { "$ref": "#/$defs/request" },
    { "$ref": "#/$defs/response" },
    { "$ref": "#/$defs/subscribe" },
    { "$ref": "#/$defs/event" },
    { "$ref": "#/$defs/unsubscribe" },
    { "$ref": "#/$defs/cancel" },
    { "$ref": "#/$defs/shutdown" },
    { "$ref": "#/$defs/goodbye" },
    { "$ref": "#/$defs/protocolError" }
  ],
  "$defs": {
    "base": {
      "type": "object",
      "required": ["v", "type"],
      "properties": {
        "v": { "const": 1 },
        "type": { "type": "string" }
      }
    },
    "id": {
      "type": ["string", "integer"],
      "minLength": 1
    },
    "error": {
      "type": "object",
      "required": ["code", "message"],
      "properties": {
        "code": { "type": "string", "minLength": 1, "maxLength": 240 },
        "message": { "type": "string", "minLength": 1, "maxLength": 4096 },
        "data": true,
        "retryable": { "type": "boolean", "default": false },
        "traceId": { "type": "string" }
      },
      "additionalProperties": true
    },
    "hello": {
      "allOf": [
        { "$ref": "#/$defs/base" },
        {
          "type": "object",
          "required": ["client", "sessionToken", "protocol", "features"],
          "properties": {
            "type": { "const": "hello" },
            "client": { "const": "backend" },
            "sessionToken": { "type": "string", "minLength": 16 },
            "protocol": {
              "type": "object",
              "required": ["min", "max"],
              "properties": {
                "min": { "type": "integer", "minimum": 1 },
                "max": { "type": "integer", "minimum": 1 }
              },
              "additionalProperties": false
            },
            "features": {
              "type": "array",
              "items": { "type": "string" },
              "uniqueItems": true
            },
            "implementation": {
              "type": "object",
              "properties": {
                "name": { "type": "string" },
                "version": { "type": "string" },
                "language": { "type": "string" }
              },
              "additionalProperties": true
            }
          },
          "additionalProperties": true
        }
      ]
    },
    "welcome": {
      "allOf": [
        { "$ref": "#/$defs/base" },
        {
          "type": "object",
          "required": ["protocol", "host", "session", "features", "limits"],
          "properties": {
            "type": { "const": "welcome" },
            "protocol": { "type": "integer", "minimum": 1 },
            "host": { "type": "object" },
            "session": { "type": "object" },
            "features": { "type": "array", "items": { "type": "string" } },
            "limits": { "type": "object" }
          },
          "additionalProperties": true
        }
      ]
    },
    "ready": {
      "allOf": [
        { "$ref": "#/$defs/base" },
        {
          "type": "object",
          "properties": { "type": { "const": "ready" } },
          "additionalProperties": true
        }
      ]
    },
    "request": {
      "allOf": [
        { "$ref": "#/$defs/base" },
        {
          "type": "object",
          "required": ["id", "service", "method"],
          "properties": {
            "type": { "const": "request" },
            "id": { "$ref": "#/$defs/id" },
            "service": { "type": "string", "minLength": 1 },
            "method": { "type": "string", "minLength": 1 },
            "params": true,
            "options": { "type": "object" },
            "context": { "type": "object" }
          },
          "additionalProperties": true
        }
      ]
    },
    "response": {
      "allOf": [
        { "$ref": "#/$defs/base" },
        {
          "type": "object",
          "required": ["id"],
          "properties": {
            "type": { "const": "response" },
            "id": { "$ref": "#/$defs/id" },
            "result": true,
            "error": { "$ref": "#/$defs/error" }
          },
          "oneOf": [
            { "required": ["result"], "not": { "required": ["error"] } },
            { "required": ["error"], "not": { "required": ["result"] } }
          ],
          "additionalProperties": true
        }
      ]
    },
    "subscribe": {
      "allOf": [
        { "$ref": "#/$defs/base" },
        {
          "type": "object",
          "required": ["id", "service", "topic"],
          "properties": {
            "type": { "const": "subscribe" },
            "id": { "$ref": "#/$defs/id" },
            "service": { "type": "string", "minLength": 1 },
            "topic": { "type": "string", "minLength": 1 },
            "params": true,
            "options": { "type": "object" },
            "context": { "type": "object" }
          },
          "additionalProperties": true
        }
      ]
    },
    "event": {
      "allOf": [
        { "$ref": "#/$defs/base" },
        {
          "type": "object",
          "required": ["subscriptionId", "event", "seq"],
          "properties": {
            "type": { "const": "event" },
            "subscriptionId": { "type": "string", "minLength": 1 },
            "event": { "type": "string", "minLength": 1 },
            "seq": { "type": "integer", "minimum": 1 },
            "data": true
          },
          "additionalProperties": true
        }
      ]
    },
    "unsubscribe": {
      "allOf": [
        { "$ref": "#/$defs/base" },
        {
          "type": "object",
          "required": ["id", "subscriptionId"],
          "properties": {
            "type": { "const": "unsubscribe" },
            "id": { "$ref": "#/$defs/id" },
            "subscriptionId": { "type": "string", "minLength": 1 }
          },
          "additionalProperties": true
        }
      ]
    },
    "cancel": {
      "allOf": [
        { "$ref": "#/$defs/base" },
        {
          "type": "object",
          "required": ["id"],
          "properties": {
            "type": { "const": "cancel" },
            "id": { "$ref": "#/$defs/id" }
          },
          "additionalProperties": true
        }
      ]
    },
    "shutdown": {
      "allOf": [
        { "$ref": "#/$defs/base" },
        {
          "type": "object",
          "required": ["reason", "gracePeriodMs"],
          "properties": {
            "type": { "const": "shutdown" },
            "reason": { "type": "string" },
            "gracePeriodMs": { "type": "integer", "minimum": 0 }
          },
          "additionalProperties": true
        }
      ]
    },
    "goodbye": {
      "allOf": [
        { "$ref": "#/$defs/base" },
        {
          "type": "object",
          "properties": { "type": { "const": "goodbye" } },
          "additionalProperties": true
        }
      ]
    },
    "protocolError": {
      "allOf": [
        { "$ref": "#/$defs/base" },
        {
          "type": "object",
          "required": ["error"],
          "properties": {
            "type": { "const": "protocolError" },
            "error": { "$ref": "#/$defs/error" }
          },
          "additionalProperties": true
        }
      ]
    }
  }
}
