{
    "schemes": [],
    "swagger": "2.0",
    "info": {
        "description": "IBMS IoT Building Management System — Device, Shadow, Alarm, Space, Discovery APIs.",
        "title": "IBMS Backend API",
        "termsOfService": "http://shellyiot.cn/terms/",
        "contact": {
            "name": "IBMS Support",
            "email": "dev@shellyiot.cn"
        },
        "license": {
            "name": "Proprietary"
        },
        "version": "v1"
    },
    "host": "localhost:8090",
    "basePath": "/api/v1",
    "paths": {
        "/_debug/bridges": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "列出当前租户下所有已注册的 Bridge 信息（包括 IngressCapable 的路径），仅返回调用者自己租户的数据。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "debug"
                ],
                "summary": "列出当前在线的 Bridge（调试）",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.DebugBridgesResponse"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "503": {
                        "description": "Service Unavailable",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/alarms": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "列出当前租户的告警，支持按 status / severity / code / deviceId 过滤（G08）。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "alarms"
                ],
                "summary": "列出告警",
                "parameters": [
                    {
                        "type": "string",
                        "description": "firing | acked | resolved | closed | shelved",
                        "name": "status",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "critical | warning | info",
                        "name": "severity",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "告警代码，如 ALM-DEV-OFFLINE",
                        "name": "code",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "设备 UUID",
                        "name": "deviceId",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "返回数量上限",
                        "name": "limit",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "偏移量",
                        "name": "offset",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.AlarmListResponse"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "503": {
                        "description": "告警服务不可用",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/alarms/{id}": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "按 ID 获取告警详情（G08）。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "alarms"
                ],
                "summary": "获取单条告警",
                "parameters": [
                    {
                        "type": "string",
                        "description": "告警 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.AlarmItem"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/alarms/{id}/ack": {
            "post": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "将告警状态从 firing 转为 acked（G08 状态机）。actor.id 取自 JWT sub。",
                "tags": [
                    "alarms"
                ],
                "summary": "确认告警",
                "parameters": [
                    {
                        "type": "string",
                        "description": "告警 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "204": {
                        "description": "成功确认"
                    },
                    "400": {
                        "description": "非法状态转移",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/alarms/{id}/close": {
            "post": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "将告警状态转为 closed（最终态，不可逆）。",
                "tags": [
                    "alarms"
                ],
                "summary": "关闭告警",
                "parameters": [
                    {
                        "type": "string",
                        "description": "告警 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "204": {
                        "description": "成功"
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/alarms/{id}/resolve": {
            "post": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "将告警状态转为 resolved。",
                "tags": [
                    "alarms"
                ],
                "summary": "解除告警",
                "parameters": [
                    {
                        "type": "string",
                        "description": "告警 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "204": {
                        "description": "成功"
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/alarms/{id}/shelve": {
            "post": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "将告警暂时搁置（shelved），TTL 到期后自动恢复为 firing。",
                "consumes": [
                    "application/json"
                ],
                "tags": [
                    "alarms"
                ],
                "summary": "搁置告警",
                "parameters": [
                    {
                        "type": "string",
                        "description": "告警 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "description": "搁置时长（分钟）",
                        "name": "body",
                        "in": "body",
                        "schema": {
                            "$ref": "#/definitions/api.shelveAlarmRequest"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "成功"
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/auth/callback": {
            "get": {
                "description": "Keycloak 认证后回调此端点，交换 code 获取 token，写 HttpOnly cookie，302 跳回 SPA 站内路径。错误通过 ?auth_error= 参数传回 SPA。\n服务端配置错误（KEYCLOAK_CLIENT_SECRET 为空）时返回 503 JSON，其余情况均 302。",
                "tags": [
                    "auth"
                ],
                "summary": "OIDC 回调",
                "parameters": [
                    {
                        "type": "string",
                        "description": "授权码",
                        "name": "code",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "防 CSRF 状态值",
                        "name": "state",
                        "in": "query",
                        "required": true
                    }
                ],
                "responses": {
                    "302": {
                        "description": "Found"
                    },
                    "503": {
                        "description": "Service Unavailable"
                    }
                }
            }
        },
        "/auth/login": {
            "get": {
                "description": "重定向到 Keycloak 登录页，完成 Authorization Code 流程。",
                "tags": [
                    "auth"
                ],
                "summary": "OIDC 登录",
                "responses": {
                    "302": {
                        "description": "Found"
                    }
                }
            }
        },
        "/auth/logout": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "服务端代理 OIDC RP-Initiated Logout 流程：拼 Keycloak logout URL（带 client_id + post_logout_redirect_uri）→ 302 跳转。回调由 handleAuthLogoutCallback 接收。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "auth"
                ],
                "summary": "OIDC 登出（302 → Keycloak）",
                "responses": {
                    "302": {
                        "description": "Found，跳转 Keycloak /protocol/openid-connect/logout"
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/auth/logout-callback": {
            "get": {
                "description": "Keycloak 完成 RP-Initiated Logout 后回调本端点，302 重定向到 Dev Console 根路径。完成 OIDC 登出闭环。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "auth"
                ],
                "summary": "OIDC 登出回调（302 → /dev/）",
                "responses": {
                    "302": {
                        "description": "Found，跳转 /dev/"
                    }
                }
            }
        },
        "/auth/me": {
            "get": {
                "description": "读取 HttpOnly cookie ibms_at 中的 access_token，返回 tenant_id。未登录返回 401。SPA 启动时调用以决定显示登录入口还是用户态。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "auth"
                ],
                "summary": "当前登录态",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.AuthMeResponse"
                        }
                    },
                    "401": {
                        "description": "未登录或 token 无效"
                    }
                }
            }
        },
        "/auth/refresh": {
            "post": {
                "description": "使用 refresh_token 获取新的 access_token。client_secret 服务端持有。",
                "consumes": [
                    "application/x-www-form-urlencoded"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "auth"
                ],
                "summary": "Refresh token",
                "parameters": [
                    {
                        "type": "string",
                        "description": "刷新令牌",
                        "name": "refresh_token",
                        "in": "formData",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.TokenResponse"
                        }
                    },
                    "400": {
                        "description": "Bad Request"
                    },
                    "502": {
                        "description": "Bad Gateway"
                    }
                }
            }
        },
        "/auth/token": {
            "post": {
                "description": "OAuth2 密码授权模式——代理到 Keycloak，方便 Swagger UI 一键授权。\n字段 `realm` / `client_id` 缺省时使用服务端配置值。",
                "consumes": [
                    "application/x-www-form-urlencoded"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "auth"
                ],
                "summary": "获取访问令牌",
                "parameters": [
                    {
                        "type": "string",
                        "default": "dev@ibms.local",
                        "description": "用户名",
                        "name": "username",
                        "in": "formData",
                        "required": true
                    },
                    {
                        "type": "string",
                        "default": "ibms_dev_2026",
                        "description": "密码",
                        "name": "password",
                        "in": "formData",
                        "required": true
                    },
                    {
                        "type": "string",
                        "default": "ibms-backend",
                        "description": "Client ID（默认 ibms-backend）",
                        "name": "client_id",
                        "in": "formData"
                    },
                    {
                        "type": "string",
                        "default": "change-me-in-task-0b5",
                        "description": "Client Secret",
                        "name": "client_secret",
                        "in": "formData"
                    },
                    {
                        "type": "string",
                        "default": "ibms",
                        "description": "Keycloak Realm（默认 ibms）",
                        "name": "realm",
                        "in": "formData"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.TokenResponse"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "用户名或密码错误",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "502": {
                        "description": "Keycloak 不可达",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/auth/token-for-stream": {
            "get": {
                "description": "WS /events、MQTT over WebSocket（连 EMQX）等非 HTTP-cookie 通道无法使用 HttpOnly cookie，需经本端点领取当前登录用户的 access_token 明文填入。token 仍由 EMQX/WS 验 JWT，cookie 不削弱其认证（PRD 05 §2.5）。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "auth"
                ],
                "summary": "领取流式通道 token",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.StreamTokenResponse"
                        }
                    },
                    "401": {
                        "description": "未登录或 token 无效"
                    }
                }
            }
        },
        "/devices": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "游标分页列出当前租户下的设备列表，支持按 deviceClass / bridgeId 过滤。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "devices"
                ],
                "summary": "列出设备",
                "parameters": [
                    {
                        "type": "integer",
                        "description": "每页数量，默认 50，最大 200",
                        "name": "limit",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "分页游标（上次响应中的 nextCursor）",
                        "name": "cursor",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "过滤 device_class，支持前缀通配 e.g. sensor.*",
                        "name": "deviceClass",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "过滤 bridge_id",
                        "name": "bridgeId",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.DeviceListResponse"
                        }
                    },
                    "400": {
                        "description": "cursor 格式非法",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            },
            "post": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "手动新建一条设备记录（不走 Discovery 审批流程）。需要提供完整的元数据。",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "devices"
                ],
                "summary": "创建设备",
                "parameters": [
                    {
                        "description": "设备创建请求",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/api.createDeviceRequest"
                        }
                    }
                ],
                "responses": {
                    "201": {
                        "description": "Created",
                        "schema": {
                            "$ref": "#/definitions/api.DeviceResponse"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "409": {
                        "description": "设备已存在 (E-RES-4090)",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/devices/{id}": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "按 UUID 获取指定设备的完整信息，含 adapterAttributes。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "devices"
                ],
                "summary": "获取设备详情",
                "parameters": [
                    {
                        "type": "string",
                        "description": "设备 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.DeviceResponse"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            },
            "delete": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "软删除设备（设 deleted_at），并发布 MQTT detach config 通知 adapter 断开连接。",
                "tags": [
                    "devices"
                ],
                "summary": "删除设备",
                "parameters": [
                    {
                        "type": "string",
                        "description": "设备 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "204": {
                        "description": "成功，无响应体"
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            },
            "patch": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "更新设备的 name 字段（最大 128 字符）。不触发 MQTT 重发。",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "devices"
                ],
                "summary": "重命名设备",
                "parameters": [
                    {
                        "type": "string",
                        "description": "设备 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "description": "新名称",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/api.renameDeviceRequest"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.RenameDeviceResponse"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/devices/{id}/commands": {
            "post": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "与 PATCH /shadow desired 相同的 channel:N 格式，但不持久化 desired、不做对账，同步等待 adapter 响应（最长 timeoutMs，默认 5000ms）。（G10）",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "commands"
                ],
                "summary": "下发设备控制指令（同步）",
                "parameters": [
                    {
                        "type": "string",
                        "description": "设备 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "幂等键",
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true
                    },
                    {
                        "description": "channel:N 控制 map，可选 timeoutMs 字段",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "type": "object"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.commandResponse"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/problem.Problem"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/problem.Problem"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/problem.Problem"
                        }
                    },
                    "503": {
                        "description": "Service Unavailable",
                        "schema": {
                            "$ref": "#/definitions/problem.Problem"
                        }
                    },
                    "504": {
                        "description": "设备超时 (E-DEV-1002)",
                        "schema": {
                            "$ref": "#/definitions/problem.Problem"
                        }
                    }
                }
            }
        },
        "/devices/{id}/password": {
            "put": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "设置或清除设备的 digest auth 密码（T9 加密存储）。空 password 字段为清除。设置后自动重发 MQTT attach config。",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "devices"
                ],
                "summary": "设置 / 清除设备密码",
                "parameters": [
                    {
                        "type": "string",
                        "description": "设备 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "description": "密码（空字符串=清除）",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/api.setPasswordRequest"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.SetPasswordResponse"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/devices/{id}/resync": {
            "post": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "重发 MQTT attach config，触发 adapter 重新接入已注册设备（adapter 重启后使用）。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "devices"
                ],
                "summary": "重新同步设备（resync）",
                "parameters": [
                    {
                        "type": "string",
                        "description": "设备 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.ResyncResponse"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "503": {
                        "description": "MQTT 不可用",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/devices/{id}/shadow": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "获取设备的完整 Shadow 状态，包括 reported / desired / delta 和元数据（G07）。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "shadow"
                ],
                "summary": "获取设备 Shadow",
                "parameters": [
                    {
                        "type": "string",
                        "description": "设备 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.shadowResponse"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            },
            "patch": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "更新设备的 desired 字段，触发 delta 计算和 RPC 下发（G07）。要求 Idempotency-Key header。",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "shadow"
                ],
                "summary": "更新 Shadow Desired 状态",
                "parameters": [
                    {
                        "type": "string",
                        "description": "设备 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "幂等键，避免重复下发",
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true
                    },
                    {
                        "description": "desired 状态 patch",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/api.patchShadowRequest"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.shadowResponse"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "409": {
                        "description": "版本冲突 (E-CFL-6001)",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/devices/{id}/timeseries": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "查询设备某个数值型 reported 字段的历史时序数据（G07 §7.8）。tenant 强制从 JWT 取。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "timeseries"
                ],
                "summary": "查询时序数据",
                "parameters": [
                    {
                        "type": "string",
                        "description": "设备 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "数据点 ref，如 power / temperature",
                        "name": "ref",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "开始时间 RFC3339，如 2026-01-01T00:00:00Z",
                        "name": "from",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "结束时间 RFC3339",
                        "name": "to",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "采样步长（Go duration），如 30s / 1m，默认 1m",
                        "name": "step",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.TimeseriesResponse"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "502": {
                        "description": "上游 VM 查询失败",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "503": {
                        "description": "时序后端未配置",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/discovery/approve": {
            "post": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "将扫描到的设备注册到 device 表，发布 MQTT attach config，触发 adapter 接入（G11）。",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "discovery"
                ],
                "summary": "审批发现的设备",
                "parameters": [
                    {
                        "description": "审批请求：fingerprint + siteId + name + bridgeId",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/api.approveRequest"
                        }
                    }
                ],
                "responses": {
                    "201": {
                        "description": "Created",
                        "schema": {
                            "$ref": "#/definitions/api.DeviceResponse"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "fingerprint 不在扫描缓存中",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/discovery/rescan": {
            "post": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "向当前租户已知的 bridge 发布 scan-request.v1 envelope，触发 on-demand mDNS/协议扫描。body 可选；bridgeId 空时广播到所有 bridge；timeoutS 范围 1-60s（默认 5s）。扫描结果通过 discovery.v1 MQTT 异步回流。",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "discovery"
                ],
                "summary": "触发设备扫描（按 bridge / 全租户广播）",
                "parameters": [
                    {
                        "description": "可选：bridgeId + timeoutS",
                        "name": "body",
                        "in": "body",
                        "schema": {
                            "$ref": "#/definitions/api.RescanRequest"
                        }
                    }
                ],
                "responses": {
                    "202": {
                        "description": "correlationId + publishedToBridges",
                        "schema": {
                            "$ref": "#/definitions/api.RescanResponse"
                        }
                    },
                    "400": {
                        "description": "bridgeId 正则失败 / timeoutS 越界 / no bridges known",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "503": {
                        "description": "MQTT 不可用 / publish 失败",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/discovery/scan": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "返回当前租户下 Redis 扫描缓存中发现的设备（TTL 5 分钟，G11）。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "discovery"
                ],
                "summary": "列出发现的设备",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.DiscoveryListResponse"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/events": {
            "get": {
                "description": "升级为 WebSocket 连接。优先从 ibms_at cookie 认证（BFF cookie 模式，省掉首帧）；无 cookie 时退回首帧 `{\"type\":\"auth\",\"token\":\"\u003cJWT\u003e\"}` 路径（兼容）。认证成功后实时接收告警和设备状态变更事件（G09）。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "events"
                ],
                "summary": "WebSocket 实时事件推送",
                "responses": {
                    "101": {
                        "description": "Switching Protocols"
                    },
                    "503": {
                        "description": "Service Unavailable",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/healthz": {
            "get": {
                "description": "Kubernetes liveness probe，始终返回 200 OK。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "health"
                ],
                "summary": "存活探针",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.HealthzResponse"
                        }
                    }
                }
            }
        },
        "/meta": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "列出所有只读参考目录（设备类 / 错误码 / 单位 / 功能类型 / 枚举 / WS schema）及各自版本，供前端发现。详见 G09 §9.11。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "meta"
                ],
                "summary": "元数据目录索引",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.MetaIndexResponse"
                        }
                    }
                }
            }
        },
        "/meta/alarm-codes": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "返回全量告警码：code / domain / default_severity / title / description / suggested_action / protocol_mapping / api_error_mapping。权威源 prd/specs/alarm/codes.yaml。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "meta"
                ],
                "summary": "告警码字典（G08）",
                "responses": {
                    "200": {
                        "description": "codes.yaml 全量内容",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/meta/device-classes": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "返回全量设备类字典：code / display_name / inherits / required_points / optional_points / actions / events / ui_hints。权威源 prd/specs/device/classes.yaml。前端据此渲染设备卡片、可写点位与可用动作。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "meta"
                ],
                "summary": "设备类目录（G13）",
                "responses": {
                    "200": {
                        "description": "classes.yaml 全量内容（version + classes[]）",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/meta/enums": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "返回前端常用的枚举：告警状态机（G08 status + 合法迁移）、告警严重度、空间 kind（G04）。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "meta"
                ],
                "summary": "跨域枚举集合",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.MetaEnumsResponse"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/meta/error-codes": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "返回全量错误码：code / domain / http / title / retryable / problem_type / alarm_mapping。权威源 prd/specs/api/error-codes.yaml。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "meta"
                ],
                "summary": "错误码字典（G09 §9.2）",
                "responses": {
                    "200": {
                        "description": "error-codes.yaml 全量内容（version + codes[]）",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/meta/event-schemas": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "返回 GET /api/v1/events 通道的消息 envelope JSON Schema（auth / event / ping / error 帧）。event 帧 data 形态随 eventType，参见 prd/specs/mqtt/*.schema.json。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "meta"
                ],
                "summary": "WebSocket 事件 schema（G09 §9.7）",
                "responses": {
                    "200": {
                        "description": "ws-events.schema.json（JSON Schema draft-07）",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/meta/functional-types": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "返回空间功能类型枚举。权威源 prd/specs/spatial/functional-types.yaml。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "meta"
                ],
                "summary": "空间功能类型枚举（G04）",
                "responses": {
                    "200": {
                        "description": "functional-types.yaml 全量内容",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/meta/units": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "返回全量单位白名单。权威源 prd/specs/units/whitelist.yaml。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "meta"
                ],
                "summary": "单位白名单（G05）",
                "responses": {
                    "200": {
                        "description": "whitelist.yaml 全量内容",
                        "schema": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            }
        },
        "/readyz": {
            "get": {
                "description": "Kubernetes readiness probe，检查 Postgres / NATS / Redis 连通性，任一失败返回 503。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "health"
                ],
                "summary": "就绪探针",
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.ReadyzResponse"
                        }
                    },
                    "503": {
                        "description": "Service Unavailable",
                        "schema": {
                            "$ref": "#/definitions/api.ReadyzResponse"
                        }
                    }
                }
            }
        },
        "/shelly-integrator-callback": {
            "post": {
                "description": "Shelly Cloud 完成授权后向本端点推送设备事件（DeviceAdd/DeviceRemove 等）。请求须携带 SCL-Trust header（ES384 JWT），由 Shelly Cloud 签发；tenant_id 通过 query 参数传递（由 MakeAuthURL 拼入）。",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "shelly-integrator"
                ],
                "summary": "Shelly Integrator OAuth 回调",
                "parameters": [
                    {
                        "type": "string",
                        "description": "租户 UUID，由授权 URL 拼入",
                        "name": "tenant_id",
                        "in": "query",
                        "required": true
                    },
                    {
                        "type": "string",
                        "description": "Shelly Cloud 签发的 ES384 JWT 安全令牌",
                        "name": "SCL-Trust",
                        "in": "header",
                        "required": true
                    },
                    {
                        "description": "设备事件",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/api.ShellyDeviceEvent"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "status: success",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "SCL-Trust 令牌无效",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "500": {
                        "description": "Internal Server Error",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/shelly/integrator": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "返回 Shelly Cloud 集成授权页跳转地址。前端打开该 URL 完成 OAuth 授权后，Shelly Cloud 将回调 /api/v1/shelly-integrator-callback。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "shelly-integrator"
                ],
                "summary": "获取 Shelly Integrator 授权页 URL",
                "responses": {
                    "200": {
                        "description": "url: Shelly Cloud 授权页地址",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/spaces": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "游标分页列出当前租户所有空间节点，支持按 kind 过滤（G04）。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "spaces"
                ],
                "summary": "列出空间节点",
                "parameters": [
                    {
                        "type": "string",
                        "description": "节点类型（site/building/floor/zone）",
                        "name": "kind",
                        "in": "query"
                    },
                    {
                        "type": "string",
                        "description": "分页游标",
                        "name": "cursor",
                        "in": "query"
                    },
                    {
                        "type": "integer",
                        "description": "每页数量，默认 50",
                        "name": "limit",
                        "in": "query"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.SpaceListResponse"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "503": {
                        "description": "Service Unavailable",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            },
            "post": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "在空间层级中创建一个节点（G04，最多六级）。code 最大 64 字符；functional_type 必须合法。",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "spaces"
                ],
                "summary": "创建空间节点",
                "parameters": [
                    {
                        "description": "空间节点创建请求",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/space.CreateRequest"
                        }
                    }
                ],
                "responses": {
                    "201": {
                        "description": "Created",
                        "schema": {
                            "$ref": "#/definitions/api.SpaceItem"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "409": {
                        "description": "code 冲突 (E-RES-4090)",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "503": {
                        "description": "Service Unavailable",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/spaces/import": {
            "post": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "批量导入 YAML/JSON 格式的空间节点树（G04）。Content-Type 支持 application/json 或 application/x-yaml。",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "spaces"
                ],
                "summary": "批量导入空间节点",
                "parameters": [
                    {
                        "description": "空间树（YAML 或 JSON）",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/api.importPayload"
                        }
                    }
                ],
                "responses": {
                    "201": {
                        "description": "Created",
                        "schema": {
                            "$ref": "#/definitions/api.ImportSpacesResponse"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "503": {
                        "description": "Service Unavailable",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/spaces/{id}": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "按 UUID 获取空间节点详情（G04）。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "spaces"
                ],
                "summary": "获取空间节点",
                "parameters": [
                    {
                        "type": "string",
                        "description": "空间节点 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.SpaceItem"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "503": {
                        "description": "Service Unavailable",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            },
            "delete": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "删除空间节点。有子节点时拒绝（409 E-VAL-2020），需先删子节点（G04）。",
                "tags": [
                    "spaces"
                ],
                "summary": "删除空间节点",
                "parameters": [
                    {
                        "type": "string",
                        "description": "空间节点 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "204": {
                        "description": "已删除"
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "409": {
                        "description": "有子节点 (E-VAL-2020)",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "503": {
                        "description": "Service Unavailable",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            },
            "patch": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "更新空间节点的 name / code / functionalType 等字段（G04）。",
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "spaces"
                ],
                "summary": "更新空间节点",
                "parameters": [
                    {
                        "type": "string",
                        "description": "空间节点 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    },
                    {
                        "description": "更新字段",
                        "name": "body",
                        "in": "body",
                        "required": true,
                        "schema": {
                            "$ref": "#/definitions/space.UpdateRequest"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.SpaceItem"
                        }
                    },
                    "400": {
                        "description": "Bad Request",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "503": {
                        "description": "Service Unavailable",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        },
        "/spaces/{id}/descendants": {
            "get": {
                "security": [
                    {
                        "BearerAuth": []
                    }
                ],
                "description": "使用 LTREE 路径查询，递归获取指定节点下的所有后裔空间节点（G04）。",
                "produces": [
                    "application/json"
                ],
                "tags": [
                    "spaces"
                ],
                "summary": "获取所有子节点",
                "parameters": [
                    {
                        "type": "string",
                        "description": "空间节点 UUID",
                        "name": "id",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "schema": {
                            "$ref": "#/definitions/api.SpaceListResponse"
                        }
                    },
                    "401": {
                        "description": "Unauthorized",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "404": {
                        "description": "Not Found",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    },
                    "503": {
                        "description": "Service Unavailable",
                        "schema": {
                            "$ref": "#/definitions/api.ProblemDetails"
                        }
                    }
                }
            }
        }
    },
    "definitions": {
        "api.AlarmItem": {
            "type": "object",
            "properties": {
                "ackedAt": {
                    "type": "string"
                },
                "code": {
                    "type": "string",
                    "example": "ALM-DEV-OFFLINE"
                },
                "deviceId": {
                    "type": "string",
                    "example": "uuid"
                },
                "firedAt": {
                    "type": "string",
                    "example": "2026-01-01T00:00:00Z"
                },
                "id": {
                    "type": "string",
                    "example": "uuid"
                },
                "resolvedAt": {
                    "type": "string"
                },
                "severity": {
                    "type": "string",
                    "example": "critical"
                },
                "status": {
                    "type": "string",
                    "example": "firing"
                },
                "tenantId": {
                    "type": "string",
                    "example": "uuid"
                }
            }
        },
        "api.AlarmListResponse": {
            "type": "object",
            "properties": {
                "items": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/api.AlarmItem"
                    }
                }
            }
        },
        "api.AuthMeResponse": {
            "type": "object",
            "properties": {
                "authenticated": {
                    "type": "boolean",
                    "example": true
                },
                "tenant_id": {
                    "type": "string"
                }
            }
        },
        "api.DebugBridgeEntry": {
            "type": "object",
            "properties": {
                "bridgeId": {
                    "type": "string"
                },
                "online": {
                    "type": "boolean"
                },
                "protocol": {
                    "type": "string"
                }
            }
        },
        "api.DebugBridgesResponse": {
            "type": "object",
            "properties": {
                "items": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/api.DebugBridgeEntry"
                    }
                }
            }
        },
        "api.DeviceListResponse": {
            "type": "object",
            "properties": {
                "hasMore": {
                    "type": "boolean"
                },
                "items": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/api.DeviceResponse"
                    }
                },
                "nextCursor": {
                    "type": "string"
                }
            }
        },
        "api.DeviceResponse": {
            "type": "object",
            "properties": {
                "adapterAttributes": {
                    "description": "AdapterAttributes mirrors device.attributes -\u003e 'adapter' (see prd/04\ndevice.attributes 顶层命名空间). Auth never exposed via API.\nAdapters push updates via device-attributes.v1 MQTT (G02), main service\nemits device.device.attributes-updated NATS event on change.",
                    "type": "object",
                    "additionalProperties": {}
                },
                "bridgeId": {
                    "type": "string"
                },
                "bridgeProtocol": {
                    "type": "string"
                },
                "createdAt": {
                    "type": "string"
                },
                "deviceClass": {
                    "type": "string"
                },
                "firmware": {
                    "type": "string"
                },
                "generation": {
                    "type": "string"
                },
                "id": {
                    "type": "string"
                },
                "identifier": {
                    "type": "string"
                },
                "labels": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "model": {
                    "type": "string"
                },
                "name": {
                    "type": "string"
                },
                "online": {
                    "type": "boolean"
                },
                "siteId": {
                    "type": "string"
                },
                "tenantId": {
                    "type": "string"
                },
                "updatedAt": {
                    "type": "string"
                },
                "vendor": {
                    "type": "string"
                }
            }
        },
        "api.DiscoveryEntry": {
            "type": "object",
            "properties": {
                "fingerprint": {
                    "type": "string",
                    "example": "AA:BB:CC:DD:EE:FF"
                },
                "natives": {
                    "type": "object",
                    "additionalProperties": {}
                },
                "protocol": {
                    "type": "string",
                    "example": "shelly"
                },
                "suggestedClass": {
                    "type": "string",
                    "example": "switch.1gang"
                },
                "vendor": {
                    "type": "string",
                    "example": "Shelly"
                }
            }
        },
        "api.DiscoveryListResponse": {
            "type": "object",
            "properties": {
                "items": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/api.DiscoveryEntry"
                    }
                }
            }
        },
        "api.HealthzResponse": {
            "type": "object",
            "properties": {
                "status": {
                    "type": "string",
                    "example": "ok"
                }
            }
        },
        "api.ImportSpacesResponse": {
            "type": "object",
            "properties": {
                "imported": {
                    "type": "integer",
                    "example": 12
                }
            }
        },
        "api.MetaCatalogRef": {
            "type": "object",
            "properties": {
                "endpoint": {
                    "type": "string",
                    "example": "/api/v1/meta/device-classes"
                },
                "gridRef": {
                    "type": "string",
                    "example": "G13"
                },
                "name": {
                    "type": "string",
                    "example": "device-classes"
                },
                "source": {
                    "type": "string",
                    "example": "prd/specs/device/classes.yaml"
                },
                "version": {
                    "type": "string",
                    "example": "0.1.0"
                }
            }
        },
        "api.MetaEnumsResponse": {
            "type": "object",
            "properties": {
                "alarmSeverity": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    },
                    "example": [
                        "critical",
                        "major",
                        "minor",
                        "warning"
                    ]
                },
                "alarmStatus": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    },
                    "example": [
                        "firing",
                        "acked",
                        "shelved",
                        "suppressed",
                        "resolved",
                        "closed"
                    ]
                },
                "alarmStatusTransitions": {
                    "type": "object",
                    "additionalProperties": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    }
                },
                "spaceKind": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    },
                    "example": [
                        "organization",
                        "site",
                        "building",
                        "floor",
                        "zone",
                        "room"
                    ]
                }
            }
        },
        "api.MetaIndexResponse": {
            "type": "object",
            "properties": {
                "catalogs": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/api.MetaCatalogRef"
                    }
                }
            }
        },
        "api.ProblemDetails": {
            "type": "object",
            "properties": {
                "code": {
                    "type": "string",
                    "example": "E-VAL-4001"
                },
                "detail": {
                    "type": "string",
                    "example": "name must not be empty"
                },
                "instance": {
                    "type": "string"
                },
                "status": {
                    "type": "integer",
                    "example": 400
                },
                "title": {
                    "type": "string",
                    "example": "invalid input"
                },
                "traceId": {
                    "type": "string",
                    "example": "abc123"
                },
                "type": {
                    "type": "string",
                    "example": "https://ibms.shellyiot.cn/errors/E-VAL-4001"
                }
            }
        },
        "api.ReadyzResponse": {
            "type": "object",
            "properties": {
                "checks": {
                    "type": "object",
                    "additionalProperties": {
                        "type": "string"
                    }
                },
                "status": {
                    "type": "string",
                    "example": "ok"
                }
            }
        },
        "api.RenameDeviceResponse": {
            "type": "object",
            "properties": {
                "id": {
                    "type": "string",
                    "example": "uuid"
                },
                "name": {
                    "type": "string",
                    "example": "Living Room Switch"
                }
            }
        },
        "api.RescanRequest": {
            "type": "object",
            "properties": {
                "bridgeId": {
                    "type": "string"
                },
                "timeoutS": {
                    "type": "integer"
                }
            }
        },
        "api.RescanResponse": {
            "type": "object",
            "properties": {
                "correlationId": {
                    "type": "string"
                },
                "publishedToBridges": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                }
            }
        },
        "api.ResyncResponse": {
            "type": "object",
            "properties": {
                "bridgeId": {
                    "type": "string",
                    "example": "native-0"
                },
                "ok": {
                    "type": "boolean",
                    "example": true
                },
                "siteSlug": {
                    "type": "string",
                    "example": "hq-site"
                }
            }
        },
        "api.SetPasswordResponse": {
            "type": "object",
            "properties": {
                "hasPassword": {
                    "type": "boolean",
                    "example": true
                },
                "ok": {
                    "type": "boolean",
                    "example": true
                }
            }
        },
        "api.ShellyDeviceEvent": {
            "type": "object",
            "properties": {
                "accessGroups": {
                    "type": "string"
                },
                "action": {
                    "type": "string"
                },
                "deviceCode": {
                    "type": "string"
                },
                "deviceId": {
                    "type": "string"
                },
                "deviceType": {
                    "type": "string"
                },
                "host": {
                    "type": "string"
                },
                "name": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "userId": {
                    "type": "integer"
                }
            }
        },
        "api.SpaceItem": {
            "type": "object",
            "properties": {
                "code": {
                    "type": "string",
                    "example": "HQ-SITE-01"
                },
                "functionalType": {
                    "type": "string",
                    "example": "office"
                },
                "id": {
                    "type": "string",
                    "example": "uuid"
                },
                "kind": {
                    "type": "string",
                    "example": "site"
                },
                "name": {
                    "type": "string",
                    "example": "总部大楼"
                },
                "parentId": {
                    "type": "string"
                },
                "path": {
                    "type": "string"
                },
                "tenantId": {
                    "type": "string",
                    "example": "uuid"
                }
            }
        },
        "api.SpaceListResponse": {
            "type": "object",
            "properties": {
                "hasMore": {
                    "type": "boolean"
                },
                "items": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/api.SpaceItem"
                    }
                },
                "nextCursor": {
                    "type": "string"
                }
            }
        },
        "api.StreamTokenResponse": {
            "type": "object",
            "properties": {
                "access_token": {
                    "type": "string",
                    "example": "eyJhbGci..."
                }
            }
        },
        "api.TimeseriesPoint": {
            "type": "object",
            "properties": {
                "ts": {
                    "type": "string",
                    "example": "2026-01-01T00:01:00Z"
                },
                "value": {
                    "type": "number",
                    "example": 45.5
                }
            }
        },
        "api.TimeseriesResponse": {
            "type": "object",
            "properties": {
                "device": {
                    "type": "string",
                    "example": "uuid"
                },
                "from": {
                    "type": "string",
                    "example": "2026-01-01T00:00:00Z"
                },
                "ref": {
                    "type": "string",
                    "example": "power"
                },
                "series": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/api.TimeseriesPoint"
                    }
                },
                "step": {
                    "type": "string",
                    "example": "1m"
                },
                "to": {
                    "type": "string",
                    "example": "2026-01-01T01:00:00Z"
                },
                "unit": {
                    "type": "string",
                    "example": "W"
                }
            }
        },
        "api.TokenResponse": {
            "type": "object",
            "properties": {
                "access_token": {
                    "type": "string",
                    "example": "eyJhbGci..."
                },
                "expires_in": {
                    "type": "integer",
                    "example": 300
                },
                "id_token": {
                    "type": "string"
                },
                "refresh_expires_in": {
                    "type": "integer",
                    "example": 1800
                },
                "refresh_token": {
                    "type": "string"
                },
                "scope": {
                    "type": "string",
                    "example": "openid profile email"
                },
                "token_type": {
                    "type": "string",
                    "example": "Bearer"
                }
            }
        },
        "api.approveRequest": {
            "type": "object",
            "properties": {
                "bridgeId": {
                    "type": "string"
                },
                "fingerprint": {
                    "type": "string"
                },
                "name": {
                    "type": "string"
                },
                "password": {
                    "description": "Password is the optional Shelly device password (set via Shelly.SetAuth\non the device). When non-empty, it is encrypted under Deps.Secrets and\nstored in device.attributes.auth.password; the adapter receives the\ndecrypted value in attach config natives.password.",
                    "type": "string"
                },
                "siteId": {
                    "type": "string"
                },
                "siteSlug": {
                    "description": "slug for MQTT topic, falls back to siteId",
                    "type": "string"
                }
            }
        },
        "api.commandResponse": {
            "type": "object",
            "properties": {
                "correlationId": {
                    "type": "string"
                },
                "durationMs": {
                    "type": "integer"
                },
                "result": {
                    "type": "object",
                    "additionalProperties": {}
                },
                "status": {
                    "type": "string"
                }
            }
        },
        "api.createDeviceRequest": {
            "type": "object",
            "properties": {
                "bridgeId": {
                    "type": "string"
                },
                "bridgeProtocol": {
                    "type": "string"
                },
                "deviceClass": {
                    "type": "string"
                },
                "firmware": {
                    "type": "string"
                },
                "generation": {
                    "type": "string"
                },
                "identifier": {
                    "type": "string"
                },
                "labels": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                },
                "model": {
                    "type": "string"
                },
                "name": {
                    "type": "string"
                },
                "siteId": {
                    "type": "string"
                },
                "vendor": {
                    "type": "string"
                }
            }
        },
        "api.importPayload": {
            "type": "object",
            "properties": {
                "spaces": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/space.ImportItem"
                    }
                },
                "version": {
                    "type": "string"
                }
            }
        },
        "api.patchShadowRequest": {
            "type": "object",
            "properties": {
                "desired": {
                    "type": "object",
                    "additionalProperties": {}
                },
                "version": {
                    "type": "integer",
                    "example": 5
                }
            }
        },
        "api.renameDeviceRequest": {
            "type": "object",
            "properties": {
                "name": {
                    "type": "string"
                }
            }
        },
        "api.setPasswordRequest": {
            "type": "object",
            "properties": {
                "password": {
                    "type": "string"
                }
            }
        },
        "api.shadowMeta": {
            "type": "object",
            "properties": {
                "desired_at": {
                    "type": "string"
                },
                "last_desired_by": {
                    "type": "string"
                },
                "quality": {
                    "type": "string"
                },
                "reachable": {
                    "type": "boolean"
                },
                "reported_at": {
                    "type": "string"
                }
            }
        },
        "api.shadowResponse": {
            "type": "object",
            "properties": {
                "delta": {
                    "type": "object",
                    "additionalProperties": {}
                },
                "desired": {
                    "type": "object",
                    "additionalProperties": {}
                },
                "deviceId": {
                    "type": "string"
                },
                "meta": {
                    "$ref": "#/definitions/api.shadowMeta"
                },
                "reported": {
                    "type": "object",
                    "additionalProperties": {}
                },
                "tenant": {
                    "type": "string"
                },
                "version": {
                    "type": "integer"
                }
            }
        },
        "api.shelveAlarmRequest": {
            "type": "object",
            "properties": {
                "durationMinutes": {
                    "type": "integer",
                    "example": 60
                }
            }
        },
        "problem.Problem": {
            "type": "object",
            "properties": {
                "code": {
                    "type": "string"
                },
                "detail": {
                    "type": "string"
                },
                "instance": {
                    "type": "string"
                },
                "status": {
                    "type": "integer"
                },
                "title": {
                    "type": "string"
                },
                "traceId": {
                    "type": "string"
                },
                "type": {
                    "type": "string"
                }
            }
        },
        "space.CreateRequest": {
            "type": "object",
            "properties": {
                "attributes": {
                    "type": "object",
                    "additionalProperties": {}
                },
                "code": {
                    "type": "string"
                },
                "functionalType": {
                    "type": "string"
                },
                "kind": {
                    "type": "string"
                },
                "name": {
                    "type": "string"
                },
                "parentId": {
                    "type": "string"
                },
                "timezone": {
                    "type": "string"
                }
            }
        },
        "space.ImportItem": {
            "type": "object",
            "properties": {
                "attributes": {
                    "type": "object",
                    "additionalProperties": {}
                },
                "code": {
                    "type": "string"
                },
                "functional_type": {
                    "type": "string"
                },
                "geometry": {
                    "type": "object",
                    "additionalProperties": {}
                },
                "kind": {
                    "type": "string"
                },
                "name": {
                    "type": "string"
                },
                "parent_code": {
                    "type": "string"
                },
                "timezone": {
                    "type": "string"
                }
            }
        },
        "space.UpdateRequest": {
            "type": "object",
            "properties": {
                "attributes": {
                    "type": "object",
                    "additionalProperties": {}
                },
                "functionalType": {
                    "type": "string"
                },
                "name": {
                    "type": "string"
                },
                "timezone": {
                    "type": "string"
                }
            }
        }
    },
    "securityDefinitions": {
        "BearerAuth": {
            "description": "JWT Bearer token。格式：`Bearer \u003ctoken\u003e`。dev 模式可用 X-Tenant-ID header 替代。",
            "type": "apiKey",
            "name": "Authorization",
            "in": "header"
        },
        "OAuth2Password": {
            "type": "oauth2",
            "flow": "password",
            "tokenUrl": "/api/v1/auth/token",
            "scopes": {
                "api": "API 访问权限"
            }
        }
    }
}