{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://www.anguskit.com/schema/angusmeter/plugins/angus-mqtt.json",
  "type": "object",
  "properties": {
    "broker": {
      "type": "string",
      "description": "MQTT broker URL (e.g. tcp://localhost, ssl://broker.example.com, ws://host:8083/mqtt, wss://host:8084/mqtt)"
    },
    "port": {
      "type": "integer",
      "minimum": 1,
      "maximum": 65535,
      "default": 1883
    },
    "topic": {
      "type": "string",
      "description": "MQTT topic (supports wildcards + and # for SUBSCRIBE)"
    },
    "payload": {
      "type": "string",
      "description": "Message payload (PUBLISH only, supports ${var} interpolation)"
    },
    "qos": {
      "type": "integer",
      "enum": [
        0,
        1,
        2
      ],
      "default": 1,
      "description": "Quality of Service level"
    },
    "retained": {
      "type": "boolean",
      "default": false,
      "description": "Publish as retained message (PUBLISH only)"
    },
    "clientId": {
      "type": "string",
      "description": "MQTT client ID (auto-generated if omitted)"
    },
    "username": {
      "type": "string"
    },
    "password": {
      "type": "string",
      "writeOnly": true
    },
    "timeout": {
      "type": "integer",
      "minimum": 1,
      "maximum": 300,
      "default": 10,
      "description": "Connection timeout in seconds (1–300)"
    },
    "keepAlive": {
      "type": "integer",
      "minimum": 0,
      "maximum": 65535,
      "default": 60,
      "description": "Keep-alive interval in seconds (0 disables keep-alive per MQTT 5.0 §3.1.2.10)"
    },
    "cleanStart": {
      "type": "boolean",
      "default": true,
      "description": "MQTT 5.0 clean start flag"
    },
    "sessionExpirySeconds": {
      "type": "integer",
      "minimum": 0,
      "description": "MQTT 5.0 session expiry interval in seconds. Omit to use broker default"
    },
    "messageExpirySeconds": {
      "type": "integer",
      "minimum": 1,
      "description": "MQTT 5.0 message expiry interval in seconds (PUBLISH only). Omit to use broker default"
    },
    "subscribeTimeout": {
      "type": "integer",
      "minimum": 1,
      "maximum": 300,
      "default": 5,
      "description": "Seconds to wait for messages (SUBSCRIBE only)"
    },
    "maxMessages": {
      "type": "integer",
      "minimum": 1,
      "default": 1,
      "description": "Max number of messages to collect (SUBSCRIBE only)"
    },
    "action": {
      "type": "string",
      "enum": [
        "PUBLISH",
        "SUBSCRIBE"
      ],
      "default": "PUBLISH"
    },
    "userProperties": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      },
      "description": "MQTT 5.0 user properties as key-value pairs (PUBLISH only, supports ${var} interpolation)"
    },
    "will": {
      "type": "object",
      "description": "Last Will and Testament configuration",
      "properties": {
        "topic": {
          "type": "string"
        },
        "payload": {
          "type": "string"
        },
        "qos": {
          "type": "integer",
          "enum": [
            0,
            1,
            2
          ],
          "default": 0
        },
        "retained": {
          "type": "boolean",
          "default": false
        }
      },
      "required": [
        "topic",
        "payload"
      ]
    },
    "tls": {
      "type": "object",
      "description": "TLS/SSL configuration. All fields are mapped through cloud.xcan.angus.spec.model.TlsConfig; provide keystore/truststore or PEM cert+key to enable mTLS.",
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": false
        },
        "trustAll": {
          "type": "boolean",
          "default": false,
          "description": "Trust all certificates (testing only)"
        },
        "verifyHostname": {
          "type": "boolean",
          "default": true,
          "description": "Verify broker hostname against the certificate (ignored when trustAll=true)"
        },
        "keystorePath": {
          "type": "string",
          "description": "Path to client keystore (JKS/PKCS12) for mTLS. Store format is inferred from the extension."
        },
        "keystorePassword": {
          "type": "string",
          "description": "Client keystore password.",
          "writeOnly": true
        },
        "truststorePath": {
          "type": "string",
          "description": "Path to custom trust store (JKS/PKCS12)."
        },
        "truststorePassword": {
          "type": "string",
          "description": "Trust store password.",
          "writeOnly": true
        },
        "certPath": {
          "type": "string",
          "description": "PEM client certificate path (used with keyPath for mTLS)."
        },
        "keyPath": {
          "type": "string",
          "description": "PEM PKCS#8 private key path (used with certPath)."
        },
        "keyPassword": {
          "type": "string",
          "description": "Password for encrypted PEM private key.",
          "writeOnly": true
        },
        "caPath": {
          "type": "string",
          "description": "PEM CA bundle path (alternative to truststorePath)."
        }
      }
    },
    "assertions": {
      "type": "array",
      "description": "Optional step-level assertions evaluated against the MQTT sample result (see MqttConfigValidator; Assertion.AssertionType).",
      "items": {
        "$ref": "#/definitions/mqttAssertion"
      }
    },
    "extractors": {
      "type": "array",
      "description": "Optional extractors from the MQTT response (see MqttConfigValidator; Extractor.ExtractorType).",
      "items": {
        "$ref": "#/definitions/mqttExtractor"
      }
    },
    "maxDurationSeconds": {
      "type": "integer",
      "minimum": 1,
      "description": "Maximum duration in seconds for streaming/SSE mode. Only used with the stream() API."
    },
    "topics": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "List of MQTT topics to subscribe to in streaming mode. Supports MQTT wildcards (+ and #)."
    }
  },
  "required": [
    "broker",
    "topic"
  ],
  "definitions": {
    "mqttAssertion": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "type": {
          "type": "string",
          "enum": [
            "STATUS_CODE",
            "RESPONSE_TIME",
            "BODY_CONTAINS",
            "BODY_JSON_PATH",
            "BODY_REGEX",
            "HEADER_EXISTS",
            "HEADER_VALUE",
            "BODY_SIZE",
            "NOT_NULL",
            "CUSTOM",
            "BODY_EQUALS",
            "BODY_XPATH",
            "METRIC_SCORE",
            "TOKEN_COUNT",
            "API_COST",
            "LLM_LATENCY",
            "JSON_SCHEMA",
            "NO_PII",
            "RESPONSE_BODY",
            "URL",
            "TITLE",
            "ELEMENT_TEXT",
            "ELEMENT_VALUE",
            "ELEMENT_VISIBLE",
            "ORIENTATION"
          ]
        },
        "operator": {
          "type": "string"
        },
        "expected": {
          "description": "Expected value for the assertion"
        },
        "expression": {
          "type": "string"
        },
        "enabled": {
          "type": "boolean"
        }
      },
      "required": [
        "type"
      ]
    },
    "mqttExtractor": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "JSON_PATH",
            "XPATH",
            "REGEX",
            "HEADER",
            "COOKIE",
            "RESPONSE_CODE",
            "RESPONSE_TIME"
          ]
        },
        "expression": {
          "type": "string"
        },
        "variable": {
          "type": "string"
        },
        "defaultValue": {
          "type": "string"
        }
      },
      "required": [
        "type",
        "variable"
      ],
      "allOf": [
        {
          "if": {
            "properties": {
              "type": {
                "enum": [
                  "JSON_PATH",
                  "XPATH",
                  "REGEX",
                  "HEADER",
                  "COOKIE"
                ]
              }
            }
          },
          "then": {
            "required": [
              "expression"
            ]
          }
        }
      ]
    }
  }
}
