{
  "openapi": "3.1.0",
  "info": {
    "title": "seedypod core API",
    "description": "Local, cloud-free control of a Gardyn hydroponic tower. LAN-only; no authentication.",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "http://localhost:3000/api"
    }
  ],
  "externalDocs": {
    "url": "https://seedypod.github.io/developers/api"
  },
  "paths": {
    "/system": {
      "get": {
        "operationId": "system-info",
        "summary": "Identity, HAL model, limits and core version",
        "tags": ["system"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "coreVersion": {
                      "type": "string"
                    },
                    "halOnline": {
                      "type": "boolean"
                    },
                    "system": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "contract": {
                              "type": "number",
                              "const": 1
                            },
                            "unitId": {
                              "type": "string"
                            },
                            "model": {
                              "type": "string"
                            },
                            "halVersion": {
                              "type": "string"
                            },
                            "caps": {
                              "type": "object",
                              "properties": {
                                "sensors": {
                                  "type": "array",
                                  "items": {
                                    "type": "string",
                                    "enum": [
                                      "air_temp",
                                      "humidity",
                                      "pcb_temp",
                                      "water_distance",
                                      "water_level_pct",
                                      "pump_v",
                                      "pump_a",
                                      "pump_w",
                                      "ph",
                                      "ec",
                                      "water_temp"
                                    ]
                                  }
                                },
                                "actuators": {
                                  "type": "array",
                                  "items": {
                                    "type": "string",
                                    "enum": ["light", "pump", "dose_1", "dose_2", "dose_3"]
                                  }
                                },
                                "cameras": {
                                  "type": "array",
                                  "items": {
                                    "type": "string",
                                    "enum": ["upper", "lower"]
                                  }
                                }
                              },
                              "required": ["sensors", "actuators", "cameras"],
                              "additionalProperties": false
                            },
                            "limits": {
                              "type": "object",
                              "properties": {
                                "pumpMaxRunS": {
                                  "type": "integer",
                                  "exclusiveMinimum": 0,
                                  "maximum": 9007199254740991
                                },
                                "pumpMaxDuty": {
                                  "type": "number",
                                  "minimum": 0,
                                  "maximum": 100
                                },
                                "waterLowCm": {
                                  "type": ["number", "null"]
                                }
                              },
                              "required": ["pumpMaxRunS", "pumpMaxDuty", "waterLowCm"],
                              "additionalProperties": false
                            }
                          },
                          "required": [
                            "contract",
                            "unitId",
                            "model",
                            "halVersion",
                            "caps",
                            "limits"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": ["coreVersion", "halOnline", "system"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/healthcheck": {
      "get": {
        "operationId": "system-healthcheck",
        "tags": ["system"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "ts": {
                      "type": "string"
                    }
                  },
                  "required": ["ok", "ts"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/settings": {
      "get": {
        "operationId": "settings-get",
        "tags": ["settings"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "unitName": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 40
                    },
                    "timezone": {
                      "type": "string",
                      "minLength": 1
                    },
                    "temperatureUnit": {
                      "type": "string",
                      "enum": ["C", "F"]
                    },
                    "waterFullCm": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "waterEmptyCm": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "tankCapacityL": {
                      "type": "number",
                      "exclusiveMinimum": 0
                    },
                    "thinningReminderDays": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "rootCheckReminderDays": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "harvestReminderDays": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "nutrientReminderDays": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "mqttUrl": {
                      "type": ["string", "null"]
                    },
                    "mqttUsername": {
                      "type": ["string", "null"]
                    },
                    "mqttTlsEnabled": {
                      "type": "boolean"
                    },
                    "mqttTlsInsecure": {
                      "type": "boolean"
                    },
                    "captureIntervalMin": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "primaryAnalyzer": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64
                    },
                    "analysisArtifacts": {
                      "type": "boolean"
                    },
                    "mirrorEndpoint": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uri"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "mirrorBucket": {
                      "anyOf": [
                        {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 63
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "mirrorRegion": {
                      "type": "string",
                      "minLength": 1
                    },
                    "mirrorPrefix": {
                      "type": "string"
                    },
                    "mirrorAccessKeyId": {
                      "type": ["string", "null"]
                    },
                    "autopilotEnabled": {
                      "type": "boolean"
                    },
                    "setupComplete": {
                      "type": "boolean"
                    },
                    "updatedAt": {
                      "type": "string"
                    },
                    "hasApiKey": {
                      "type": "boolean"
                    },
                    "hasMqttPassword": {
                      "type": "boolean"
                    },
                    "hasAnalysisIngestToken": {
                      "type": "boolean"
                    },
                    "hasMirrorSecret": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "unitName",
                    "timezone",
                    "temperatureUnit",
                    "waterFullCm",
                    "waterEmptyCm",
                    "tankCapacityL",
                    "thinningReminderDays",
                    "rootCheckReminderDays",
                    "harvestReminderDays",
                    "nutrientReminderDays",
                    "mqttUrl",
                    "mqttUsername",
                    "mqttTlsEnabled",
                    "mqttTlsInsecure",
                    "captureIntervalMin",
                    "primaryAnalyzer",
                    "analysisArtifacts",
                    "mirrorEndpoint",
                    "mirrorBucket",
                    "mirrorRegion",
                    "mirrorPrefix",
                    "mirrorAccessKeyId",
                    "autopilotEnabled",
                    "setupComplete",
                    "updatedAt",
                    "hasApiKey",
                    "hasMqttPassword",
                    "hasAnalysisIngestToken",
                    "hasMirrorSecret"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "settings-update",
        "tags": ["settings"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "unitName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "timezone": {
                    "type": "string",
                    "minLength": 1
                  },
                  "temperatureUnit": {
                    "type": "string",
                    "enum": ["C", "F"]
                  },
                  "waterFullCm": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 100
                  },
                  "waterEmptyCm": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 100
                  },
                  "tankCapacityL": {
                    "type": "number",
                    "exclusiveMinimum": 0
                  },
                  "thinningReminderDays": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  },
                  "rootCheckReminderDays": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  },
                  "harvestReminderDays": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  },
                  "nutrientReminderDays": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  },
                  "apiKey": {
                    "type": "string"
                  },
                  "mqttUrl": {
                    "type": ["string", "null"]
                  },
                  "mqttUsername": {
                    "type": ["string", "null"]
                  },
                  "mqttPassword": {
                    "type": ["string", "null"]
                  },
                  "mqttTlsEnabled": {
                    "type": "boolean"
                  },
                  "mqttTlsInsecure": {
                    "type": "boolean"
                  },
                  "captureIntervalMin": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  },
                  "primaryAnalyzer": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "analysisArtifacts": {
                    "type": "boolean"
                  },
                  "analysisIngestToken": {
                    "type": "string"
                  },
                  "mirrorEndpoint": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uri"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "mirrorBucket": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 63
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "mirrorRegion": {
                    "type": "string",
                    "minLength": 1
                  },
                  "mirrorPrefix": {
                    "type": "string"
                  },
                  "mirrorAccessKeyId": {
                    "type": ["string", "null"]
                  },
                  "mirrorSecretAccessKey": {
                    "type": ["string", "null"]
                  },
                  "autopilotEnabled": {
                    "type": "boolean"
                  },
                  "setupComplete": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "unitName": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 40
                    },
                    "timezone": {
                      "type": "string",
                      "minLength": 1
                    },
                    "temperatureUnit": {
                      "type": "string",
                      "enum": ["C", "F"]
                    },
                    "waterFullCm": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "waterEmptyCm": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "tankCapacityL": {
                      "type": "number",
                      "exclusiveMinimum": 0
                    },
                    "thinningReminderDays": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "rootCheckReminderDays": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "harvestReminderDays": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "nutrientReminderDays": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "mqttUrl": {
                      "type": ["string", "null"]
                    },
                    "mqttUsername": {
                      "type": ["string", "null"]
                    },
                    "mqttTlsEnabled": {
                      "type": "boolean"
                    },
                    "mqttTlsInsecure": {
                      "type": "boolean"
                    },
                    "captureIntervalMin": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "primaryAnalyzer": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64
                    },
                    "analysisArtifacts": {
                      "type": "boolean"
                    },
                    "mirrorEndpoint": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uri"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "mirrorBucket": {
                      "anyOf": [
                        {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 63
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "mirrorRegion": {
                      "type": "string",
                      "minLength": 1
                    },
                    "mirrorPrefix": {
                      "type": "string"
                    },
                    "mirrorAccessKeyId": {
                      "type": ["string", "null"]
                    },
                    "autopilotEnabled": {
                      "type": "boolean"
                    },
                    "setupComplete": {
                      "type": "boolean"
                    },
                    "updatedAt": {
                      "type": "string"
                    },
                    "hasApiKey": {
                      "type": "boolean"
                    },
                    "hasMqttPassword": {
                      "type": "boolean"
                    },
                    "hasAnalysisIngestToken": {
                      "type": "boolean"
                    },
                    "hasMirrorSecret": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "unitName",
                    "timezone",
                    "temperatureUnit",
                    "waterFullCm",
                    "waterEmptyCm",
                    "tankCapacityL",
                    "thinningReminderDays",
                    "rootCheckReminderDays",
                    "harvestReminderDays",
                    "nutrientReminderDays",
                    "mqttUrl",
                    "mqttUsername",
                    "mqttTlsEnabled",
                    "mqttTlsInsecure",
                    "captureIntervalMin",
                    "primaryAnalyzer",
                    "analysisArtifacts",
                    "mirrorEndpoint",
                    "mirrorBucket",
                    "mirrorRegion",
                    "mirrorPrefix",
                    "mirrorAccessKeyId",
                    "autopilotEnabled",
                    "setupComplete",
                    "updatedAt",
                    "hasApiKey",
                    "hasMqttPassword",
                    "hasAnalysisIngestToken",
                    "hasMirrorSecret"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/network/wifi": {
      "get": {
        "operationId": "network-status",
        "summary": "Wi-Fi mode (client/setup/offline), network, address, and the setup hotspot if it is up",
        "tags": ["network"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "available": {
                      "type": "boolean"
                    },
                    "mode": {
                      "type": "string",
                      "enum": ["client", "setup", "offline"]
                    },
                    "ssid": {
                      "type": ["string", "null"]
                    },
                    "ip": {
                      "type": ["string", "null"]
                    },
                    "setup": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "ssid": {
                              "type": "string"
                            },
                            "url": {
                              "type": "string"
                            },
                            "until": {
                              "type": "string"
                            }
                          },
                          "required": ["ssid", "url", "until"],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "lastError": {
                      "type": ["string", "null"]
                    }
                  },
                  "required": ["available", "mode", "ssid", "ip", "setup", "lastError"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/network/wifi/networks": {
      "get": {
        "operationId": "network-scan",
        "summary": "Networks in range, strongest first",
        "tags": ["network"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "ssid": {
                        "type": "string"
                      },
                      "signal": {
                        "type": "number"
                      },
                      "secure": {
                        "type": "boolean"
                      },
                      "inUse": {
                        "type": "boolean"
                      }
                    },
                    "required": ["ssid", "signal", "secure", "inUse"],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/network/wifi/setup": {
      "post": {
        "operationId": "network-startSetup",
        "summary": "Open the setup hotspot (closes itself after `minutes`)",
        "tags": ["network"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "minutes": {
                    "default": 15,
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 60
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "available": {
                      "type": "boolean"
                    },
                    "mode": {
                      "type": "string",
                      "enum": ["client", "setup", "offline"]
                    },
                    "ssid": {
                      "type": ["string", "null"]
                    },
                    "ip": {
                      "type": ["string", "null"]
                    },
                    "setup": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "ssid": {
                              "type": "string"
                            },
                            "url": {
                              "type": "string"
                            },
                            "until": {
                              "type": "string"
                            }
                          },
                          "required": ["ssid", "url", "until"],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "lastError": {
                      "type": ["string", "null"]
                    }
                  },
                  "required": ["available", "mode", "ssid", "ip", "setup", "lastError"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "network-stopSetup",
        "summary": "Close the setup hotspot and rejoin the saved network",
        "tags": ["network"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "available": {
                      "type": "boolean"
                    },
                    "mode": {
                      "type": "string",
                      "enum": ["client", "setup", "offline"]
                    },
                    "ssid": {
                      "type": ["string", "null"]
                    },
                    "ip": {
                      "type": ["string", "null"]
                    },
                    "setup": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "ssid": {
                              "type": "string"
                            },
                            "url": {
                              "type": "string"
                            },
                            "until": {
                              "type": "string"
                            }
                          },
                          "required": ["ssid", "url", "until"],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "lastError": {
                      "type": ["string", "null"]
                    }
                  },
                  "required": ["available", "mode", "ssid", "ip", "setup", "lastError"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/network/wifi/connect": {
      "post": {
        "operationId": "network-connect",
        "summary": "Save a network and switch to it a moment after replying",
        "tags": ["network"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ssid": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "password": {
                    "type": "string",
                    "maxLength": 63
                  }
                },
                "required": ["ssid"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "detail": {
                      "type": "string"
                    }
                  },
                  "required": ["ok", "detail"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/sensors": {
      "get": {
        "operationId": "sensors-latest",
        "summary": "Latest reading for every sensor",
        "tags": ["sensors"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "propertyNames": {
                    "type": "string",
                    "enum": [
                      "air_temp",
                      "humidity",
                      "pcb_temp",
                      "water_distance",
                      "water_level_pct",
                      "pump_v",
                      "pump_a",
                      "pump_w",
                      "ph",
                      "ec",
                      "water_temp"
                    ]
                  },
                  "additionalProperties": {
                    "type": "object",
                    "properties": {
                      "ts": {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                      },
                      "value": {
                        "type": "number"
                      },
                      "unit": {
                        "type": "string"
                      },
                      "quality": {
                        "default": "good",
                        "type": "string",
                        "enum": ["good", "stale", "suspect"]
                      }
                    },
                    "required": ["ts", "value", "unit", "quality"],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/sensors/{id}": {
      "get": {
        "operationId": "sensors-read",
        "tags": ["sensors"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string",
              "enum": [
                "air_temp",
                "humidity",
                "pcb_temp",
                "water_distance",
                "water_level_pct",
                "pump_v",
                "pump_a",
                "pump_w",
                "ph",
                "ec",
                "water_temp"
              ]
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ts": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                    },
                    "value": {
                      "type": "number"
                    },
                    "unit": {
                      "type": "string"
                    },
                    "quality": {
                      "default": "good",
                      "type": "string",
                      "enum": ["good", "stale", "suspect"]
                    }
                  },
                  "required": ["ts", "value", "unit", "quality"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/sensors/{id}/calibrate": {
      "post": {
        "operationId": "sensors-calibrate",
        "summary": "Store a calibration point on a pH, EC or RTD probe (EZO)",
        "description": "pH: `mid` first, then optional `low`/`high`. EC: `dry`, then `single` or `low`+`high`. RTD: `single`. `clear` wipes stored points. `value` is the reference solution in the reported unit (pH, mS/cm, \u00b0C).",
        "tags": ["sensors"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string",
              "enum": [
                "air_temp",
                "humidity",
                "pcb_temp",
                "water_distance",
                "water_level_pct",
                "pump_v",
                "pump_a",
                "pump_w",
                "ph",
                "ec",
                "water_temp"
              ]
            },
            "required": true
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "point": {
                    "type": "string",
                    "enum": ["mid", "low", "high", "dry", "single", "clear"]
                  },
                  "value": {
                    "type": "number"
                  }
                },
                "required": ["point"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ts": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                    },
                    "point": {
                      "type": "string",
                      "enum": ["mid", "low", "high", "dry", "single", "clear"]
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "points": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "detail": {
                      "default": "",
                      "type": "string"
                    }
                  },
                  "required": ["ts", "point", "ok", "points", "detail"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/devices": {
      "get": {
        "operationId": "devices-list",
        "summary": "Configured sensor devices (with probe status) and the kinds that can be added",
        "tags": ["devices"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sensors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "addr": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "ids": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "air_temp",
                                "humidity",
                                "pcb_temp",
                                "water_distance",
                                "water_level_pct",
                                "pump_v",
                                "pump_a",
                                "pump_w",
                                "ph",
                                "ec",
                                "water_temp"
                              ]
                            }
                          },
                          "source": {
                            "type": "string",
                            "enum": ["config", "user"]
                          },
                          "status": {
                            "type": "string",
                            "enum": ["ready", "absent"]
                          },
                          "detail": {
                            "type": "string"
                          }
                        },
                        "required": ["kind", "label", "addr", "ids", "source", "status", "detail"],
                        "additionalProperties": false
                      }
                    },
                    "addable": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "ids": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "air_temp",
                                "humidity",
                                "pcb_temp",
                                "water_distance",
                                "water_level_pct",
                                "pump_v",
                                "pump_a",
                                "pump_w",
                                "ph",
                                "ec",
                                "water_temp"
                              ]
                            }
                          },
                          "bus": {
                            "type": "string"
                          },
                          "defaultAddr": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "calibration": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "point": {
                                  "type": "string",
                                  "enum": ["mid", "low", "high", "dry", "single", "clear"]
                                },
                                "label": {
                                  "type": "string"
                                },
                                "instruction": {
                                  "type": "string"
                                },
                                "defaultValue": {
                                  "type": ["number", "null"]
                                },
                                "optional": {
                                  "type": "boolean"
                                }
                              },
                              "required": [
                                "point",
                                "label",
                                "instruction",
                                "defaultValue",
                                "optional"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "kind",
                          "label",
                          "description",
                          "ids",
                          "bus",
                          "defaultAddr",
                          "calibration"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": ["sensors", "addable"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/devices/sensors": {
      "post": {
        "operationId": "devices-addSensor",
        "summary": "Add a probe of an addable kind at an I\u00b2C address; it goes live without a restart",
        "description": "Refused (412) when the kind is not addable, the address is outside 0x08\u20130x77 or already used, the quantity is already installed, or the probe does not answer.",
        "tags": ["devices"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "minLength": 1
                  },
                  "addr": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 127
                  }
                },
                "required": ["kind", "addr"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "requestId": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "detail": {
                      "type": "string"
                    }
                  },
                  "required": ["requestId", "ok", "detail"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/devices/sensors/{kind}/{addr}": {
      "delete": {
        "operationId": "devices-removeSensor",
        "summary": "Remove a probe that was added from the app (sensors from hal.toml are refused)",
        "tags": ["devices"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "kind",
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true
          },
          {
            "in": "path",
            "name": "addr",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 127
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "requestId": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "detail": {
                      "type": "string"
                    }
                  },
                  "required": ["requestId", "ok", "detail"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/telemetry/{sensor}": {
      "get": {
        "operationId": "telemetry-history",
        "summary": "Downsampled history for a sensor",
        "tags": ["sensors"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "sensor",
            "schema": {
              "type": "string",
              "enum": [
                "air_temp",
                "humidity",
                "pcb_temp",
                "water_distance",
                "water_level_pct",
                "pump_v",
                "pump_a",
                "pump_w",
                "ph",
                "ec",
                "water_temp"
              ]
            },
            "required": true
          },
          {
            "in": "query",
            "name": "hours",
            "schema": {
              "default": 24,
              "type": "number",
              "minimum": 1,
              "maximum": 2160
            }
          },
          {
            "in": "query",
            "name": "maxPoints",
            "schema": {
              "default": 300,
              "type": "integer",
              "minimum": 10,
              "maximum": 2000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "ts": {
                        "type": "string"
                      },
                      "value": {
                        "type": "number"
                      }
                    },
                    "required": ["ts", "value"],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/telemetry/light-hours": {
      "get": {
        "operationId": "telemetry-lightHours",
        "summary": "Cumulative grow-light hours (LED aging)",
        "tags": ["sensors"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "hours": {
                      "type": "number"
                    },
                    "ratedHours": {
                      "type": "number"
                    },
                    "pctUsed": {
                      "type": "number"
                    }
                  },
                  "required": ["hours", "ratedHours", "pctUsed"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/light": {
      "get": {
        "operationId": "light-get",
        "tags": ["light"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "on": {
                          "type": "boolean"
                        },
                        "level": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 100
                        },
                        "since": {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                        },
                        "fault": {
                          "default": null,
                          "type": ["string", "null"]
                        },
                        "remainingS": {
                          "default": null,
                          "anyOf": [
                            {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 9007199254740991
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": ["on", "level", "since", "fault", "remainingS"],
                      "additionalProperties": false
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "light-set",
        "summary": "Turn the grow light on/off and set brightness 0\u2013100",
        "tags": ["light"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "on": {
                    "type": "boolean"
                  },
                  "level": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 100
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "on": {
                      "type": "boolean"
                    },
                    "level": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "since": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                    },
                    "fault": {
                      "default": null,
                      "type": ["string", "null"]
                    },
                    "remainingS": {
                      "default": null,
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": ["on", "level", "since", "fault", "remainingS"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/light/owner": {
      "get": {
        "operationId": "light-owner",
        "summary": "Who controls the light now: manual hold, Autopilot or the schedule",
        "tags": ["light"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "source": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": ["manual", "autopilot", "schedule"]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "level": {
                      "type": ["number", "null"]
                    },
                    "leaseId": {
                      "type": ["string", "null"]
                    },
                    "manualUntil": {
                      "type": ["string", "null"]
                    },
                    "schedule": {
                      "type": ["number", "null"]
                    }
                  },
                  "required": ["source", "level", "leaseId", "manualUntil", "schedule"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/light/resume": {
      "post": {
        "operationId": "light-resume",
        "summary": "End a manual hold and hand the light back to Autopilot or the schedule",
        "tags": ["light"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "source": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": ["manual", "autopilot", "schedule"]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "level": {
                      "type": ["number", "null"]
                    },
                    "leaseId": {
                      "type": ["string", "null"]
                    },
                    "manualUntil": {
                      "type": ["string", "null"]
                    },
                    "schedule": {
                      "type": ["number", "null"]
                    }
                  },
                  "required": ["source", "level", "leaseId", "manualUntil", "schedule"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/pump": {
      "get": {
        "operationId": "pump-get",
        "tags": ["pump"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "on": {
                          "type": "boolean"
                        },
                        "level": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 100
                        },
                        "since": {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                        },
                        "fault": {
                          "default": null,
                          "type": ["string", "null"]
                        },
                        "remainingS": {
                          "default": null,
                          "anyOf": [
                            {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 9007199254740991
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": ["on", "level", "since", "fault", "remainingS"],
                      "additionalProperties": false
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "pump-set",
        "summary": "Run the pump; every run is bounded by the HAL max-run limit and the dry-run interlock",
        "tags": ["pump"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "on": {
                    "type": "boolean"
                  },
                  "level": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 100
                  },
                  "durationS": {
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "on": {
                      "type": "boolean"
                    },
                    "level": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "since": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                    },
                    "fault": {
                      "default": null,
                      "type": ["string", "null"]
                    },
                    "remainingS": {
                      "default": null,
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": ["on", "level", "since", "fault", "remainingS"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/pump/run-once": {
      "post": {
        "operationId": "pump-runOnce",
        "summary": "Run the pump for N seconds at a speed",
        "tags": ["pump"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "durationS": {
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991
                  },
                  "level": {
                    "type": "number",
                    "minimum": 1,
                    "maximum": 100
                  }
                },
                "required": ["durationS"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "on": {
                      "type": "boolean"
                    },
                    "level": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "since": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                    },
                    "fault": {
                      "default": null,
                      "type": ["string", "null"]
                    },
                    "remainingS": {
                      "default": null,
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": ["on", "level", "since", "fault", "remainingS"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/pump/stop": {
      "post": {
        "operationId": "pump-stop",
        "tags": ["pump"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "on": {
                      "type": "boolean"
                    },
                    "level": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "since": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                    },
                    "fault": {
                      "default": null,
                      "type": ["string", "null"]
                    },
                    "remainingS": {
                      "default": null,
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": ["on", "level", "since", "fault", "remainingS"],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/schedules": {
      "get": {
        "operationId": "schedules-list",
        "tags": ["schedules"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "kind": {
                        "type": "string",
                        "enum": ["light", "pump"]
                      },
                      "name": {
                        "type": "string"
                      },
                      "enabled": {
                        "type": "boolean"
                      },
                      "days": {
                        "type": "number"
                      },
                      "spec": {
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "setpoints": {
                                "maxItems": 24,
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "minute": {
                                      "type": "integer",
                                      "minimum": 0,
                                      "maximum": 1439
                                    },
                                    "level": {
                                      "type": "number",
                                      "minimum": 0,
                                      "maximum": 100
                                    }
                                  },
                                  "required": ["minute", "level"],
                                  "additionalProperties": false
                                }
                              }
                            },
                            "required": ["setpoints"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "minute": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1439
                              },
                              "durationS": {
                                "type": "integer",
                                "exclusiveMinimum": 0,
                                "maximum": 3600
                              },
                              "level": {
                                "type": "number",
                                "minimum": 1,
                                "maximum": 100
                              }
                            },
                            "required": ["minute", "durationS"],
                            "additionalProperties": false
                          }
                        ]
                      },
                      "createdAt": {
                        "type": "string"
                      },
                      "updatedAt": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "kind",
                      "name",
                      "enabled",
                      "days",
                      "spec",
                      "createdAt",
                      "updatedAt"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/schedules/{id}": {
      "put": {
        "operationId": "schedules-upsert",
        "summary": "Create or replace a light curve or pump cycle",
        "tags": ["schedules"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": ["light", "pump"]
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "days": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 127
                  },
                  "spec": {
                    "anyOf": [
                      {
                        "type": "object",
                        "properties": {
                          "setpoints": {
                            "maxItems": 24,
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "minute": {
                                  "type": "integer",
                                  "minimum": 0,
                                  "maximum": 1439
                                },
                                "level": {
                                  "type": "number",
                                  "minimum": 0,
                                  "maximum": 100
                                }
                              },
                              "required": ["minute", "level"]
                            }
                          }
                        },
                        "required": ["setpoints"]
                      },
                      {
                        "type": "object",
                        "properties": {
                          "minute": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 1439
                          },
                          "durationS": {
                            "type": "integer",
                            "exclusiveMinimum": 0,
                            "maximum": 3600
                          },
                          "level": {
                            "type": "number",
                            "minimum": 1,
                            "maximum": 100
                          }
                        },
                        "required": ["minute", "durationS"]
                      }
                    ]
                  }
                },
                "required": ["kind", "name", "enabled", "days", "spec"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string",
                      "enum": ["light", "pump"]
                    },
                    "name": {
                      "type": "string"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "days": {
                      "type": "number"
                    },
                    "spec": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "setpoints": {
                              "maxItems": 24,
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "minute": {
                                    "type": "integer",
                                    "minimum": 0,
                                    "maximum": 1439
                                  },
                                  "level": {
                                    "type": "number",
                                    "minimum": 0,
                                    "maximum": 100
                                  }
                                },
                                "required": ["minute", "level"],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": ["setpoints"],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "minute": {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 1439
                            },
                            "durationS": {
                              "type": "integer",
                              "exclusiveMinimum": 0,
                              "maximum": 3600
                            },
                            "level": {
                              "type": "number",
                              "minimum": 1,
                              "maximum": 100
                            }
                          },
                          "required": ["minute", "durationS"],
                          "additionalProperties": false
                        }
                      ]
                    },
                    "createdAt": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "kind",
                    "name",
                    "enabled",
                    "days",
                    "spec",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "schedules-remove",
        "tags": ["schedules"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "removed": {
                      "type": "boolean"
                    }
                  },
                  "required": ["removed"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/schedules/runs": {
      "get": {
        "operationId": "schedules-recentRuns",
        "tags": ["schedules"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "scheduleId": {
                        "type": "string"
                      },
                      "key": {
                        "type": "string"
                      },
                      "firedAt": {
                        "type": "string"
                      },
                      "result": {
                        "type": "string"
                      }
                    },
                    "required": ["scheduleId", "key", "firedAt", "result"],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/automations/signals": {
      "get": {
        "operationId": "automations-catalog",
        "summary": "Signals rules can read, with units; liveOnly ones are unknown in a backtest",
        "tags": ["autopilot"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "key": {
                        "type": "string"
                      },
                      "label": {
                        "type": "string"
                      },
                      "unit": {
                        "type": "string"
                      },
                      "group": {
                        "type": "string"
                      },
                      "liveOnly": {
                        "type": "boolean"
                      }
                    },
                    "required": ["key", "label", "unit", "group", "liveOnly"],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/automations": {
      "get": {
        "operationId": "automations-list",
        "tags": ["autopilot"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "number"
                      },
                      "name": {
                        "type": "string"
                      },
                      "enabled": {
                        "type": "boolean"
                      },
                      "dryRun": {
                        "type": "boolean"
                      },
                      "priority": {
                        "type": "number"
                      },
                      "cooldownMin": {
                        "type": ["number", "null"]
                      },
                      "trigger": {
                        "oneOf": [
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "tick"
                              },
                              "everyMin": {
                                "type": "integer",
                                "minimum": 1,
                                "maximum": 1440
                              }
                            },
                            "required": ["kind", "everyMin"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "signalChange"
                              },
                              "signal": {
                                "type": "string",
                                "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$"
                              }
                            },
                            "required": ["kind", "signal"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "timeOfDay"
                              },
                              "at": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                              },
                              "days": {
                                "minItems": 1,
                                "type": "array",
                                "items": {
                                  "type": "string",
                                  "enum": [
                                    "monday",
                                    "tuesday",
                                    "wednesday",
                                    "thursday",
                                    "friday",
                                    "saturday",
                                    "sunday"
                                  ]
                                }
                              }
                            },
                            "required": ["kind", "at"],
                            "additionalProperties": false
                          }
                        ],
                        "type": "object"
                      },
                      "conditions": {
                        "$ref": "#/components/schemas/__schema2"
                      },
                      "actions": {
                        "type": "array",
                        "items": {
                          "oneOf": [
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "const": "notify"
                                },
                                "message": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 200
                                }
                              },
                              "required": ["kind", "message"],
                              "additionalProperties": false
                            },
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "const": "setLight"
                                },
                                "level": {
                                  "$ref": "#/components/schemas/__schema3"
                                },
                                "clamp": {
                                  "type": "object",
                                  "properties": {
                                    "min": {
                                      "type": "number",
                                      "minimum": 0,
                                      "maximum": 100
                                    },
                                    "max": {
                                      "type": "number",
                                      "minimum": 0,
                                      "maximum": 100
                                    }
                                  },
                                  "required": ["min", "max"],
                                  "additionalProperties": false
                                },
                                "mode": {
                                  "type": "string",
                                  "enum": ["policy", "one-shot"]
                                },
                                "holdMinutes": {
                                  "type": "integer",
                                  "minimum": 1,
                                  "maximum": 1440
                                }
                              },
                              "required": ["kind", "level"],
                              "additionalProperties": false
                            },
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "const": "runPump"
                                },
                                "durationS": {
                                  "$ref": "#/components/schemas/__schema3"
                                },
                                "level": {
                                  "type": "number",
                                  "minimum": 1,
                                  "maximum": 100
                                }
                              },
                              "required": ["kind", "durationS"],
                              "additionalProperties": false
                            },
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "const": "stopPump"
                                }
                              },
                              "required": ["kind"],
                              "additionalProperties": false
                            },
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "const": "dose"
                                },
                                "doser": {
                                  "type": "string",
                                  "enum": ["dose_1", "dose_2", "dose_3"]
                                },
                                "durationS": {
                                  "$ref": "#/components/schemas/__schema3"
                                }
                              },
                              "required": ["kind", "doser", "durationS"],
                              "additionalProperties": false
                            },
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "const": "setPodStatus"
                                },
                                "slot": {
                                  "type": "integer",
                                  "minimum": 1,
                                  "maximum": 30
                                },
                                "status": {
                                  "type": "string",
                                  "enum": ["empty", "seeded", "growing", "harvest", "attention"]
                                }
                              },
                              "required": ["kind", "slot", "status"],
                              "additionalProperties": false
                            }
                          ],
                          "type": "object"
                        }
                      },
                      "createdAt": {
                        "type": "string"
                      },
                      "updatedAt": {
                        "type": "string"
                      },
                      "lastRun": {
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "number"
                              },
                              "automationId": {
                                "type": "number"
                              },
                              "firedAt": {
                                "type": "string"
                              },
                              "outcome": {
                                "type": "string",
                                "enum": [
                                  "fired",
                                  "skipped",
                                  "clamped",
                                  "dry_run",
                                  "refused",
                                  "error"
                                ]
                              },
                              "detail": {}
                            },
                            "required": ["id", "automationId", "firedAt", "outcome", "detail"],
                            "additionalProperties": false
                          },
                          {
                            "type": "null"
                          }
                        ]
                      }
                    },
                    "required": [
                      "id",
                      "name",
                      "enabled",
                      "dryRun",
                      "priority",
                      "cooldownMin",
                      "trigger",
                      "conditions",
                      "actions",
                      "createdAt",
                      "updatedAt",
                      "lastRun"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "automations-create",
        "summary": "Create a rule. New rules start in dry-run unless dryRun is false.",
        "tags": ["autopilot"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "enabled": {
                    "default": true,
                    "type": "boolean"
                  },
                  "dryRun": {
                    "default": true,
                    "type": "boolean"
                  },
                  "priority": {
                    "default": 50,
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100
                  },
                  "cooldownMin": {
                    "default": null,
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 10080
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "trigger": {
                    "oneOf": [
                      {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "const": "tick"
                          },
                          "everyMin": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 1440
                          }
                        },
                        "required": ["kind", "everyMin"]
                      },
                      {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "const": "signalChange"
                          },
                          "signal": {
                            "type": "string",
                            "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$"
                          }
                        },
                        "required": ["kind", "signal"]
                      },
                      {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "const": "timeOfDay"
                          },
                          "at": {
                            "type": "string",
                            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                          },
                          "days": {
                            "minItems": 1,
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "monday",
                                "tuesday",
                                "wednesday",
                                "thursday",
                                "friday",
                                "saturday",
                                "sunday"
                              ]
                            }
                          }
                        },
                        "required": ["kind", "at"]
                      }
                    ],
                    "type": "object"
                  },
                  "conditions": {
                    "$ref": "#/components/schemas/__schema0"
                  },
                  "actions": {
                    "minItems": 1,
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "oneOf": [
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "notify"
                            },
                            "message": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 200
                            }
                          },
                          "required": ["kind", "message"]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "setLight"
                            },
                            "level": {
                              "$ref": "#/components/schemas/__schema1"
                            },
                            "clamp": {
                              "type": "object",
                              "properties": {
                                "min": {
                                  "type": "number",
                                  "minimum": 0,
                                  "maximum": 100
                                },
                                "max": {
                                  "type": "number",
                                  "minimum": 0,
                                  "maximum": 100
                                }
                              },
                              "required": ["min", "max"]
                            },
                            "mode": {
                              "type": "string",
                              "enum": ["policy", "one-shot"]
                            },
                            "holdMinutes": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 1440
                            }
                          },
                          "required": ["kind", "level"]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "runPump"
                            },
                            "durationS": {
                              "$ref": "#/components/schemas/__schema1"
                            },
                            "level": {
                              "type": "number",
                              "minimum": 1,
                              "maximum": 100
                            }
                          },
                          "required": ["kind", "durationS"]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "stopPump"
                            }
                          },
                          "required": ["kind"]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "dose"
                            },
                            "doser": {
                              "type": "string",
                              "enum": ["dose_1", "dose_2", "dose_3"]
                            },
                            "durationS": {
                              "$ref": "#/components/schemas/__schema1"
                            }
                          },
                          "required": ["kind", "doser", "durationS"]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "setPodStatus"
                            },
                            "slot": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 30
                            },
                            "status": {
                              "type": "string",
                              "enum": ["empty", "seeded", "growing", "harvest", "attention"]
                            }
                          },
                          "required": ["kind", "slot", "status"]
                        }
                      ],
                      "type": "object"
                    }
                  }
                },
                "required": ["name", "trigger", "conditions", "actions"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "number"
                    },
                    "name": {
                      "type": "string"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "dryRun": {
                      "type": "boolean"
                    },
                    "priority": {
                      "type": "number"
                    },
                    "cooldownMin": {
                      "type": ["number", "null"]
                    },
                    "trigger": {
                      "oneOf": [
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "tick"
                            },
                            "everyMin": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 1440
                            }
                          },
                          "required": ["kind", "everyMin"],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "signalChange"
                            },
                            "signal": {
                              "type": "string",
                              "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$"
                            }
                          },
                          "required": ["kind", "signal"],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "timeOfDay"
                            },
                            "at": {
                              "type": "string",
                              "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                            },
                            "days": {
                              "minItems": 1,
                              "type": "array",
                              "items": {
                                "type": "string",
                                "enum": [
                                  "monday",
                                  "tuesday",
                                  "wednesday",
                                  "thursday",
                                  "friday",
                                  "saturday",
                                  "sunday"
                                ]
                              }
                            }
                          },
                          "required": ["kind", "at"],
                          "additionalProperties": false
                        }
                      ],
                      "type": "object"
                    },
                    "conditions": {
                      "$ref": "#/components/schemas/__schema2"
                    },
                    "actions": {
                      "type": "array",
                      "items": {
                        "oneOf": [
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "notify"
                              },
                              "message": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 200
                              }
                            },
                            "required": ["kind", "message"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "setLight"
                              },
                              "level": {
                                "$ref": "#/components/schemas/__schema3"
                              },
                              "clamp": {
                                "type": "object",
                                "properties": {
                                  "min": {
                                    "type": "number",
                                    "minimum": 0,
                                    "maximum": 100
                                  },
                                  "max": {
                                    "type": "number",
                                    "minimum": 0,
                                    "maximum": 100
                                  }
                                },
                                "required": ["min", "max"],
                                "additionalProperties": false
                              },
                              "mode": {
                                "type": "string",
                                "enum": ["policy", "one-shot"]
                              },
                              "holdMinutes": {
                                "type": "integer",
                                "minimum": 1,
                                "maximum": 1440
                              }
                            },
                            "required": ["kind", "level"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "runPump"
                              },
                              "durationS": {
                                "$ref": "#/components/schemas/__schema3"
                              },
                              "level": {
                                "type": "number",
                                "minimum": 1,
                                "maximum": 100
                              }
                            },
                            "required": ["kind", "durationS"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "stopPump"
                              }
                            },
                            "required": ["kind"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "dose"
                              },
                              "doser": {
                                "type": "string",
                                "enum": ["dose_1", "dose_2", "dose_3"]
                              },
                              "durationS": {
                                "$ref": "#/components/schemas/__schema3"
                              }
                            },
                            "required": ["kind", "doser", "durationS"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "setPodStatus"
                              },
                              "slot": {
                                "type": "integer",
                                "minimum": 1,
                                "maximum": 30
                              },
                              "status": {
                                "type": "string",
                                "enum": ["empty", "seeded", "growing", "harvest", "attention"]
                              }
                            },
                            "required": ["kind", "slot", "status"],
                            "additionalProperties": false
                          }
                        ],
                        "type": "object"
                      }
                    },
                    "createdAt": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "enabled",
                    "dryRun",
                    "priority",
                    "cooldownMin",
                    "trigger",
                    "conditions",
                    "actions",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/automations/status": {
      "get": {
        "operationId": "automations-status",
        "summary": "Kill switch, last tick, live light leases and per-rule state",
        "tags": ["autopilot"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "enabled": {
                      "type": "boolean"
                    },
                    "lastTickAt": {
                      "type": ["string", "null"]
                    },
                    "leases": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "level": {
                            "type": "number"
                          },
                          "expiresAt": {
                            "type": "string"
                          }
                        },
                        "required": ["id", "level", "expiresAt"],
                        "additionalProperties": false
                      }
                    },
                    "rules": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "number"
                          },
                          "condition": {
                            "type": ["boolean", "null"]
                          },
                          "lastFiredAt": {
                            "type": ["string", "null"]
                          },
                          "actionsLastHour": {
                            "type": "number"
                          },
                          "cooldownUntil": {
                            "type": ["string", "null"]
                          }
                        },
                        "required": [
                          "id",
                          "condition",
                          "lastFiredAt",
                          "actionsLastHour",
                          "cooldownUntil"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "light": {
                      "type": "object",
                      "properties": {
                        "source": {
                          "anyOf": [
                            {
                              "type": "string",
                              "enum": ["manual", "autopilot", "schedule"]
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "level": {
                          "type": ["number", "null"]
                        },
                        "leaseId": {
                          "type": ["string", "null"]
                        },
                        "manualUntil": {
                          "type": ["string", "null"]
                        },
                        "schedule": {
                          "type": ["number", "null"]
                        }
                      },
                      "required": ["source", "level", "leaseId", "manualUntil", "schedule"],
                      "additionalProperties": false
                    }
                  },
                  "required": ["enabled", "lastTickAt", "leases", "rules", "light"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/automations/runs": {
      "get": {
        "operationId": "automations-runs",
        "summary": "The audit log, newest first: every evaluation where a rule's trigger was active",
        "tags": ["autopilot"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "automationId",
            "schema": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "number"
                      },
                      "automationId": {
                        "type": "number"
                      },
                      "firedAt": {
                        "type": "string"
                      },
                      "outcome": {
                        "type": "string",
                        "enum": ["fired", "skipped", "clamped", "dry_run", "refused", "error"]
                      },
                      "detail": {}
                    },
                    "required": ["id", "automationId", "firedAt", "outcome", "detail"],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/automations/{id}": {
      "get": {
        "operationId": "automations-get",
        "tags": ["autopilot"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "number"
                    },
                    "name": {
                      "type": "string"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "dryRun": {
                      "type": "boolean"
                    },
                    "priority": {
                      "type": "number"
                    },
                    "cooldownMin": {
                      "type": ["number", "null"]
                    },
                    "trigger": {
                      "oneOf": [
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "tick"
                            },
                            "everyMin": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 1440
                            }
                          },
                          "required": ["kind", "everyMin"],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "signalChange"
                            },
                            "signal": {
                              "type": "string",
                              "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$"
                            }
                          },
                          "required": ["kind", "signal"],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "timeOfDay"
                            },
                            "at": {
                              "type": "string",
                              "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                            },
                            "days": {
                              "minItems": 1,
                              "type": "array",
                              "items": {
                                "type": "string",
                                "enum": [
                                  "monday",
                                  "tuesday",
                                  "wednesday",
                                  "thursday",
                                  "friday",
                                  "saturday",
                                  "sunday"
                                ]
                              }
                            }
                          },
                          "required": ["kind", "at"],
                          "additionalProperties": false
                        }
                      ],
                      "type": "object"
                    },
                    "conditions": {
                      "$ref": "#/components/schemas/__schema2"
                    },
                    "actions": {
                      "type": "array",
                      "items": {
                        "oneOf": [
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "notify"
                              },
                              "message": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 200
                              }
                            },
                            "required": ["kind", "message"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "setLight"
                              },
                              "level": {
                                "$ref": "#/components/schemas/__schema3"
                              },
                              "clamp": {
                                "type": "object",
                                "properties": {
                                  "min": {
                                    "type": "number",
                                    "minimum": 0,
                                    "maximum": 100
                                  },
                                  "max": {
                                    "type": "number",
                                    "minimum": 0,
                                    "maximum": 100
                                  }
                                },
                                "required": ["min", "max"],
                                "additionalProperties": false
                              },
                              "mode": {
                                "type": "string",
                                "enum": ["policy", "one-shot"]
                              },
                              "holdMinutes": {
                                "type": "integer",
                                "minimum": 1,
                                "maximum": 1440
                              }
                            },
                            "required": ["kind", "level"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "runPump"
                              },
                              "durationS": {
                                "$ref": "#/components/schemas/__schema3"
                              },
                              "level": {
                                "type": "number",
                                "minimum": 1,
                                "maximum": 100
                              }
                            },
                            "required": ["kind", "durationS"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "stopPump"
                              }
                            },
                            "required": ["kind"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "dose"
                              },
                              "doser": {
                                "type": "string",
                                "enum": ["dose_1", "dose_2", "dose_3"]
                              },
                              "durationS": {
                                "$ref": "#/components/schemas/__schema3"
                              }
                            },
                            "required": ["kind", "doser", "durationS"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "setPodStatus"
                              },
                              "slot": {
                                "type": "integer",
                                "minimum": 1,
                                "maximum": 30
                              },
                              "status": {
                                "type": "string",
                                "enum": ["empty", "seeded", "growing", "harvest", "attention"]
                              }
                            },
                            "required": ["kind", "slot", "status"],
                            "additionalProperties": false
                          }
                        ],
                        "type": "object"
                      }
                    },
                    "createdAt": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "enabled",
                    "dryRun",
                    "priority",
                    "cooldownMin",
                    "trigger",
                    "conditions",
                    "actions",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "automations-update",
        "tags": ["autopilot"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "required": true
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "enabled": {
                    "default": true,
                    "type": "boolean"
                  },
                  "dryRun": {
                    "default": true,
                    "type": "boolean"
                  },
                  "priority": {
                    "default": 50,
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100
                  },
                  "cooldownMin": {
                    "default": null,
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 10080
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "trigger": {
                    "oneOf": [
                      {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "const": "tick"
                          },
                          "everyMin": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 1440
                          }
                        },
                        "required": ["kind", "everyMin"]
                      },
                      {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "const": "signalChange"
                          },
                          "signal": {
                            "type": "string",
                            "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$"
                          }
                        },
                        "required": ["kind", "signal"]
                      },
                      {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "const": "timeOfDay"
                          },
                          "at": {
                            "type": "string",
                            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                          },
                          "days": {
                            "minItems": 1,
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "monday",
                                "tuesday",
                                "wednesday",
                                "thursday",
                                "friday",
                                "saturday",
                                "sunday"
                              ]
                            }
                          }
                        },
                        "required": ["kind", "at"]
                      }
                    ],
                    "type": "object"
                  },
                  "conditions": {
                    "$ref": "#/components/schemas/__schema0"
                  },
                  "actions": {
                    "minItems": 1,
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "oneOf": [
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "notify"
                            },
                            "message": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 200
                            }
                          },
                          "required": ["kind", "message"]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "setLight"
                            },
                            "level": {
                              "$ref": "#/components/schemas/__schema1"
                            },
                            "clamp": {
                              "type": "object",
                              "properties": {
                                "min": {
                                  "type": "number",
                                  "minimum": 0,
                                  "maximum": 100
                                },
                                "max": {
                                  "type": "number",
                                  "minimum": 0,
                                  "maximum": 100
                                }
                              },
                              "required": ["min", "max"]
                            },
                            "mode": {
                              "type": "string",
                              "enum": ["policy", "one-shot"]
                            },
                            "holdMinutes": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 1440
                            }
                          },
                          "required": ["kind", "level"]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "runPump"
                            },
                            "durationS": {
                              "$ref": "#/components/schemas/__schema1"
                            },
                            "level": {
                              "type": "number",
                              "minimum": 1,
                              "maximum": 100
                            }
                          },
                          "required": ["kind", "durationS"]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "stopPump"
                            }
                          },
                          "required": ["kind"]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "dose"
                            },
                            "doser": {
                              "type": "string",
                              "enum": ["dose_1", "dose_2", "dose_3"]
                            },
                            "durationS": {
                              "$ref": "#/components/schemas/__schema1"
                            }
                          },
                          "required": ["kind", "doser", "durationS"]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "setPodStatus"
                            },
                            "slot": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 30
                            },
                            "status": {
                              "type": "string",
                              "enum": ["empty", "seeded", "growing", "harvest", "attention"]
                            }
                          },
                          "required": ["kind", "slot", "status"]
                        }
                      ],
                      "type": "object"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "number"
                    },
                    "name": {
                      "type": "string"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "dryRun": {
                      "type": "boolean"
                    },
                    "priority": {
                      "type": "number"
                    },
                    "cooldownMin": {
                      "type": ["number", "null"]
                    },
                    "trigger": {
                      "oneOf": [
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "tick"
                            },
                            "everyMin": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 1440
                            }
                          },
                          "required": ["kind", "everyMin"],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "signalChange"
                            },
                            "signal": {
                              "type": "string",
                              "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$"
                            }
                          },
                          "required": ["kind", "signal"],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "timeOfDay"
                            },
                            "at": {
                              "type": "string",
                              "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                            },
                            "days": {
                              "minItems": 1,
                              "type": "array",
                              "items": {
                                "type": "string",
                                "enum": [
                                  "monday",
                                  "tuesday",
                                  "wednesday",
                                  "thursday",
                                  "friday",
                                  "saturday",
                                  "sunday"
                                ]
                              }
                            }
                          },
                          "required": ["kind", "at"],
                          "additionalProperties": false
                        }
                      ],
                      "type": "object"
                    },
                    "conditions": {
                      "$ref": "#/components/schemas/__schema2"
                    },
                    "actions": {
                      "type": "array",
                      "items": {
                        "oneOf": [
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "notify"
                              },
                              "message": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 200
                              }
                            },
                            "required": ["kind", "message"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "setLight"
                              },
                              "level": {
                                "$ref": "#/components/schemas/__schema3"
                              },
                              "clamp": {
                                "type": "object",
                                "properties": {
                                  "min": {
                                    "type": "number",
                                    "minimum": 0,
                                    "maximum": 100
                                  },
                                  "max": {
                                    "type": "number",
                                    "minimum": 0,
                                    "maximum": 100
                                  }
                                },
                                "required": ["min", "max"],
                                "additionalProperties": false
                              },
                              "mode": {
                                "type": "string",
                                "enum": ["policy", "one-shot"]
                              },
                              "holdMinutes": {
                                "type": "integer",
                                "minimum": 1,
                                "maximum": 1440
                              }
                            },
                            "required": ["kind", "level"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "runPump"
                              },
                              "durationS": {
                                "$ref": "#/components/schemas/__schema3"
                              },
                              "level": {
                                "type": "number",
                                "minimum": 1,
                                "maximum": 100
                              }
                            },
                            "required": ["kind", "durationS"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "stopPump"
                              }
                            },
                            "required": ["kind"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "dose"
                              },
                              "doser": {
                                "type": "string",
                                "enum": ["dose_1", "dose_2", "dose_3"]
                              },
                              "durationS": {
                                "$ref": "#/components/schemas/__schema3"
                              }
                            },
                            "required": ["kind", "doser", "durationS"],
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "setPodStatus"
                              },
                              "slot": {
                                "type": "integer",
                                "minimum": 1,
                                "maximum": 30
                              },
                              "status": {
                                "type": "string",
                                "enum": ["empty", "seeded", "growing", "harvest", "attention"]
                              }
                            },
                            "required": ["kind", "slot", "status"],
                            "additionalProperties": false
                          }
                        ],
                        "type": "object"
                      }
                    },
                    "createdAt": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "enabled",
                    "dryRun",
                    "priority",
                    "cooldownMin",
                    "trigger",
                    "conditions",
                    "actions",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "automations-remove",
        "tags": ["autopilot"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "removed": {
                      "type": "boolean"
                    }
                  },
                  "required": ["removed"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/autopilot/enabled": {
      "put": {
        "operationId": "automations-setGlobal",
        "summary": "The kill switch: off stops every rule and releases the light",
        "tags": ["autopilot"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  }
                },
                "required": ["enabled"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "enabled": {
                      "type": "boolean"
                    }
                  },
                  "required": ["enabled"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/automations/backtest": {
      "post": {
        "operationId": "automations-backtest",
        "summary": "Replay a saved rule (id) or a draft (rule) over recorded history without touching hardware",
        "tags": ["autopilot"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "rule": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 80
                      },
                      "enabled": {
                        "default": true,
                        "type": "boolean"
                      },
                      "dryRun": {
                        "default": true,
                        "type": "boolean"
                      },
                      "priority": {
                        "default": 50,
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 100
                      },
                      "cooldownMin": {
                        "default": null,
                        "anyOf": [
                          {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 10080
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "trigger": {
                        "oneOf": [
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "tick"
                              },
                              "everyMin": {
                                "type": "integer",
                                "minimum": 1,
                                "maximum": 1440
                              }
                            },
                            "required": ["kind", "everyMin"]
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "signalChange"
                              },
                              "signal": {
                                "type": "string",
                                "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$"
                              }
                            },
                            "required": ["kind", "signal"]
                          },
                          {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "const": "timeOfDay"
                              },
                              "at": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                              },
                              "days": {
                                "minItems": 1,
                                "type": "array",
                                "items": {
                                  "type": "string",
                                  "enum": [
                                    "monday",
                                    "tuesday",
                                    "wednesday",
                                    "thursday",
                                    "friday",
                                    "saturday",
                                    "sunday"
                                  ]
                                }
                              }
                            },
                            "required": ["kind", "at"]
                          }
                        ],
                        "type": "object"
                      },
                      "conditions": {
                        "$ref": "#/components/schemas/__schema0"
                      },
                      "actions": {
                        "minItems": 1,
                        "maxItems": 10,
                        "type": "array",
                        "items": {
                          "oneOf": [
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "const": "notify"
                                },
                                "message": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 200
                                }
                              },
                              "required": ["kind", "message"]
                            },
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "const": "setLight"
                                },
                                "level": {
                                  "$ref": "#/components/schemas/__schema1"
                                },
                                "clamp": {
                                  "type": "object",
                                  "properties": {
                                    "min": {
                                      "type": "number",
                                      "minimum": 0,
                                      "maximum": 100
                                    },
                                    "max": {
                                      "type": "number",
                                      "minimum": 0,
                                      "maximum": 100
                                    }
                                  },
                                  "required": ["min", "max"]
                                },
                                "mode": {
                                  "type": "string",
                                  "enum": ["policy", "one-shot"]
                                },
                                "holdMinutes": {
                                  "type": "integer",
                                  "minimum": 1,
                                  "maximum": 1440
                                }
                              },
                              "required": ["kind", "level"]
                            },
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "const": "runPump"
                                },
                                "durationS": {
                                  "$ref": "#/components/schemas/__schema1"
                                },
                                "level": {
                                  "type": "number",
                                  "minimum": 1,
                                  "maximum": 100
                                }
                              },
                              "required": ["kind", "durationS"]
                            },
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "const": "stopPump"
                                }
                              },
                              "required": ["kind"]
                            },
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "const": "dose"
                                },
                                "doser": {
                                  "type": "string",
                                  "enum": ["dose_1", "dose_2", "dose_3"]
                                },
                                "durationS": {
                                  "$ref": "#/components/schemas/__schema1"
                                }
                              },
                              "required": ["kind", "doser", "durationS"]
                            },
                            {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "const": "setPodStatus"
                                },
                                "slot": {
                                  "type": "integer",
                                  "minimum": 1,
                                  "maximum": 30
                                },
                                "status": {
                                  "type": "string",
                                  "enum": ["empty", "seeded", "growing", "harvest", "attention"]
                                }
                              },
                              "required": ["kind", "slot", "status"]
                            }
                          ],
                          "type": "object"
                        }
                      }
                    },
                    "required": ["name", "trigger", "conditions", "actions"]
                  },
                  "hours": {
                    "default": 24,
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 336
                  },
                  "stepMin": {
                    "default": 5,
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 60
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "from": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    },
                    "stepMin": {
                      "type": "number"
                    },
                    "times": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "traces": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "unit": {
                            "type": "string"
                          },
                          "values": {
                            "type": "array",
                            "items": {
                              "type": ["number", "null"]
                            }
                          }
                        },
                        "required": ["key", "label", "unit", "values"],
                        "additionalProperties": false
                      }
                    },
                    "liveOnly": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "fires": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "at": {
                            "type": "string"
                          },
                          "outcome": {
                            "type": "string",
                            "enum": ["fired", "skipped", "clamped", "dry_run", "refused", "error"]
                          },
                          "actions": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string"
                                },
                                "raw": {
                                  "type": "number"
                                },
                                "value": {
                                  "type": "number"
                                },
                                "clamped": {
                                  "type": "boolean"
                                },
                                "dryRun": {
                                  "type": "boolean"
                                },
                                "sent": {
                                  "type": "boolean"
                                },
                                "antiThrash": {
                                  "type": "boolean"
                                },
                                "skipped": {
                                  "type": "string"
                                },
                                "refused": {
                                  "type": "string"
                                },
                                "error": {
                                  "type": "string"
                                }
                              },
                              "required": ["kind"],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": ["at", "outcome", "actions"],
                        "additionalProperties": false
                      }
                    },
                    "suppressed": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "at": {
                            "type": "string"
                          },
                          "reason": {
                            "type": "string"
                          }
                        },
                        "required": ["at", "reason"],
                        "additionalProperties": false
                      }
                    },
                    "summary": {
                      "type": "object",
                      "properties": {
                        "fires": {
                          "type": "number"
                        },
                        "suppressed": {
                          "type": "number"
                        },
                        "unknownSteps": {
                          "type": "number"
                        },
                        "disabledAt": {
                          "type": ["string", "null"]
                        }
                      },
                      "required": ["fires", "suppressed", "unknownSteps", "disabledAt"],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "from",
                    "to",
                    "stepMin",
                    "times",
                    "traces",
                    "liveOnly",
                    "fires",
                    "suppressed",
                    "summary"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/grow": {
      "get": {
        "operationId": "grow-current",
        "tags": ["grow"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "cycle": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "startedAt": {
                              "type": "string"
                            },
                            "endedAt": {
                              "type": ["string", "null"]
                            },
                            "stage": {
                              "type": "string",
                              "enum": ["germination", "seedling", "vegetative", "harvest", "ended"]
                            },
                            "notes": {
                              "type": "string"
                            },
                            "issued": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          },
                          "required": ["id", "startedAt", "endedAt", "stage", "notes", "issued"],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "day": {
                      "type": ["number", "null"]
                    }
                  },
                  "required": ["cycle", "day"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/grow/start": {
      "post": {
        "operationId": "grow-start",
        "summary": "Start a new grow cycle (ends any open one)",
        "tags": ["grow"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "notes": {
                    "default": "",
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "startedAt": {
                      "type": "string"
                    },
                    "endedAt": {
                      "type": ["string", "null"]
                    },
                    "stage": {
                      "type": "string",
                      "enum": ["germination", "seedling", "vegetative", "harvest", "ended"]
                    },
                    "notes": {
                      "type": "string"
                    },
                    "issued": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": ["id", "startedAt", "endedAt", "stage", "notes", "issued"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/grow/stage": {
      "post": {
        "operationId": "grow-setStage",
        "tags": ["grow"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "stage": {
                    "type": "string",
                    "enum": ["germination", "seedling", "vegetative", "harvest", "ended"]
                  }
                },
                "required": ["stage"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "startedAt": {
                          "type": "string"
                        },
                        "endedAt": {
                          "type": ["string", "null"]
                        },
                        "stage": {
                          "type": "string",
                          "enum": ["germination", "seedling", "vegetative", "harvest", "ended"]
                        },
                        "notes": {
                          "type": "string"
                        },
                        "issued": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      },
                      "required": ["id", "startedAt", "endedAt", "stage", "notes", "issued"],
                      "additionalProperties": false
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/grow/end": {
      "post": {
        "operationId": "grow-end",
        "tags": ["grow"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "startedAt": {
                          "type": "string"
                        },
                        "endedAt": {
                          "type": ["string", "null"]
                        },
                        "stage": {
                          "type": "string",
                          "enum": ["germination", "seedling", "vegetative", "harvest", "ended"]
                        },
                        "notes": {
                          "type": "string"
                        },
                        "issued": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      },
                      "required": ["id", "startedAt", "endedAt", "stage", "notes", "issued"],
                      "additionalProperties": false
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/grow/history": {
      "get": {
        "operationId": "grow-history",
        "tags": ["grow"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "startedAt": {
                        "type": "string"
                      },
                      "endedAt": {
                        "type": ["string", "null"]
                      },
                      "stage": {
                        "type": "string",
                        "enum": ["germination", "seedling", "vegetative", "harvest", "ended"]
                      },
                      "notes": {
                        "type": "string"
                      },
                      "issued": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    },
                    "required": ["id", "startedAt", "endedAt", "stage", "notes", "issued"],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/pods": {
      "get": {
        "operationId": "grow-pods",
        "tags": ["grow"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "slot": {
                        "type": "number"
                      },
                      "plant": {
                        "type": ["string", "null"]
                      },
                      "plantedAt": {
                        "type": ["string", "null"]
                      },
                      "status": {
                        "type": "string",
                        "enum": ["empty", "seeded", "growing", "harvest", "attention"]
                      },
                      "notes": {
                        "type": "string"
                      },
                      "updatedAt": {
                        "type": "string"
                      }
                    },
                    "required": ["slot", "plant", "plantedAt", "status", "notes", "updatedAt"],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/pods/{slot}": {
      "patch": {
        "operationId": "grow-updatePod",
        "tags": ["grow"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "slot",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 60
            },
            "required": true
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "plant": {
                    "type": ["string", "null"]
                  },
                  "plantedAt": {
                    "type": ["string", "null"]
                  },
                  "status": {
                    "type": "string",
                    "enum": ["empty", "seeded", "growing", "harvest", "attention"]
                  },
                  "notes": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "slot": {
                      "type": "number"
                    },
                    "plant": {
                      "type": ["string", "null"]
                    },
                    "plantedAt": {
                      "type": ["string", "null"]
                    },
                    "status": {
                      "type": "string",
                      "enum": ["empty", "seeded", "growing", "harvest", "attention"]
                    },
                    "notes": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string"
                    }
                  },
                  "required": ["slot", "plant", "plantedAt", "status", "notes", "updatedAt"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/captures": {
      "get": {
        "operationId": "camera-list",
        "tags": ["camera"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "camera",
            "schema": {
              "type": "string",
              "enum": ["upper", "lower"]
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "camera": {
                        "type": "string",
                        "enum": ["upper", "lower"]
                      },
                      "ts": {
                        "type": "string"
                      },
                      "path": {
                        "type": "string"
                      },
                      "bytes": {
                        "type": "number"
                      },
                      "url": {
                        "type": "string"
                      }
                    },
                    "required": ["id", "camera", "ts", "path", "bytes", "url"],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/camera/{camera}/capture": {
      "post": {
        "operationId": "camera-capture",
        "summary": "Take a still now",
        "tags": ["camera"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "camera",
            "schema": {
              "type": "string",
              "enum": ["upper", "lower"]
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "camera": {
                      "type": "string",
                      "enum": ["upper", "lower"]
                    },
                    "ts": {
                      "type": "string"
                    },
                    "path": {
                      "type": "string"
                    },
                    "bytes": {
                      "type": "number"
                    },
                    "url": {
                      "type": "string"
                    }
                  },
                  "required": ["id", "camera", "ts", "path", "bytes", "url"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/vision/pods": {
      "get": {
        "operationId": "vision-podTrends",
        "summary": "Per-pod green-area trend from the primary analyser",
        "tags": ["vision"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "analyzer",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "slot": {
                        "type": "number"
                      },
                      "green": {
                        "type": ["number", "null"]
                      },
                      "verdict": {
                        "type": "string",
                        "enum": ["growing", "stalled", "declining", "unknown"]
                      },
                      "slope": {
                        "type": "number"
                      },
                      "samples": {
                        "type": "number"
                      }
                    },
                    "required": ["slot", "green", "verdict", "slope", "samples"],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/vision/pods/{slot}": {
      "get": {
        "operationId": "vision-podSeries",
        "tags": ["vision"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "slot",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 60
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "ts": {
                        "type": "string"
                      },
                      "green": {
                        "type": "number"
                      },
                      "captureId": {
                        "type": "string"
                      }
                    },
                    "required": ["ts", "green", "captureId"],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/vision/analyzers": {
      "get": {
        "operationId": "vision-analyzers",
        "summary": "Analysers on the unit and any that posted results, with row counts and which is primary",
        "tags": ["vision"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "version": {
                        "type": "number"
                      },
                      "label": {
                        "type": "string"
                      },
                      "description": {
                        "type": "string"
                      },
                      "metrics": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "name": {
                              "type": "string"
                            },
                            "label": {
                              "type": "string"
                            },
                            "unit": {
                              "type": "string"
                            },
                            "description": {
                              "type": "string"
                            }
                          },
                          "required": ["name", "label", "description"],
                          "additionalProperties": false
                        }
                      },
                      "runsOn": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "enum": ["device", "remote"]
                        }
                      },
                      "source": {
                        "type": "string",
                        "enum": ["device", "remote"]
                      },
                      "primary": {
                        "type": "boolean"
                      },
                      "rows": {
                        "type": "number"
                      },
                      "captures": {
                        "type": "number"
                      },
                      "firstTs": {
                        "type": ["string", "null"]
                      },
                      "lastTs": {
                        "type": ["string", "null"]
                      }
                    },
                    "required": [
                      "id",
                      "version",
                      "label",
                      "description",
                      "metrics",
                      "runsOn",
                      "source",
                      "primary",
                      "rows",
                      "captures",
                      "firstTs",
                      "lastTs"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/vision/status": {
      "get": {
        "operationId": "vision-status",
        "summary": "Analysis queue: running, waiting, dropped, failed, re-run progress",
        "tags": ["vision"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "running": {
                      "type": ["string", "null"]
                    },
                    "waiting": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "dropped": {
                      "type": "number"
                    },
                    "failed": {
                      "type": "number"
                    },
                    "backfill": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "analyzer": {
                              "type": "string"
                            },
                            "done": {
                              "type": "number"
                            },
                            "total": {
                              "type": "number"
                            }
                          },
                          "required": ["analyzer", "done", "total"],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": ["running", "waiting", "dropped", "failed", "backfill"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/vision/compare/{slot}": {
      "get": {
        "operationId": "vision-compare",
        "summary": "One pod's series from every analyser@version, for side-by-side comparison",
        "tags": ["vision"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "slot",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 60
            },
            "required": true
          },
          {
            "in": "query",
            "name": "metric",
            "schema": {
              "default": "green_fraction",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 200,
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "analyzer": {
                        "type": "string"
                      },
                      "version": {
                        "type": "number"
                      },
                      "source": {
                        "type": "string",
                        "enum": ["device", "remote"]
                      },
                      "points": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "ts": {
                              "type": "string"
                            },
                            "value": {
                              "type": "number"
                            },
                            "captureId": {
                              "type": "string"
                            }
                          },
                          "required": ["ts", "value", "captureId"],
                          "additionalProperties": false
                        }
                      }
                    },
                    "required": ["analyzer", "version", "source", "points"],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/vision/captures/{captureId}": {
      "get": {
        "operationId": "vision-capture",
        "summary": "Every analyser's results for one capture",
        "tags": ["vision"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "captureId",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "captureId": {
                        "type": "string"
                      },
                      "ts": {
                        "type": "string"
                      },
                      "camera": {
                        "type": "string",
                        "enum": ["upper", "lower"]
                      },
                      "analyzer": {
                        "type": "string"
                      },
                      "version": {
                        "type": "number"
                      },
                      "source": {
                        "type": "string",
                        "enum": ["device", "remote"]
                      },
                      "slot": {
                        "type": "number"
                      },
                      "metric": {
                        "type": "string"
                      },
                      "value": {
                        "type": "number"
                      },
                      "detail": {
                        "anyOf": [
                          {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {}
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "artifact": {
                        "type": ["string", "null"]
                      }
                    },
                    "required": [
                      "captureId",
                      "ts",
                      "camera",
                      "analyzer",
                      "version",
                      "source",
                      "slot",
                      "metric",
                      "value",
                      "detail",
                      "artifact"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/vision/primary": {
      "put": {
        "operationId": "vision-setPrimary",
        "summary": "Choose the analyser that drives pod trends",
        "tags": ["vision"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "analyzer": {
                    "type": "string"
                  }
                },
                "required": ["analyzer"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "analyzer": {
                      "type": "string"
                    }
                  },
                  "required": ["analyzer"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/vision/analyzers/{analyzer}/rerun": {
      "post": {
        "operationId": "vision-rerun",
        "summary": "Re-score stored captures with one on-device analyser, in the background",
        "tags": ["vision"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "analyzer",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "limit": {
                    "default": 2000,
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 5000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "captures": {
                      "type": "number"
                    }
                  },
                  "required": ["captures"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/datasets/summary": {
      "get": {
        "operationId": "datasets-summary",
        "summary": "What a dataset export of this window would contain (download it from GET /api/datasets/export)",
        "tags": ["datasets"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "from",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "to",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "images",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "from": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    },
                    "images": {
                      "type": "boolean"
                    },
                    "captures": {
                      "type": "number"
                    },
                    "analyses": {
                      "type": "number"
                    },
                    "telemetry": {
                      "type": "number"
                    },
                    "imageBytes": {
                      "type": "number"
                    }
                  },
                  "required": [
                    "from",
                    "to",
                    "images",
                    "captures",
                    "analyses",
                    "telemetry",
                    "imageBytes"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/storage/flash": {
      "get": {
        "operationId": "storage-flash",
        "summary": "SD card writes: bytes per day (7-day average, or since boot until a day of samples exists), written since boot, card size",
        "tags": ["storage"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "available": {
                      "type": "boolean"
                    },
                    "device": {
                      "type": ["string", "null"]
                    },
                    "cardBytes": {
                      "type": ["number", "null"]
                    },
                    "sinceBootBytes": {
                      "type": ["number", "null"]
                    },
                    "uptimeS": {
                      "type": ["number", "null"]
                    },
                    "bytesPerDay": {
                      "type": ["number", "null"]
                    },
                    "basis": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": ["history", "boot"]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "windowDays": {
                      "type": ["number", "null"]
                    },
                    "lastSampleAt": {
                      "type": ["string", "null"]
                    }
                  },
                  "required": [
                    "available",
                    "device",
                    "cardBytes",
                    "sinceBootBytes",
                    "uptimeS",
                    "bytesPerDay",
                    "basis",
                    "windowDays",
                    "lastSampleAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/storage/mirror": {
      "get": {
        "operationId": "storage-mirror",
        "summary": "Off-device mirror status: enabled, uploads pending/done/failed, last error",
        "tags": ["storage"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "available": {
                      "type": "boolean"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "pending": {
                      "type": "number"
                    },
                    "uploaded": {
                      "type": "number"
                    },
                    "failed": {
                      "type": "number"
                    },
                    "lastError": {
                      "type": ["string", "null"]
                    },
                    "lastUploadAt": {
                      "type": ["string", "null"]
                    }
                  },
                  "required": [
                    "available",
                    "enabled",
                    "pending",
                    "uploaded",
                    "failed",
                    "lastError",
                    "lastUploadAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/storage/mirror/test": {
      "post": {
        "operationId": "storage-testMirror",
        "summary": "Write, read back and delete a probe object with the saved mirror settings",
        "tags": ["storage"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "detail": {
                      "type": "string"
                    }
                  },
                  "required": ["ok", "detail"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/storage/mirror/sync": {
      "post": {
        "operationId": "storage-syncMirror",
        "summary": "Copy the stills and artifacts already on the unit to the mirror",
        "tags": ["storage"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "queued": {
                      "type": "number"
                    }
                  },
                  "required": ["queued"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/backup": {
      "get": {
        "operationId": "backup-status",
        "summary": "Last off-card backup, nightly bucket uploads, and whether backup_stale is raised",
        "tags": ["backup"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "available": {
                      "type": "boolean"
                    },
                    "lastSuccess": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "number"
                            },
                            "ts": {
                              "type": "string"
                            },
                            "destination": {
                              "type": "string",
                              "enum": ["download", "bucket"]
                            },
                            "name": {
                              "type": "string"
                            },
                            "bytes": {
                              "type": "number"
                            },
                            "ok": {
                              "type": "boolean"
                            },
                            "detail": {
                              "type": "string"
                            }
                          },
                          "required": ["id", "ts", "destination", "name", "bytes", "ok", "detail"],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "lastBucketAttempt": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "number"
                            },
                            "ts": {
                              "type": "string"
                            },
                            "destination": {
                              "type": "string",
                              "enum": ["download", "bucket"]
                            },
                            "name": {
                              "type": "string"
                            },
                            "bytes": {
                              "type": "number"
                            },
                            "ok": {
                              "type": "boolean"
                            },
                            "detail": {
                              "type": "string"
                            }
                          },
                          "required": ["id", "ts", "destination", "name", "bytes", "ok", "detail"],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "nightly": {
                      "type": "object",
                      "properties": {
                        "enabled": {
                          "type": "boolean"
                        },
                        "hour": {
                          "type": "number"
                        },
                        "keep": {
                          "type": "number"
                        }
                      },
                      "required": ["enabled", "hour", "keep"],
                      "additionalProperties": false
                    },
                    "staleAfterDays": {
                      "type": "number"
                    },
                    "stale": {
                      "type": "boolean"
                    },
                    "recent": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "number"
                          },
                          "ts": {
                            "type": "string"
                          },
                          "destination": {
                            "type": "string",
                            "enum": ["download", "bucket"]
                          },
                          "name": {
                            "type": "string"
                          },
                          "bytes": {
                            "type": "number"
                          },
                          "ok": {
                            "type": "boolean"
                          },
                          "detail": {
                            "type": "string"
                          }
                        },
                        "required": ["id", "ts", "destination", "name", "bytes", "ok", "detail"],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "available",
                    "lastSuccess",
                    "lastBucketAttempt",
                    "nightly",
                    "staleAfterDays",
                    "stale",
                    "recent"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/backup/run": {
      "post": {
        "operationId": "backup-runNow",
        "summary": "Back up to the mirror's bucket now (the nightly upload, early)",
        "tags": ["backup"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "number"
                    },
                    "ts": {
                      "type": "string"
                    },
                    "destination": {
                      "type": "string",
                      "enum": ["download", "bucket"]
                    },
                    "name": {
                      "type": "string"
                    },
                    "bytes": {
                      "type": "number"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "detail": {
                      "type": "string"
                    }
                  },
                  "required": ["id", "ts", "destination", "name", "bytes", "ok", "detail"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/backup/bucket": {
      "get": {
        "operationId": "backup-list",
        "summary": "Backups in the mirror's bucket (backups/), newest first",
        "tags": ["backup"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "key": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "unit": {
                        "type": ["string", "null"]
                      },
                      "createdAt": {
                        "type": "string"
                      },
                      "size": {
                        "type": "number"
                      }
                    },
                    "required": ["key", "name", "unit", "createdAt", "size"],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/backup/browse": {
      "post": {
        "operationId": "backup-browse",
        "summary": "List the backups in a bucket that isn't saved yet (Welcome \u2192 Restore); the saved mirror when config is omitted",
        "tags": ["backup"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "config": {
                    "type": "object",
                    "properties": {
                      "endpoint": {
                        "type": "string",
                        "format": "uri"
                      },
                      "bucket": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 63
                      },
                      "region": {
                        "default": "auto",
                        "type": "string",
                        "minLength": 1
                      },
                      "prefix": {
                        "default": "",
                        "type": "string"
                      },
                      "accessKeyId": {
                        "type": "string",
                        "minLength": 1
                      },
                      "secretAccessKey": {
                        "type": "string",
                        "minLength": 1
                      }
                    },
                    "required": ["endpoint", "bucket", "accessKeyId", "secretAccessKey"]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "key": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "unit": {
                        "type": ["string", "null"]
                      },
                      "createdAt": {
                        "type": "string"
                      },
                      "size": {
                        "type": "number"
                      }
                    },
                    "required": ["key", "name", "unit", "createdAt", "size"],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/backup/restore": {
      "get": {
        "operationId": "backup-restoreInfo",
        "summary": "Whether restore is installed, the last restore or undo, and what an undo would put back",
        "tags": ["backup"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "available": {
                      "type": "boolean"
                    },
                    "status": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "op": {
                              "type": "string",
                              "enum": ["restore", "undo", "check"]
                            },
                            "state": {
                              "type": "string",
                              "enum": [
                                "checking",
                                "queued",
                                "stopping",
                                "restoring",
                                "starting",
                                "done",
                                "failed",
                                "refused"
                              ]
                            },
                            "at": {
                              "type": "string"
                            },
                            "error": {
                              "type": "string"
                            },
                            "code": {
                              "type": "string"
                            },
                            "bundle": {
                              "type": "object",
                              "properties": {
                                "createdAt": {
                                  "type": ["string", "null"]
                                },
                                "unit": {
                                  "anyOf": [
                                    {
                                      "type": "object",
                                      "properties": {
                                        "id": {
                                          "type": ["string", "null"]
                                        },
                                        "name": {
                                          "type": "string"
                                        }
                                      },
                                      "required": ["id", "name"],
                                      "additionalProperties": false
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "core": {
                                  "type": ["string", "null"]
                                },
                                "schema": {
                                  "type": ["number", "null"]
                                },
                                "photos": {
                                  "type": "boolean"
                                }
                              },
                              "required": ["createdAt", "unit", "core", "schema", "photos"],
                              "additionalProperties": false
                            },
                            "undone": {
                              "type": "boolean"
                            }
                          },
                          "required": ["op", "state", "at"],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "undo": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "restoredAt": {
                              "type": "string"
                            },
                            "bundle": {
                              "type": "object",
                              "properties": {
                                "createdAt": {
                                  "type": ["string", "null"]
                                },
                                "unit": {
                                  "anyOf": [
                                    {
                                      "type": "object",
                                      "properties": {
                                        "id": {
                                          "type": ["string", "null"]
                                        },
                                        "name": {
                                          "type": "string"
                                        }
                                      },
                                      "required": ["id", "name"],
                                      "additionalProperties": false
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "core": {
                                  "type": ["string", "null"]
                                },
                                "schema": {
                                  "type": ["number", "null"]
                                },
                                "photos": {
                                  "type": "boolean"
                                }
                              },
                              "required": ["createdAt", "unit", "core", "schema", "photos"],
                              "additionalProperties": false
                            },
                            "undoneAt": {
                              "type": ["string", "null"]
                            }
                          },
                          "required": ["restoredAt", "bundle", "undoneAt"],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": ["available", "status", "undo"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/backup/restore-from-bucket": {
      "post": {
        "operationId": "backup-restoreFromBucket",
        "summary": "Restore a backup from the bucket. The bundle is checked first; then the unit restarts on it (upload a file with POST /api/backup/restore)",
        "tags": ["backup"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "key": {
                    "type": "string",
                    "minLength": 1
                  },
                  "config": {
                    "type": "object",
                    "properties": {
                      "endpoint": {
                        "type": "string",
                        "format": "uri"
                      },
                      "bucket": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 63
                      },
                      "region": {
                        "default": "auto",
                        "type": "string",
                        "minLength": 1
                      },
                      "prefix": {
                        "default": "",
                        "type": "string"
                      },
                      "accessKeyId": {
                        "type": "string",
                        "minLength": 1
                      },
                      "secretAccessKey": {
                        "type": "string",
                        "minLength": 1
                      }
                    },
                    "required": ["endpoint", "bucket", "accessKeyId", "secretAccessKey"]
                  }
                },
                "required": ["key"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "restarting": {
                      "type": "boolean",
                      "const": true
                    },
                    "bundle": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "createdAt": {
                              "type": ["string", "null"]
                            },
                            "unit": {
                              "anyOf": [
                                {
                                  "type": "object",
                                  "properties": {
                                    "id": {
                                      "type": ["string", "null"]
                                    },
                                    "name": {
                                      "type": "string"
                                    }
                                  },
                                  "required": ["id", "name"],
                                  "additionalProperties": false
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "core": {
                              "type": ["string", "null"]
                            },
                            "schema": {
                              "type": ["number", "null"]
                            },
                            "photos": {
                              "type": "boolean"
                            }
                          },
                          "required": ["createdAt", "unit", "core", "schema", "photos"],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": ["restarting", "bundle"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/backup/undo": {
      "post": {
        "operationId": "backup-undo",
        "summary": "Put back what the last restore replaced; again to redo it. The unit restarts",
        "tags": ["backup"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "restarting": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": ["restarting"],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/alerts": {
      "get": {
        "operationId": "alerts-list",
        "tags": ["alerts"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "query",
            "name": "activeOnly",
            "schema": {
              "default": true,
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "number"
                      },
                      "kind": {
                        "type": "string"
                      },
                      "active": {
                        "type": "boolean"
                      },
                      "detail": {
                        "type": "string"
                      },
                      "raisedAt": {
                        "type": "string"
                      },
                      "clearedAt": {
                        "type": ["string", "null"]
                      },
                      "acknowledgedAt": {
                        "type": ["string", "null"]
                      },
                      "dismissedAt": {
                        "type": ["string", "null"]
                      }
                    },
                    "required": [
                      "id",
                      "kind",
                      "active",
                      "detail",
                      "raisedAt",
                      "clearedAt",
                      "acknowledgedAt",
                      "dismissedAt"
                    ],
                    "additionalProperties": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.NOT_FOUND"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/alerts/{id}/acknowledge": {
      "post": {
        "operationId": "alerts-acknowledge",
        "summary": "Acknowledge an alert; clears a latched hardware fault so the actuator may re-enable",
        "tags": ["alerts"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "number"
                        },
                        "kind": {
                          "type": "string"
                        },
                        "active": {
                          "type": "boolean"
                        },
                        "detail": {
                          "type": "string"
                        },
                        "raisedAt": {
                          "type": "string"
                        },
                        "clearedAt": {
                          "type": ["string", "null"]
                        },
                        "acknowledgedAt": {
                          "type": ["string", "null"]
                        },
                        "dismissedAt": {
                          "type": ["string", "null"]
                        }
                      },
                      "required": [
                        "id",
                        "kind",
                        "active",
                        "detail",
                        "raisedAt",
                        "clearedAt",
                        "acknowledgedAt",
                        "dismissedAt"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    },
    "/alerts/{id}/dismiss": {
      "post": {
        "operationId": "alerts-dismiss",
        "tags": ["alerts"],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "number"
                        },
                        "kind": {
                          "type": "string"
                        },
                        "active": {
                          "type": "boolean"
                        },
                        "detail": {
                          "type": "string"
                        },
                        "raisedAt": {
                          "type": "string"
                        },
                        "clearedAt": {
                          "type": ["string", "null"]
                        },
                        "acknowledgedAt": {
                          "type": ["string", "null"]
                        },
                        "dismissedAt": {
                          "type": ["string", "null"]
                        }
                      },
                      "required": [
                        "id",
                        "kind",
                        "active",
                        "detail",
                        "raisedAt",
                        "clearedAt",
                        "acknowledgedAt",
                        "dismissedAt"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid input data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Authorization not provided",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.UNAUTHORIZED"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.FORBIDDEN"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/error.INTERNAL_SERVER_ERROR"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "__schema0": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "and"
              },
              "conditions": {
                "maxItems": 20,
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/__schema0"
                }
              }
            },
            "required": ["kind", "conditions"]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "or"
              },
              "conditions": {
                "minItems": 1,
                "maxItems": 20,
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/__schema0"
                }
              }
            },
            "required": ["kind", "conditions"]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "not"
              },
              "condition": {
                "$ref": "#/components/schemas/__schema0"
              }
            },
            "required": ["kind", "condition"]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "compare"
              },
              "op": {
                "type": "string",
                "enum": [">", ">=", "<", "<=", "==", "!="]
              },
              "left": {
                "$ref": "#/components/schemas/__schema1"
              },
              "right": {
                "$ref": "#/components/schemas/__schema1"
              }
            },
            "required": ["kind", "op", "left", "right"]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "between"
              },
              "subject": {
                "$ref": "#/components/schemas/__schema1"
              },
              "min": {
                "$ref": "#/components/schemas/__schema1"
              },
              "max": {
                "$ref": "#/components/schemas/__schema1"
              }
            },
            "required": ["kind", "subject", "min", "max"]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "timeBetween"
              },
              "start": {
                "type": "string",
                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
              },
              "end": {
                "type": "string",
                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
              }
            },
            "required": ["kind", "start", "end"]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "onDays"
              },
              "days": {
                "minItems": 1,
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "monday",
                    "tuesday",
                    "wednesday",
                    "thursday",
                    "friday",
                    "saturday",
                    "sunday"
                  ]
                }
              }
            },
            "required": ["kind", "days"]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "sustained"
              },
              "condition": {
                "$ref": "#/components/schemas/__schema0"
              },
              "forMin": {
                "type": "integer",
                "minimum": 1,
                "maximum": 1440
              }
            },
            "required": ["kind", "condition", "forMin"]
          }
        ],
        "type": "object"
      },
      "__schema1": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "literal"
              },
              "value": {
                "type": "number"
              }
            },
            "required": ["kind", "value"]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "signal"
              },
              "signal": {
                "type": "string",
                "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$"
              }
            },
            "required": ["kind", "signal"]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "window"
              },
              "fn": {
                "type": "string",
                "enum": ["avg", "min", "max", "sum", "count"]
              },
              "signal": {
                "type": "string",
                "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$"
              },
              "lastMin": {
                "type": "integer",
                "minimum": 1,
                "maximum": 1440
              }
            },
            "required": ["kind", "fn", "signal", "lastMin"]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "binary"
              },
              "op": {
                "type": "string",
                "enum": ["+", "-", "*", "/"]
              },
              "left": {
                "$ref": "#/components/schemas/__schema1"
              },
              "right": {
                "$ref": "#/components/schemas/__schema1"
              }
            },
            "required": ["kind", "op", "left", "right"]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "clamp"
              },
              "value": {
                "$ref": "#/components/schemas/__schema1"
              },
              "min": {
                "$ref": "#/components/schemas/__schema1"
              },
              "max": {
                "$ref": "#/components/schemas/__schema1"
              }
            },
            "required": ["kind", "value", "min", "max"]
          }
        ],
        "type": "object"
      },
      "error.BAD_REQUEST": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "The error message",
            "example": "Invalid input data"
          },
          "code": {
            "type": "string",
            "description": "The error code",
            "example": "BAD_REQUEST"
          },
          "issues": {
            "description": "An array of issues that were responsible for the error",
            "example": [],
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "message": {
                  "type": "string"
                }
              },
              "required": ["message"],
              "additionalProperties": false
            }
          }
        },
        "required": ["message", "code"],
        "additionalProperties": false,
        "title": "Invalid input data error (400)",
        "description": "The error information",
        "example": {
          "code": "BAD_REQUEST",
          "message": "Invalid input data",
          "issues": []
        }
      },
      "error.UNAUTHORIZED": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "The error message",
            "example": "Authorization not provided"
          },
          "code": {
            "type": "string",
            "description": "The error code",
            "example": "UNAUTHORIZED"
          },
          "issues": {
            "description": "An array of issues that were responsible for the error",
            "example": [],
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "message": {
                  "type": "string"
                }
              },
              "required": ["message"],
              "additionalProperties": false
            }
          }
        },
        "required": ["message", "code"],
        "additionalProperties": false,
        "title": "Authorization not provided error (401)",
        "description": "The error information",
        "example": {
          "code": "UNAUTHORIZED",
          "message": "Authorization not provided",
          "issues": []
        }
      },
      "error.FORBIDDEN": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "The error message",
            "example": "Insufficient access"
          },
          "code": {
            "type": "string",
            "description": "The error code",
            "example": "FORBIDDEN"
          },
          "issues": {
            "description": "An array of issues that were responsible for the error",
            "example": [],
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "message": {
                  "type": "string"
                }
              },
              "required": ["message"],
              "additionalProperties": false
            }
          }
        },
        "required": ["message", "code"],
        "additionalProperties": false,
        "title": "Insufficient access error (403)",
        "description": "The error information",
        "example": {
          "code": "FORBIDDEN",
          "message": "Insufficient access",
          "issues": []
        }
      },
      "error.NOT_FOUND": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "The error message",
            "example": "Not found"
          },
          "code": {
            "type": "string",
            "description": "The error code",
            "example": "NOT_FOUND"
          },
          "issues": {
            "description": "An array of issues that were responsible for the error",
            "example": [],
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "message": {
                  "type": "string"
                }
              },
              "required": ["message"],
              "additionalProperties": false
            }
          }
        },
        "required": ["message", "code"],
        "additionalProperties": false,
        "title": "Not found error (404)",
        "description": "The error information",
        "example": {
          "code": "NOT_FOUND",
          "message": "Not found",
          "issues": []
        }
      },
      "error.INTERNAL_SERVER_ERROR": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "The error message",
            "example": "Internal server error"
          },
          "code": {
            "type": "string",
            "description": "The error code",
            "example": "INTERNAL_SERVER_ERROR"
          },
          "issues": {
            "description": "An array of issues that were responsible for the error",
            "example": [],
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "message": {
                  "type": "string"
                }
              },
              "required": ["message"],
              "additionalProperties": false
            }
          }
        },
        "required": ["message", "code"],
        "additionalProperties": false,
        "title": "Internal server error error (500)",
        "description": "The error information",
        "example": {
          "code": "INTERNAL_SERVER_ERROR",
          "message": "Internal server error",
          "issues": []
        }
      },
      "__schema2": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "and"
              },
              "conditions": {
                "maxItems": 20,
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/__schema2"
                }
              }
            },
            "required": ["kind", "conditions"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "or"
              },
              "conditions": {
                "minItems": 1,
                "maxItems": 20,
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/__schema2"
                }
              }
            },
            "required": ["kind", "conditions"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "not"
              },
              "condition": {
                "$ref": "#/components/schemas/__schema2"
              }
            },
            "required": ["kind", "condition"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "compare"
              },
              "op": {
                "type": "string",
                "enum": [">", ">=", "<", "<=", "==", "!="]
              },
              "left": {
                "$ref": "#/components/schemas/__schema3"
              },
              "right": {
                "$ref": "#/components/schemas/__schema3"
              }
            },
            "required": ["kind", "op", "left", "right"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "between"
              },
              "subject": {
                "$ref": "#/components/schemas/__schema3"
              },
              "min": {
                "$ref": "#/components/schemas/__schema3"
              },
              "max": {
                "$ref": "#/components/schemas/__schema3"
              }
            },
            "required": ["kind", "subject", "min", "max"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "timeBetween"
              },
              "start": {
                "type": "string",
                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
              },
              "end": {
                "type": "string",
                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
              }
            },
            "required": ["kind", "start", "end"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "onDays"
              },
              "days": {
                "minItems": 1,
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "monday",
                    "tuesday",
                    "wednesday",
                    "thursday",
                    "friday",
                    "saturday",
                    "sunday"
                  ]
                }
              }
            },
            "required": ["kind", "days"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "sustained"
              },
              "condition": {
                "$ref": "#/components/schemas/__schema2"
              },
              "forMin": {
                "type": "integer",
                "minimum": 1,
                "maximum": 1440
              }
            },
            "required": ["kind", "condition", "forMin"],
            "additionalProperties": false
          }
        ],
        "type": "object"
      },
      "__schema3": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "literal"
              },
              "value": {
                "type": "number"
              }
            },
            "required": ["kind", "value"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "signal"
              },
              "signal": {
                "type": "string",
                "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$"
              }
            },
            "required": ["kind", "signal"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "window"
              },
              "fn": {
                "type": "string",
                "enum": ["avg", "min", "max", "sum", "count"]
              },
              "signal": {
                "type": "string",
                "pattern": "^[a-z][a-z0-9_]*(\\.[a-z0-9_]+)+$"
              },
              "lastMin": {
                "type": "integer",
                "minimum": 1,
                "maximum": 1440
              }
            },
            "required": ["kind", "fn", "signal", "lastMin"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "binary"
              },
              "op": {
                "type": "string",
                "enum": ["+", "-", "*", "/"]
              },
              "left": {
                "$ref": "#/components/schemas/__schema3"
              },
              "right": {
                "$ref": "#/components/schemas/__schema3"
              }
            },
            "required": ["kind", "op", "left", "right"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "const": "clamp"
              },
              "value": {
                "$ref": "#/components/schemas/__schema3"
              },
              "min": {
                "$ref": "#/components/schemas/__schema3"
              },
              "max": {
                "$ref": "#/components/schemas/__schema3"
              }
            },
            "required": ["kind", "value", "min", "max"],
            "additionalProperties": false
          }
        ],
        "type": "object"
      }
    },
    "securitySchemes": {
      "Authorization": {
        "type": "http",
        "scheme": "bearer"
      }
    }
  }
}
