692 lines
27 KiB
JSON
692 lines
27 KiB
JSON
{
|
|||
|
|
"openapi": "3.1.0",
|
||
|
|
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
|
||
|
|
"info": {
|
||
|
|
"title": "YoVision Sense Control API",
|
||
|
|
"version": "1.0.0",
|
||
|
|
"description": "受控的设备期望态与收敛查询契约。Tenant 只从认证上下文确定;Site、Area、RBAC 和配额真相仍由 Bell 持有。"
|
||
|
|
},
|
||
|
|
"servers": [
|
||
|
|
{
|
||
|
|
"url": "/",
|
||
|
|
"description": "由部署入口提供 scheme、host 和认证终止"
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"security": [
|
||
|
|
{
|
||
|
|
"bearerAuth": []
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"tags": [
|
||
|
|
{
|
||
|
|
"name": "Devices",
|
||
|
|
"description": "设备台账、期望态和收敛状态"
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"name": "Operations",
|
||
|
|
"description": "批量写入的逐项结果"
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"paths": {
|
||
|
|
"/api/v1/sites/{site_id}/devices": {
|
||
|
|
"get": {
|
||
|
|
"tags": ["Devices"],
|
||
|
|
"operationId": "listDevices",
|
||
|
|
"summary": "分页查询当前认证租户下的站点设备",
|
||
|
|
"parameters": [
|
||
|
|
{"$ref": "#/components/parameters/SiteID"},
|
||
|
|
{"$ref": "#/components/parameters/Cursor"},
|
||
|
|
{"$ref": "#/components/parameters/Limit"},
|
||
|
|
{"$ref": "#/components/parameters/ModalityFilter"},
|
||
|
|
{"$ref": "#/components/parameters/CapabilityFilter"},
|
||
|
|
{"$ref": "#/components/parameters/DesiredStateFilter"},
|
||
|
|
{"$ref": "#/components/parameters/ActualStateFilter"}
|
||
|
|
],
|
||
|
|
"responses": {
|
||
|
|
"200": {
|
||
|
|
"description": "按 created_at、id 稳定升序返回的一页设备",
|
||
|
|
"headers": {"X-Trace-ID": {"$ref": "#/components/headers/TraceID"}},
|
||
|
|
"content": {
|
||
|
|
"application/json": {"schema": {"$ref": "#/components/schemas/DevicePage"}}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"401": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"404": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"500": {"$ref": "#/components/responses/ErrorResponse"}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"post": {
|
||
|
|
"tags": ["Devices"],
|
||
|
|
"operationId": "createDevice",
|
||
|
|
"summary": "创建待探测设备",
|
||
|
|
"parameters": [
|
||
|
|
{"$ref": "#/components/parameters/SiteID"},
|
||
|
|
{"$ref": "#/components/parameters/IdempotencyKey"}
|
||
|
|
],
|
||
|
|
"requestBody": {
|
||
|
|
"required": true,
|
||
|
|
"content": {
|
||
|
|
"application/json": {"schema": {"$ref": "#/components/schemas/DeviceCreate"}}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"responses": {
|
||
|
|
"201": {"$ref": "#/components/responses/CreatedDevice"},
|
||
|
|
"400": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"401": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"404": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"409": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"422": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"503": {"$ref": "#/components/responses/ErrorResponse"}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"/api/v1/sites/{site_id}/devices/{device_id}": {
|
||
|
|
"get": {
|
||
|
|
"tags": ["Devices"],
|
||
|
|
"operationId": "getDevice",
|
||
|
|
"summary": "读取设备期望态、实际态和收敛进度",
|
||
|
|
"parameters": [
|
||
|
|
{"$ref": "#/components/parameters/SiteID"},
|
||
|
|
{"$ref": "#/components/parameters/DeviceID"}
|
||
|
|
],
|
||
|
|
"responses": {
|
||
|
|
"200": {"$ref": "#/components/responses/CurrentDevice"},
|
||
|
|
"401": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"404": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"500": {"$ref": "#/components/responses/ErrorResponse"}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"patch": {
|
||
|
|
"tags": ["Devices"],
|
||
|
|
"operationId": "updateDevice",
|
||
|
|
"summary": "按 ETag 修改设备可编辑配置",
|
||
|
|
"parameters": [
|
||
|
|
{"$ref": "#/components/parameters/SiteID"},
|
||
|
|
{"$ref": "#/components/parameters/DeviceID"},
|
||
|
|
{"$ref": "#/components/parameters/IfMatch"}
|
||
|
|
],
|
||
|
|
"requestBody": {
|
||
|
|
"required": true,
|
||
|
|
"content": {
|
||
|
|
"application/merge-patch+json": {"schema": {"$ref": "#/components/schemas/DevicePatch"}}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"responses": {
|
||
|
|
"202": {"$ref": "#/components/responses/AcceptedMutation"},
|
||
|
|
"400": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"401": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"404": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"409": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"412": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"422": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"428": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"503": {"$ref": "#/components/responses/ErrorResponse"}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"/api/v1/sites/{site_id}/devices/{device_id}/desired-state": {
|
||
|
|
"put": {
|
||
|
|
"tags": ["Devices"],
|
||
|
|
"operationId": "setDeviceDesiredState",
|
||
|
|
"summary": "启用或停用设备接入期望态",
|
||
|
|
"description": "成功只表示期望态已持久化并进入对账,不表示实际态已经收敛。重复提交不会重复改变 generation,但每次请求均可产生审计事实。",
|
||
|
|
"parameters": [
|
||
|
|
{"$ref": "#/components/parameters/SiteID"},
|
||
|
|
{"$ref": "#/components/parameters/DeviceID"},
|
||
|
|
{"$ref": "#/components/parameters/IfMatch"}
|
||
|
|
],
|
||
|
|
"requestBody": {
|
||
|
|
"required": true,
|
||
|
|
"content": {
|
||
|
|
"application/json": {"schema": {"$ref": "#/components/schemas/DesiredStateChange"}}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"responses": {
|
||
|
|
"202": {"$ref": "#/components/responses/AcceptedMutation"},
|
||
|
|
"400": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"401": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"404": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"412": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"422": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"428": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"503": {"$ref": "#/components/responses/ErrorResponse"}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"/api/v1/sites/{site_id}/devices:batchDesiredState": {
|
||
|
|
"post": {
|
||
|
|
"tags": ["Devices"],
|
||
|
|
"operationId": "batchSetDeviceDesiredState",
|
||
|
|
"summary": "批量提交最多 128 个设备期望态变更",
|
||
|
|
"parameters": [
|
||
|
|
{"$ref": "#/components/parameters/SiteID"},
|
||
|
|
{"$ref": "#/components/parameters/IdempotencyKey"}
|
||
|
|
],
|
||
|
|
"requestBody": {
|
||
|
|
"required": true,
|
||
|
|
"content": {
|
||
|
|
"application/json": {"schema": {"$ref": "#/components/schemas/BatchDesiredStateRequest"}}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"responses": {
|
||
|
|
"202": {
|
||
|
|
"description": "请求已接收;响应包含已知的逐项接受/拒绝结果,后续状态从 operation 读取",
|
||
|
|
"headers": {
|
||
|
|
"Location": {"$ref": "#/components/headers/OperationLocation"},
|
||
|
|
"X-Trace-ID": {"$ref": "#/components/headers/TraceID"}
|
||
|
|
},
|
||
|
|
"content": {
|
||
|
|
"application/json": {"schema": {"$ref": "#/components/schemas/BatchOperation"}}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"400": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"401": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"404": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"409": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"422": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"503": {"$ref": "#/components/responses/ErrorResponse"}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"/api/v1/operations/{operation_id}": {
|
||
|
|
"get": {
|
||
|
|
"tags": ["Operations"],
|
||
|
|
"operationId": "getOperation",
|
||
|
|
"summary": "查询批量写入和逐项结果",
|
||
|
|
"parameters": [
|
||
|
|
{"$ref": "#/components/parameters/OperationID"}
|
||
|
|
],
|
||
|
|
"responses": {
|
||
|
|
"200": {
|
||
|
|
"description": "批量操作状态",
|
||
|
|
"headers": {"X-Trace-ID": {"$ref": "#/components/headers/TraceID"}},
|
||
|
|
"content": {
|
||
|
|
"application/json": {"schema": {"$ref": "#/components/schemas/BatchOperation"}}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"401": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"404": {"$ref": "#/components/responses/ErrorResponse"},
|
||
|
|
"500": {"$ref": "#/components/responses/ErrorResponse"}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"components": {
|
||
|
|
"securitySchemes": {
|
||
|
|
"bearerAuth": {
|
||
|
|
"type": "http",
|
||
|
|
"scheme": "bearer",
|
||
|
|
"bearerFormat": "opaque",
|
||
|
|
"description": "认证实现与 claim 格式不属于 v1 契约;服务端必须从已验证主体确定 tenant 与权限。"
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"parameters": {
|
||
|
|
"SiteID": {
|
||
|
|
"name": "site_id",
|
||
|
|
"in": "path",
|
||
|
|
"required": true,
|
||
|
|
"schema": {"$ref": "#/components/schemas/LogicalID"},
|
||
|
|
"description": "当前认证租户中的稳定站点 ID"
|
||
|
|
},
|
||
|
|
"DeviceID": {
|
||
|
|
"name": "device_id",
|
||
|
|
"in": "path",
|
||
|
|
"required": true,
|
||
|
|
"schema": {"$ref": "#/components/schemas/LogicalID"}
|
||
|
|
},
|
||
|
|
"OperationID": {
|
||
|
|
"name": "operation_id",
|
||
|
|
"in": "path",
|
||
|
|
"required": true,
|
||
|
|
"schema": {"type": "string", "pattern": "^op_[0-9A-HJKMNP-TV-Z]{26}$"}
|
||
|
|
},
|
||
|
|
"Cursor": {
|
||
|
|
"name": "cursor",
|
||
|
|
"in": "query",
|
||
|
|
"required": false,
|
||
|
|
"schema": {"type": "string", "minLength": 16, "maxLength": 512},
|
||
|
|
"description": "不透明游标;客户端不得解析或构造"
|
||
|
|
},
|
||
|
|
"Limit": {
|
||
|
|
"name": "limit",
|
||
|
|
"in": "query",
|
||
|
|
"required": false,
|
||
|
|
"schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}
|
||
|
|
},
|
||
|
|
"ModalityFilter": {
|
||
|
|
"name": "modality",
|
||
|
|
"in": "query",
|
||
|
|
"required": false,
|
||
|
|
"schema": {"$ref": "#/components/schemas/Modality"}
|
||
|
|
},
|
||
|
|
"CapabilityFilter": {
|
||
|
|
"name": "capability",
|
||
|
|
"in": "query",
|
||
|
|
"required": false,
|
||
|
|
"schema": {"$ref": "#/components/schemas/Capability"}
|
||
|
|
},
|
||
|
|
"DesiredStateFilter": {
|
||
|
|
"name": "desired_state",
|
||
|
|
"in": "query",
|
||
|
|
"required": false,
|
||
|
|
"schema": {"$ref": "#/components/schemas/DesiredState"}
|
||
|
|
},
|
||
|
|
"ActualStateFilter": {
|
||
|
|
"name": "actual_state",
|
||
|
|
"in": "query",
|
||
|
|
"required": false,
|
||
|
|
"schema": {"$ref": "#/components/schemas/ActualState"}
|
||
|
|
},
|
||
|
|
"IdempotencyKey": {
|
||
|
|
"name": "Idempotency-Key",
|
||
|
|
"in": "header",
|
||
|
|
"required": true,
|
||
|
|
"schema": {
|
||
|
|
"type": "string",
|
||
|
|
"minLength": 16,
|
||
|
|
"maxLength": 128,
|
||
|
|
"pattern": "^[A-Za-z0-9._:-]+$"
|
||
|
|
},
|
||
|
|
"description": "同一认证主体、站点、operationId、key 和规范化 body 在 24 小时内返回同一结果;key 相同而 body 不同返回 idempotency_conflict。"
|
||
|
|
},
|
||
|
|
"IfMatch": {
|
||
|
|
"name": "If-Match",
|
||
|
|
"in": "header",
|
||
|
|
"required": true,
|
||
|
|
"schema": {"type": "string", "minLength": 3, "maxLength": 128},
|
||
|
|
"description": "使用最近一次 GET/写响应的 opaque ETag;不匹配返回 412 etag_mismatch。"
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"headers": {
|
||
|
|
"ETag": {
|
||
|
|
"description": "设备资源的不透明并发版本",
|
||
|
|
"schema": {"type": "string"}
|
||
|
|
},
|
||
|
|
"TraceID": {
|
||
|
|
"description": "不含租户、主机或凭据的排查 ID",
|
||
|
|
"schema": {"type": "string", "minLength": 8, "maxLength": 128}
|
||
|
|
},
|
||
|
|
"DeviceLocation": {
|
||
|
|
"description": "新建设备资源的相对路径",
|
||
|
|
"schema": {"type": "string", "pattern": "^/api/v1/sites/[^/]+/devices/[^/]+$"}
|
||
|
|
},
|
||
|
|
"OperationLocation": {
|
||
|
|
"description": "批量操作资源的相对路径",
|
||
|
|
"schema": {"type": "string", "pattern": "^/api/v1/operations/op_[0-9A-HJKMNP-TV-Z]{26}$"}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"responses": {
|
||
|
|
"CurrentDevice": {
|
||
|
|
"description": "设备当前表示;endpoint 与 credential ref 永不回显",
|
||
|
|
"headers": {
|
||
|
|
"ETag": {"$ref": "#/components/headers/ETag"},
|
||
|
|
"X-Trace-ID": {"$ref": "#/components/headers/TraceID"}
|
||
|
|
},
|
||
|
|
"content": {
|
||
|
|
"application/json": {"schema": {"$ref": "#/components/schemas/Device"}}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"CreatedDevice": {
|
||
|
|
"description": "设备已创建;启用设备仍需等待对账收敛",
|
||
|
|
"headers": {
|
||
|
|
"ETag": {"$ref": "#/components/headers/ETag"},
|
||
|
|
"Location": {"$ref": "#/components/headers/DeviceLocation"},
|
||
|
|
"X-Trace-ID": {"$ref": "#/components/headers/TraceID"}
|
||
|
|
},
|
||
|
|
"content": {
|
||
|
|
"application/json": {"schema": {"$ref": "#/components/schemas/Device"}}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"AcceptedMutation": {
|
||
|
|
"description": "期望态/配置写入已接受,实际态异步收敛",
|
||
|
|
"headers": {
|
||
|
|
"ETag": {"$ref": "#/components/headers/ETag"},
|
||
|
|
"X-Trace-ID": {"$ref": "#/components/headers/TraceID"}
|
||
|
|
},
|
||
|
|
"content": {
|
||
|
|
"application/json": {"schema": {"$ref": "#/components/schemas/MutationReceipt"}}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"ErrorResponse": {
|
||
|
|
"description": "稳定错误;不返回内部堆栈、资源存在性或连接秘密",
|
||
|
|
"headers": {"X-Trace-ID": {"$ref": "#/components/headers/TraceID"}},
|
||
|
|
"content": {
|
||
|
|
"application/problem+json": {"schema": {"$ref": "#/components/schemas/Problem"}}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"schemas": {
|
||
|
|
"LogicalID": {
|
||
|
|
"type": "string",
|
||
|
|
"minLength": 1,
|
||
|
|
"maxLength": 64,
|
||
|
|
"pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$"
|
||
|
|
},
|
||
|
|
"Modality": {
|
||
|
|
"type": "string",
|
||
|
|
"enum": ["video", "radar", "contact", "button", "wearable", "other"]
|
||
|
|
},
|
||
|
|
"Capability": {
|
||
|
|
"type": "string",
|
||
|
|
"enum": ["video_capture", "audio_capture", "spatial_rule", "telemetry"]
|
||
|
|
},
|
||
|
|
"DesiredState": {
|
||
|
|
"type": "string",
|
||
|
|
"enum": ["disabled", "enabled"]
|
||
|
|
},
|
||
|
|
"ActualState": {
|
||
|
|
"type": "string",
|
||
|
|
"enum": ["pending", "online", "offline", "failed"]
|
||
|
|
},
|
||
|
|
"AdapterStatus": {
|
||
|
|
"type": "string",
|
||
|
|
"enum": ["pending", "ready", "adapter_not_ready", "authentication_failed", "unavailable"]
|
||
|
|
},
|
||
|
|
"ErrorCode": {
|
||
|
|
"type": "string",
|
||
|
|
"enum": [
|
||
|
|
"invalid_request",
|
||
|
|
"unauthenticated",
|
||
|
|
"forbidden",
|
||
|
|
"not_found",
|
||
|
|
"conflict",
|
||
|
|
"precondition_required",
|
||
|
|
"etag_mismatch",
|
||
|
|
"idempotency_conflict",
|
||
|
|
"duplicate_serial_number",
|
||
|
|
"quota_exceeded",
|
||
|
|
"quota_projection_unavailable",
|
||
|
|
"quota_projection_invalid",
|
||
|
|
"area_policy_denied",
|
||
|
|
"area_policy_unavailable",
|
||
|
|
"adapter_not_ready",
|
||
|
|
"authentication_failed",
|
||
|
|
"endpoint_credentials_forbidden",
|
||
|
|
"batch_too_large",
|
||
|
|
"service_unavailable",
|
||
|
|
"internal_error"
|
||
|
|
]
|
||
|
|
},
|
||
|
|
"DeviceCreate": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["serial_number", "name", "modality", "capabilities", "area_id"],
|
||
|
|
"properties": {
|
||
|
|
"serial_number": {"type": "string", "minLength": 1, "maxLength": 128},
|
||
|
|
"name": {"type": "string", "minLength": 1, "maxLength": 200},
|
||
|
|
"modality": {"$ref": "#/components/schemas/Modality"},
|
||
|
|
"capabilities": {
|
||
|
|
"type": "array",
|
||
|
|
"minItems": 1,
|
||
|
|
"maxItems": 16,
|
||
|
|
"uniqueItems": true,
|
||
|
|
"items": {"$ref": "#/components/schemas/Capability"},
|
||
|
|
"description": "请求接入的能力集合;适配器探测不支持时以稳定错误拒绝或标记 adapter_not_ready。"
|
||
|
|
},
|
||
|
|
"area_id": {"$ref": "#/components/schemas/LogicalID"},
|
||
|
|
"endpoint_ref": {
|
||
|
|
"type": "string",
|
||
|
|
"format": "uri",
|
||
|
|
"minLength": 1,
|
||
|
|
"maxLength": 2048,
|
||
|
|
"writeOnly": true,
|
||
|
|
"description": "绝对 URI,禁止 userinfo;只在受控写路径使用。"
|
||
|
|
},
|
||
|
|
"credential_ref": {
|
||
|
|
"type": "string",
|
||
|
|
"minLength": 1,
|
||
|
|
"maxLength": 512,
|
||
|
|
"writeOnly": true,
|
||
|
|
"description": "不透明密钥引用,不是用户名、密码或 token。"
|
||
|
|
},
|
||
|
|
"profile_token": {
|
||
|
|
"type": "string",
|
||
|
|
"minLength": 1,
|
||
|
|
"maxLength": 256,
|
||
|
|
"writeOnly": true
|
||
|
|
},
|
||
|
|
"desired_state": {
|
||
|
|
"allOf": [{"$ref": "#/components/schemas/DesiredState"}],
|
||
|
|
"default": "disabled"
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"allOf": [
|
||
|
|
{
|
||
|
|
"if": {
|
||
|
|
"required": ["modality"],
|
||
|
|
"properties": {"modality": {"const": "video"}}
|
||
|
|
},
|
||
|
|
"then": {
|
||
|
|
"properties": {
|
||
|
|
"capabilities": {"contains": {"const": "video_capture"}, "minContains": 1}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"if": {
|
||
|
|
"required": ["capabilities"],
|
||
|
|
"properties": {
|
||
|
|
"capabilities": {"contains": {"const": "video_capture"}, "minContains": 1}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"then": {"required": ["endpoint_ref", "credential_ref"]}
|
||
|
|
}
|
||
|
|
]
|
||
|
|
},
|
||
|
|
"DevicePatch": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"minProperties": 1,
|
||
|
|
"properties": {
|
||
|
|
"name": {"type": "string", "minLength": 1, "maxLength": 200},
|
||
|
|
"area_id": {"$ref": "#/components/schemas/LogicalID"},
|
||
|
|
"endpoint_ref": {
|
||
|
|
"type": "string",
|
||
|
|
"format": "uri",
|
||
|
|
"minLength": 1,
|
||
|
|
"maxLength": 2048,
|
||
|
|
"writeOnly": true,
|
||
|
|
"description": "绝对 URI,禁止 userinfo。"
|
||
|
|
},
|
||
|
|
"credential_ref": {
|
||
|
|
"type": "string",
|
||
|
|
"minLength": 1,
|
||
|
|
"maxLength": 512,
|
||
|
|
"writeOnly": true
|
||
|
|
},
|
||
|
|
"profile_token": {
|
||
|
|
"type": "string",
|
||
|
|
"minLength": 1,
|
||
|
|
"maxLength": 256,
|
||
|
|
"writeOnly": true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"DesiredStateChange": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["desired_state", "reason"],
|
||
|
|
"properties": {
|
||
|
|
"desired_state": {"$ref": "#/components/schemas/DesiredState"},
|
||
|
|
"reason": {"type": "string", "minLength": 1, "maxLength": 500}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"Device": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": [
|
||
|
|
"id", "tenant_id", "site_id", "serial_number", "name", "modality",
|
||
|
|
"capabilities", "area_id", "desired_state", "actual_state", "adapter_status",
|
||
|
|
"endpoint_configured", "credential_configured", "generation", "observed_generation",
|
||
|
|
"converged", "failure_count", "projection_versions", "created_at", "updated_at"
|
||
|
|
],
|
||
|
|
"properties": {
|
||
|
|
"id": {"$ref": "#/components/schemas/LogicalID"},
|
||
|
|
"tenant_id": {
|
||
|
|
"allOf": [{"$ref": "#/components/schemas/LogicalID"}],
|
||
|
|
"readOnly": true,
|
||
|
|
"description": "只用于回显已授权上下文,不得由客户端写入。"
|
||
|
|
},
|
||
|
|
"site_id": {"$ref": "#/components/schemas/LogicalID"},
|
||
|
|
"serial_number": {"type": "string", "minLength": 1, "maxLength": 128},
|
||
|
|
"name": {"type": "string", "minLength": 1, "maxLength": 200},
|
||
|
|
"modality": {"$ref": "#/components/schemas/Modality"},
|
||
|
|
"capabilities": {
|
||
|
|
"type": "array",
|
||
|
|
"items": {"$ref": "#/components/schemas/Capability"},
|
||
|
|
"uniqueItems": true,
|
||
|
|
"maxItems": 16,
|
||
|
|
"readOnly": true
|
||
|
|
},
|
||
|
|
"area_id": {"$ref": "#/components/schemas/LogicalID"},
|
||
|
|
"desired_state": {"$ref": "#/components/schemas/DesiredState"},
|
||
|
|
"actual_state": {"$ref": "#/components/schemas/ActualState"},
|
||
|
|
"adapter_status": {"$ref": "#/components/schemas/AdapterStatus"},
|
||
|
|
"endpoint_configured": {"type": "boolean", "readOnly": true},
|
||
|
|
"credential_configured": {"type": "boolean", "readOnly": true},
|
||
|
|
"generation": {"type": "integer", "format": "int64", "minimum": 1, "readOnly": true},
|
||
|
|
"observed_generation": {"type": "integer", "format": "int64", "minimum": 0, "readOnly": true},
|
||
|
|
"converged": {
|
||
|
|
"type": "boolean",
|
||
|
|
"readOnly": true,
|
||
|
|
"description": "期望代已被观察且当前无待重试;不等价于所有外部系统健康。"
|
||
|
|
},
|
||
|
|
"failure_count": {"type": "integer", "minimum": 0, "readOnly": true},
|
||
|
|
"next_attempt_at": {"type": ["string", "null"], "format": "date-time", "readOnly": true},
|
||
|
|
"last_error_code": {"type": ["string", "null"], "maxLength": 128, "readOnly": true},
|
||
|
|
"projection_versions": {"$ref": "#/components/schemas/ProjectionVersions"},
|
||
|
|
"created_at": {"type": "string", "format": "date-time", "readOnly": true},
|
||
|
|
"updated_at": {"type": "string", "format": "date-time", "readOnly": true}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"ProjectionVersions": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["quota_source_version", "area_policy_source_version", "synced_at"],
|
||
|
|
"properties": {
|
||
|
|
"quota_source_version": {"type": ["integer", "null"], "format": "int64", "minimum": 1, "readOnly": true},
|
||
|
|
"area_policy_source_version": {"type": ["integer", "null"], "format": "int64", "minimum": 1, "readOnly": true},
|
||
|
|
"synced_at": {"type": ["string", "null"], "format": "date-time", "readOnly": true}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"SiteQuotaStatus": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["status", "used_video_channels", "max_video_channels", "available_video_channels", "over_limit", "source_version", "synced_at"],
|
||
|
|
"properties": {
|
||
|
|
"status": {"type": "string", "enum": ["current", "unavailable", "invalid"]},
|
||
|
|
"used_video_channels": {"type": "integer", "minimum": 0, "maximum": 128},
|
||
|
|
"max_video_channels": {"type": ["integer", "null"], "minimum": 1, "maximum": 128},
|
||
|
|
"available_video_channels": {"type": ["integer", "null"], "minimum": 0, "maximum": 128},
|
||
|
|
"over_limit": {"type": "boolean"},
|
||
|
|
"source_version": {"type": ["integer", "null"], "format": "int64", "minimum": 1},
|
||
|
|
"synced_at": {"type": ["string", "null"], "format": "date-time"}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"PageInfo": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["limit", "has_more", "next_cursor"],
|
||
|
|
"properties": {
|
||
|
|
"limit": {"type": "integer", "minimum": 1, "maximum": 100},
|
||
|
|
"has_more": {"type": "boolean"},
|
||
|
|
"next_cursor": {"type": ["string", "null"], "maxLength": 512}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"DevicePage": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["items", "page", "quota"],
|
||
|
|
"properties": {
|
||
|
|
"items": {"type": "array", "maxItems": 100, "items": {"$ref": "#/components/schemas/Device"}},
|
||
|
|
"page": {"$ref": "#/components/schemas/PageInfo"},
|
||
|
|
"quota": {"$ref": "#/components/schemas/SiteQuotaStatus"}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"MutationReceipt": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["device", "accepted_at", "trace_id"],
|
||
|
|
"properties": {
|
||
|
|
"device": {"$ref": "#/components/schemas/Device"},
|
||
|
|
"accepted_at": {"type": "string", "format": "date-time"},
|
||
|
|
"trace_id": {"type": "string", "minLength": 8, "maxLength": 128}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"BatchDesiredStateItem": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["device_id", "etag", "desired_state"],
|
||
|
|
"properties": {
|
||
|
|
"device_id": {"$ref": "#/components/schemas/LogicalID"},
|
||
|
|
"etag": {"type": "string", "minLength": 3, "maxLength": 128},
|
||
|
|
"desired_state": {"$ref": "#/components/schemas/DesiredState"}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"BatchDesiredStateRequest": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["items", "reason"],
|
||
|
|
"properties": {
|
||
|
|
"items": {
|
||
|
|
"type": "array",
|
||
|
|
"minItems": 1,
|
||
|
|
"maxItems": 128,
|
||
|
|
"items": {"$ref": "#/components/schemas/BatchDesiredStateItem"}
|
||
|
|
},
|
||
|
|
"reason": {"type": "string", "minLength": 1, "maxLength": 500}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"BatchItemResult": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["device_id", "status", "error_code", "message", "generation"],
|
||
|
|
"properties": {
|
||
|
|
"device_id": {"$ref": "#/components/schemas/LogicalID"},
|
||
|
|
"status": {"type": "string", "enum": ["accepted", "rejected", "succeeded", "failed"]},
|
||
|
|
"error_code": {"oneOf": [{"$ref": "#/components/schemas/ErrorCode"}, {"type": "null"}]},
|
||
|
|
"message": {"type": ["string", "null"], "maxLength": 500},
|
||
|
|
"generation": {"type": ["integer", "null"], "format": "int64", "minimum": 1}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"BatchOperation": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["id", "status", "submitted_at", "completed_at", "results", "trace_id"],
|
||
|
|
"properties": {
|
||
|
|
"id": {"type": "string", "pattern": "^op_[0-9A-HJKMNP-TV-Z]{26}$"},
|
||
|
|
"status": {"type": "string", "enum": ["queued", "running", "succeeded", "partially_succeeded", "failed"]},
|
||
|
|
"submitted_at": {"type": "string", "format": "date-time"},
|
||
|
|
"completed_at": {"type": ["string", "null"], "format": "date-time"},
|
||
|
|
"results": {"type": "array", "maxItems": 128, "items": {"$ref": "#/components/schemas/BatchItemResult"}},
|
||
|
|
"trace_id": {"type": "string", "minLength": 8, "maxLength": 128}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"FieldError": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["field", "code", "message"],
|
||
|
|
"properties": {
|
||
|
|
"field": {"type": "string", "maxLength": 256},
|
||
|
|
"code": {"type": "string", "maxLength": 128},
|
||
|
|
"message": {"type": "string", "maxLength": 500}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"Problem": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["type", "title", "status", "code", "message", "trace_id", "field_errors"],
|
||
|
|
"properties": {
|
||
|
|
"type": {"type": "string", "format": "uri-reference"},
|
||
|
|
"title": {"type": "string", "maxLength": 200},
|
||
|
|
"status": {"type": "integer", "minimum": 400, "maximum": 599},
|
||
|
|
"code": {"$ref": "#/components/schemas/ErrorCode"},
|
||
|
|
"message": {"type": "string", "maxLength": 1000},
|
||
|
|
"trace_id": {"type": "string", "minLength": 8, "maxLength": 128},
|
||
|
|
"field_errors": {"type": "array", "maxItems": 100, "items": {"$ref": "#/components/schemas/FieldError"}}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|