feat: expand companion platform, device controls, and memoir workflows
ci / verify (push) Canceled after 0s
ci / verify (push) Canceled after 0s
Add customer and operator login, BLE provisioning, device fleet controls, call memory, memoir generation, and refreshed family and maintenance portals. Include API contracts, migrations, firmware sources, tests, assets, and deployment documentation.
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: 蓝牙配网与账号绑定
|
||||
version: 1.1.1
|
||||
description: 蓝牙只传 Wi-Fi 与一次性绑定令牌,账号身份从登录态获取。实际响应统一使用 ok/code/request_id/server_time_ms/data 信封。
|
||||
paths:
|
||||
/api/v1/web/ble-bind-tokens:
|
||||
post:
|
||||
summary: 为已登录账号签发5分钟一次性设备绑定令牌
|
||||
security:
|
||||
- Bearer: []
|
||||
- AccountCookie: []
|
||||
description: Cookie 请求必须同源并携带 X-CSRF-Token。省略 expected_binding_id 时设备必须未添加;省略 elder_id 时仅添加到账号。更换已绑定设备的使用老人必须同时提交 elder_id 和当前 expected_binding_id,账号需有原家庭及目标家庭设备管理权限。申请不改变原归属,设备实体确认后才原子完成转移;届时再次检查权限、归属版本、通话及升级。仅替换本人对该设备的未完成令牌。
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [device_id]
|
||||
properties:
|
||||
device_id: {type: string, pattern: '^KP01-[0-9A-F]{12}$'}
|
||||
elder_id: {type: string, format: uuid, description: 可省略;省略表示先添加到账号,之后在设备管理中绑定老人。不会发送到蓝牙设备}
|
||||
expected_binding_id: {type: string, format: uuid, description: 更换使用老人时必填,为 binding-impact 返回的当前绑定 UUID。配网及普通添加不得携带。}
|
||||
responses:
|
||||
'200': {description: 'data: {bind_token: 43字符Base64URL令牌}'}
|
||||
'400': {description: 'DEVICE_ID_INVALID:设备编号格式错误;ELDER_ID_INVALID:老人编号格式错误;PROFILE_REQUIRED:显式选择的使用者不可管理'}
|
||||
'403': {description: '按具体原因返回账号、组织、设备状态或归属权限错误;与 mini/ble-device-state 一致,message 为可直接展示的中文原因,不再合并提示'}
|
||||
'404': {description: 'DEVICE_NOT_REGISTERED:平台没有该设备的注册记录'}
|
||||
'409': {description: 'DEVICE_NOT_RELEASED / DEVICE_ENROLLMENT_UNSUPPORTED / DEVICE_BINDING_STALE / ALREADY_BOUND;message 给出相应处理方式'}
|
||||
default: {description: 权限不足、设备已绑定、使用者未选择或服务暂不可用}
|
||||
/api/v1/web/ble-bind-status:
|
||||
post:
|
||||
summary: 由签发账号查询平台绑定结果
|
||||
security:
|
||||
- Bearer: []
|
||||
- AccountCookie: []
|
||||
description: 同源和CSRF要求同签发接口。平台成功不代表设备已经保存Wi-Fi;蓝牙断开后可用此接口确认云端结果。
|
||||
requestBody:
|
||||
$ref: '#/components/requestBodies/Token'
|
||||
responses:
|
||||
'200': {description: 'data.status 为 pending/success/failed,可附 message'}
|
||||
default: {description: 不属于当前账号的令牌不可查询}
|
||||
/api/v1/device/ble-bind:
|
||||
post:
|
||||
summary: 设备绑定并同步取得火山连接配置
|
||||
security:
|
||||
- DeviceRequest: []
|
||||
description: HTTPS,DEVREQ1九行HMAC签名;X-Device-ID、X-Key-Version、X-Timestamp-Ms、X-Nonce、X-Request-ID 必填。每次重试刷新nonce,保留实体确认事件的request ID。已提交令牌的重试返回同一有效绑定;不会抢占已有设备归属。
|
||||
requestBody:
|
||||
$ref: '#/components/requestBodies/Token'
|
||||
responses:
|
||||
'200':
|
||||
description: data直接带status及5个火山字段,无voice_status/voice。平台取齐才成功,设备保存配置与Wi-Fi后才报告蓝牙success;凭据不转发小程序。设备超时设45秒,平台取参等待上限35秒。
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [ok, data]
|
||||
properties:
|
||||
ok: {const: true}
|
||||
code: {type: string}
|
||||
request_id: {type: string}
|
||||
server_time_ms: {type: integer}
|
||||
data:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [status, instance_id, product_key, device_name, device_secret, RTCAppID]
|
||||
properties:
|
||||
status: {const: success}
|
||||
instance_id: {type: string, minLength: 1}
|
||||
product_key: {type: string, minLength: 1}
|
||||
device_name: {type: string, minLength: 1}
|
||||
device_secret: {type: string, minLength: 16, maxLength: 256}
|
||||
RTCAppID: {type: string, minLength: 1, maxLength: 128}
|
||||
'409': {description: 'BINDING_CHANGED:等待期间解绑/归属变化;VOICE_MIGRATION_REQUIRED:需补交旧设备凭据。另有原令牌错误。'}
|
||||
'502': {description: 'VOICE_REGISTRATION_FAILED / VOICE_CONFIG_INVALID:未取得完整配置,已完成绑定保留。注册结果不确定由平台核对,不重复注册。'}
|
||||
'503': {description: 'VOICE_REGISTRATION_PAUSED:语音暂停,已完成绑定保留;也可能是绑定暂停。'}
|
||||
'504': {description: 'VOICE_REGISTRATION_TIMEOUT:取参超时,保留原令牌重试;已完成绑定保留。'}
|
||||
default: {description: 令牌无效、过期、归属变化或服务暂不可用;网络超时/5xx不应视为绑定失败}
|
||||
components:
|
||||
securitySchemes:
|
||||
Bearer: {type: http, scheme: bearer}
|
||||
AccountCookie: {type: apiKey, in: cookie, name: __Host-platform-onboarding}
|
||||
DeviceRequest: {type: apiKey, in: header, name: Authorization, description: 'Device-HMAC-SHA256 后接64字符小写十六进制MAC'}
|
||||
requestBodies:
|
||||
Token:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [bind_token]
|
||||
properties:
|
||||
bind_token: {type: string, pattern: '^[A-Za-z0-9_-]{43}$'}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,271 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: 家庭端手机号登录
|
||||
version: 1.1.0
|
||||
paths:
|
||||
/api/v1/web/login/session:
|
||||
get:
|
||||
operationId: customerLoginSession
|
||||
summary: 初始化手机号登录页面
|
||||
description: HTTPS,同源,不接受查询参数。签发 HttpOnly 登录 Cookie 和 CSRF token,20 分钟后过期,同一 Cookie 重载不会轮换 CSRF。短信不可用时仍可使用密码登录。
|
||||
security: []
|
||||
responses:
|
||||
'200':
|
||||
description: 页面状态;sms_enabled=false 不代表发送成功
|
||||
headers:
|
||||
Set-Cookie:
|
||||
schema: { type: string }
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [ok, data]
|
||||
properties:
|
||||
ok: { type: boolean }
|
||||
data:
|
||||
type: object
|
||||
required: [sms_enabled, password_enabled, csrf_token]
|
||||
properties:
|
||||
sms_enabled: { type: boolean }
|
||||
password_enabled: { type: boolean }
|
||||
signup_enabled: { type: boolean }
|
||||
csrf_token: { type: string }
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
/api/v1/web/login/sms/send:
|
||||
post:
|
||||
operationId: customerSendLoginSMS
|
||||
summary: 发送家庭端登录验证码
|
||||
description: 6 位随机验证码,5 分钟有效;每个手机号至少间隔 60 秒、每小时最多 5 次,设备绑定入口共用此限额。同一请求号重试不重复发送。手机号加密、验证码仅存 keyed hash;不在响应中返回验证码。
|
||||
security: [{ CustomerLoginCookie: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/RequestID' }
|
||||
- { $ref: '#/components/parameters/CSRF' }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: './onboarding.yaml#/components/schemas/SMSSendInput' }
|
||||
responses:
|
||||
'200':
|
||||
description: 网关已接受发送请求
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: './onboarding.yaml#/components/schemas/SMSResponse' }
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
/api/v1/web/login/sms/verify:
|
||||
post:
|
||||
operationId: customerVerifyLoginSMS
|
||||
summary: 验证验证码并创建家庭端登录会话
|
||||
description: 验证码只能在发起发送的浏览器会话使用,最多尝试 5 次,成功后一次性消费。已有短信账号复用原身份;仅配置唯一自助注册租户时可自动创建普通客户账号。账号 Cookie 24 小时有效,调用家庭写接口还需 CSRF;不授予运维权限。
|
||||
security: [{ CustomerLoginCookie: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/RequestID' }
|
||||
- { $ref: '#/components/parameters/CSRF' }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: './onboarding.yaml#/components/schemas/SMSVerifyInput' }
|
||||
responses:
|
||||
'200':
|
||||
description: 签发 HttpOnly 账号 Cookie,消费匿名登录会话;前端继续读取 /api/v1/me 校验业务账号
|
||||
headers:
|
||||
Set-Cookie:
|
||||
schema: { type: string }
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [ok, data]
|
||||
properties:
|
||||
ok: { type: boolean }
|
||||
data:
|
||||
type: object
|
||||
required: [csrf_token, data]
|
||||
properties:
|
||||
csrf_token: { type: string }
|
||||
data:
|
||||
type: object
|
||||
required: [authenticated]
|
||||
properties:
|
||||
authenticated: { type: boolean }
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
/api/v1/web/login/captcha:
|
||||
post:
|
||||
operationId: customerLoginCaptcha
|
||||
summary: 获取或更换密码登录、发送短信前的人机验证
|
||||
description: 服务端选择图片、腾讯云或本地拼图滑块模式,不返回答案或目标横坐标。绑定登录 Cookie,2 分钟有效;刷新使旧挑战失效;每次校验均消费验证码。滑块需先调用 captcha/verify,成功票据再随短信或密码请求提交。校验状态保存在 Redis,依赖不可用时拒绝登录。
|
||||
security: [{ CustomerLoginCookie: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/RequestID' }
|
||||
- { $ref: '#/components/parameters/CSRF' }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { type: object, additionalProperties: false }
|
||||
responses:
|
||||
'200':
|
||||
description: 图片验证码
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [ok, data]
|
||||
properties:
|
||||
ok: { type: boolean }
|
||||
data:
|
||||
type: object
|
||||
required: [captcha_id, mode, expires_at_ms]
|
||||
properties:
|
||||
captcha_id: { type: string, format: uuid }
|
||||
mode: { type: string, enum: [image, tencent, slide] }
|
||||
captcha_app_id: { type: string, description: 腾讯云模式对应客户端的公开 CaptchaAppId,不含密钥 }
|
||||
image: { type: string, pattern: '^data:image/(png|jpeg);base64,' }
|
||||
thumb_image: { type: string, pattern: '^data:image/png;base64,' }
|
||||
image_width: { type: integer, minimum: 1 }
|
||||
image_height: { type: integer, minimum: 1 }
|
||||
thumb_width: { type: integer, minimum: 1 }
|
||||
thumb_height: { type: integer, minimum: 1 }
|
||||
thumb_x: { type: integer, minimum: 0, description: 拼图块的初始展示横坐标 }
|
||||
thumb_y: { type: integer, minimum: 0, description: 拼图块所在水平轨道 }
|
||||
expires_at_ms: { type: integer, format: int64 }
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
/api/v1/web/login/captcha/verify:
|
||||
post:
|
||||
operationId: customerVerifyLocalSlideCaptcha
|
||||
summary: 校验本地滑块位置并换取一次性票据
|
||||
description: 同源、CSRF 和登录会话校验;挑战每次提交即消费。成功票据绑定原会话、客户端、策略版本和原到期时间,只能用于一次短信发送或密码登录。
|
||||
security: [{ CustomerLoginCookie: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/RequestID' }
|
||||
- { $ref: '#/components/parameters/CSRF' }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: './login-captcha.yaml#/components/schemas/SlideCaptchaVerifyInput' }
|
||||
responses:
|
||||
'200':
|
||||
description: 位置正确,返回一次性校验票据
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: './login-captcha.yaml#/components/schemas/SlideCaptchaVerifyResponse' }
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
/api/v1/web/login/password:
|
||||
post:
|
||||
operationId: customerLoginPassword
|
||||
summary: 手机号、密码和图片验证码登录
|
||||
description: 使用与短信登录一致的手机号身份,密码登录不自动注册。每手机号 10 分钟最多 10 次密码尝试;每登录会话最多 20 次。失败返回统一的手机号或密码错误,不暴露手机号是否注册。密码正确但没有该账号的有效设备验证 Cookie 时返回 403 NEW_DEVICE_SMS_REQUIRED,不消费登录会话、不发账号 Cookie;完成现有 LOGIN 短信验证后签发 30 天 HttpOnly 设备验证 Cookie。已验证设备成功消费登录会话,签发 24 小时账号 Cookie。
|
||||
security: [{ CustomerLoginCookie: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/RequestID' }
|
||||
- { $ref: '#/components/parameters/CSRF' }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [phone_e164, password, captcha_id]
|
||||
anyOf:
|
||||
- required: [captcha_code]
|
||||
- required: [captcha_ticket]
|
||||
properties:
|
||||
phone_e164: { type: string, pattern: '^\+[1-9][0-9]{7,14}$' }
|
||||
password: { type: string, minLength: 1, maxLength: 256, writeOnly: true }
|
||||
captcha_id: { type: string, format: uuid }
|
||||
captcha_code: { type: string, pattern: '^[0-9]{6}$', writeOnly: true }
|
||||
captcha_ticket: { type: string, maxLength: 4096, writeOnly: true }
|
||||
captcha_randstr: { type: string, maxLength: 256, writeOnly: true, description: 腾讯云 Web 模式必填,本地滑块模式无需提供 }
|
||||
responses:
|
||||
'200':
|
||||
$ref: '#/paths/~1api~1v1~1web~1login~1sms~1verify/post/responses/200'
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
/api/v1/web/account/password:
|
||||
get:
|
||||
operationId: customerPasswordState
|
||||
summary: 查看当前手机号和密码设置状态
|
||||
security: [{ CustomerAccountCookie: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: 仅返回脱敏手机号、是否已设置密码、是否具有最近 10 分钟内且未消费的短信验证,不返回密码或摘要
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok: { type: boolean }
|
||||
data:
|
||||
type: object
|
||||
required: [available]
|
||||
properties:
|
||||
available: { type: boolean }
|
||||
phone_masked: { type: string }
|
||||
password_configured: { type: boolean }
|
||||
sms_verified_recently: { type: boolean }
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
post:
|
||||
operationId: customerSetPassword
|
||||
summary: 设置、修改或重置当前手机号的密码
|
||||
description: 需要当前有效账号 Cookie、同源及 CSRF;同时需要最近 10 分钟内且未消费的短信验证,或正确的当前密码。新密码 6–64 个 Unicode 字符且不超过 256 字节。修改后清除短信证明并撤销该身份的其他账号和设备绑定浏览器会话,保留本次会话。密码使用随机盐 Argon2id 存储。
|
||||
security: [{ CustomerAccountCookie: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/RequestID' }
|
||||
- { $ref: '#/components/parameters/CSRF' }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [password]
|
||||
properties:
|
||||
password: { type: string, minLength: 6, maxLength: 64, writeOnly: true }
|
||||
current_password: { type: string, maxLength: 256, writeOnly: true }
|
||||
responses:
|
||||
'200':
|
||||
description: 密码已保存
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok: { type: boolean }
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
password_configured: { type: boolean }
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
components:
|
||||
securitySchemes:
|
||||
CustomerAccountCookie:
|
||||
type: apiKey
|
||||
in: cookie
|
||||
name: __Host-platform-onboarding
|
||||
description: 仅本地 HTTP 模式使用 platform-onboarding。不能用于运维接口。
|
||||
CustomerLoginCookie:
|
||||
type: apiKey
|
||||
in: cookie
|
||||
name: __Host-platform-login
|
||||
description: Secure、HttpOnly、SameSite=Lax;仅本地 HTTP 模式使用 platform-login。
|
||||
parameters:
|
||||
RequestID:
|
||||
in: header
|
||||
name: X-Request-ID
|
||||
required: true
|
||||
schema: { type: string, format: uuid }
|
||||
description: UUID v4,发送结果未知时用同一 ID 和正文重试。
|
||||
CSRF:
|
||||
in: header
|
||||
name: X-CSRF-Token
|
||||
required: true
|
||||
schema: { type: string }
|
||||
responses:
|
||||
Failure:
|
||||
description: 400/401/403/409/413/415/429/500/503;SMS_CODE_INVALID、LOGIN_SESSION_EXPIRED、SMS_RATE_LIMITED、SMS_SEND_UNCERTAIN、SMS_UNAVAILABLE、CAPTCHA_INVALID、CAPTCHA_UNAVAILABLE、PASSWORD_INVALID、PASSWORD_POLICY、CURRENT_PASSWORD_INVALID、SMS_REAUTH_REQUIRED、RATE_LIMITED 等,不返回验证码或密码。
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: './onboarding.yaml#/components/schemas/Failure' }
|
||||
@@ -0,0 +1,86 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: Subject home overview
|
||||
version: 0.99.24
|
||||
paths:
|
||||
/api/v1/subjects/{id}/home-overview:
|
||||
get:
|
||||
operationId: subjectHomeOverview
|
||||
summary: Current calendar week and latest finished conversation
|
||||
description: >-
|
||||
Read-only, subject-scoped metadata independent of conversation-list pagination or filters.
|
||||
Week boundaries use the subject timezone, Monday inclusive to next Monday exclusive.
|
||||
Entire duration belongs to the session start date, including midnight/week crossings.
|
||||
Legacy sessions require started_at and ended_at; DIRECT sessions require ended_at and
|
||||
a valid finalized USER or ASSISTANT utterance. Interrupted sessions with this evidence count;
|
||||
preparation failures, active sessions, future end times, and deleted sources do not count.
|
||||
DIRECT duration is created_at to ended_at, because no reliable connected_at is stored.
|
||||
Latest conversation is independent of the week and never replaced with an older recap.
|
||||
Metadata requires household conversation-read access; recap additionally requires the
|
||||
independent memory grant, current storage consent, and applicable privacy fencing.
|
||||
Legacy unclassified summaries require sensitive access. DIRECT recap is an existing
|
||||
active normal memory from that exact session, not a newly synthesized full summary.
|
||||
security:
|
||||
- bearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema: {type: string, format: uuid}
|
||||
responses:
|
||||
'200':
|
||||
description: Home overview; no-store
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data: {$ref: '#/components/schemas/HomeOverview'}
|
||||
'400': {description: Invalid subject ID or unsupported query parameters}
|
||||
'401': {description: Authentication required}
|
||||
'403': {description: Subject metadata access denied}
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerAuth: {type: http, scheme: bearer}
|
||||
schemas:
|
||||
HomeOverview:
|
||||
type: object
|
||||
required: [subject_id, timezone, week_start, week_end, conversation_count, total_duration_ms, daily, latest_conversation]
|
||||
properties:
|
||||
subject_id: {type: string, format: uuid}
|
||||
timezone: {type: string, example: Asia/Shanghai}
|
||||
week_start: {type: string, format: date}
|
||||
week_end: {type: string, format: date, description: Exclusive next Monday}
|
||||
conversation_count: {type: integer, minimum: 0}
|
||||
total_duration_ms: {type: integer, format: int64, minimum: 0}
|
||||
daily:
|
||||
type: array
|
||||
minItems: 7
|
||||
maxItems: 7
|
||||
items:
|
||||
type: object
|
||||
required: [date, conversation_count, duration_ms]
|
||||
properties:
|
||||
date: {type: string, format: date}
|
||||
conversation_count: {type: integer, minimum: 0}
|
||||
duration_ms: {type: integer, format: int64, minimum: 0}
|
||||
latest_conversation:
|
||||
oneOf:
|
||||
- type: 'null'
|
||||
- $ref: '#/components/schemas/HomeConversation'
|
||||
HomeConversation:
|
||||
type: object
|
||||
required: [id, source, status, started_at, ended_at, duration_ms, summary_state]
|
||||
properties:
|
||||
id: {type: string, format: uuid}
|
||||
source: {type: string, enum: [conversation, call_memory]}
|
||||
status: {type: string, description: Original terminal status, including FAILED for an interrupted actual conversation}
|
||||
started_at: {type: string, format: date-time}
|
||||
ended_at: {type: string, format: date-time}
|
||||
duration_ms: {type: integer, format: int64, minimum: 0}
|
||||
summary: {type: string, description: Only present when authorized and READY}
|
||||
summary_kind: {type: string, enum: [conversation_summary, memory]}
|
||||
summary_state:
|
||||
type: string
|
||||
enum: [READY, PROCESSING, INSUFFICIENT_TRANSCRIPT, NO_SUMMARY, SYNC_FAILED, UNAVAILABLE]
|
||||
description: UNAVAILABLE covers access, storage consent, or privacy restrictions without revealing hidden content.
|
||||
@@ -0,0 +1,96 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: Login CAPTCHA policy
|
||||
version: 1.0.0
|
||||
paths:
|
||||
/api/v1/ops/login-captcha-policy:
|
||||
get:
|
||||
operationId: getLoginCaptchaPolicy
|
||||
summary: 平台管理员查看 SaaS 和小程序验证码方式与配置就绪状态
|
||||
description: 需要 operator 登录身份及 X-Tenant-ID 对应的 ops_admin 角色。配置为全平台设置,只返回模式、版本和凭据是否已加载,绝不返回密钥。
|
||||
parameters:
|
||||
- {in: header, name: X-Tenant-ID, required: true, schema: {type: string, format: uuid}}
|
||||
responses:
|
||||
'200':
|
||||
description: 验证码配置
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok: {type: boolean}
|
||||
data: {$ref: '#/components/schemas/Policy'}
|
||||
'403': {description: 非平台管理员}
|
||||
post:
|
||||
operationId: updateLoginCaptchaPolicy
|
||||
summary: 分端切换图形、拼图滑块或腾讯云验证码
|
||||
description: 需要 ops_admin、X-Tenant-ID、UUID v4 X-Request-ID;使用 Cookie 时另需同源 Origin 和有效 X-CSRF-Token。使用 version 乐观锁。新配置立即生效,旧挑战失效;凭据未配置不能启用腾讯云。不自动降级。
|
||||
parameters:
|
||||
- {in: header, name: X-Tenant-ID, required: true, schema: {type: string, format: uuid}}
|
||||
- {in: header, name: X-Request-ID, required: true, schema: {type: string, format: uuid}}
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [saas_mode, mini_mode, version]
|
||||
properties:
|
||||
saas_mode: {type: string, enum: [image, slide, tencent]}
|
||||
mini_mode: {type: string, enum: [image, tencent]}
|
||||
version: {type: integer, minimum: 1}
|
||||
responses:
|
||||
'200':
|
||||
description: 保存成功并记录审计
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok: {type: boolean}
|
||||
data: {$ref: '#/components/schemas/Policy'}
|
||||
'403': {description: 非平台管理员或 CSRF 校验失败}
|
||||
'409': {description: 版本冲突或腾讯云配置未就绪}
|
||||
components:
|
||||
schemas:
|
||||
Policy:
|
||||
type: object
|
||||
required: [saas_mode, mini_mode, version, saas_configured, mini_configured]
|
||||
properties:
|
||||
saas_mode: {type: string, enum: [image, slide, tencent]}
|
||||
mini_mode: {type: string, enum: [image, tencent]}
|
||||
version: {type: integer}
|
||||
saas_configured: {type: boolean}
|
||||
mini_configured: {type: boolean}
|
||||
SlideCaptchaVerifyInput:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [captcha_id, x, y]
|
||||
description: 提交拼块左上角在原图 320×180 像素坐标系的位置;服务端核对位置及当前会话,误差最多 3 像素。一次错误即消费挑战。
|
||||
properties:
|
||||
captcha_id: {type: string, format: uuid}
|
||||
x: {type: integer, minimum: 0, maximum: 268}
|
||||
y: {type: integer, minimum: 0, maximum: 128}
|
||||
SlideCaptchaVerifyResponse:
|
||||
type: object
|
||||
required: [ok, data]
|
||||
properties:
|
||||
ok: {type: boolean, const: true}
|
||||
code: {type: string}
|
||||
request_id: {type: string, format: uuid}
|
||||
server_time_ms: {type: integer, format: int64}
|
||||
data:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [captcha_id, captcha_ticket, expires_at_ms]
|
||||
properties:
|
||||
captcha_id: {type: string, format: uuid}
|
||||
captcha_ticket:
|
||||
type: string
|
||||
pattern: '^[A-Za-z0-9_-]{43}$'
|
||||
description: 仅本地校验的一次凭证,绑定当前会话、客户端、挑战与策略版本;通过既有 captcha_id/captcha_ticket 提交密码登录或短信申请。
|
||||
expires_at_ms:
|
||||
type: integer
|
||||
format: int64
|
||||
description: 原挑战的 2 分钟截止时间,验证成功不会延长有效期。
|
||||
@@ -0,0 +1,207 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: 小程序原生登录与自动蓝牙连接
|
||||
version: 2.0.1
|
||||
description: HTTPS;POST 必须携带 UUID v4 X-Request-ID。响应使用 ok/code/request_id/server_time_ms/data 信封。不发 Cookie,不使用 AppSecret 或云开发。现有网页 Origin/CSRF 规则不变。
|
||||
paths:
|
||||
/api/v1/mini/login/session:
|
||||
post:
|
||||
summary: 创建20分钟原生登录会话
|
||||
security: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [portal]
|
||||
properties:
|
||||
portal: {type: string, enum: [customer, operator]}
|
||||
responses:
|
||||
'200': {description: 'data: {login_token: realm.opaque, expires_in: 1200, sms_enabled: boolean}'}
|
||||
default: {description: 参数错误、限流或服务异常}
|
||||
/api/v1/mini/login/captcha:
|
||||
post:
|
||||
summary: 获取图形验证码
|
||||
security: [{MiniLogin: []}]
|
||||
requestBody: {$ref: '#/components/requestBodies/Empty'}
|
||||
responses:
|
||||
'200': {description: 'data: {captcha_id, image: PNG data URL, expires_at_ms}'}
|
||||
default: {description: 登录会话失效或限流}
|
||||
/api/v1/mini/login/password:
|
||||
post:
|
||||
summary: 使用已有手机号密码登录,不自动注册或提升权限
|
||||
description: 设备未通过短信验证或验证已过期时返回 403 NEW_DEVICE_SMS_REQUIRED。先完成 LOGIN 短信验证,再将返回的 trusted_device_token 按服务地址、账号和 portal 保存在客户端,后续密码登录携带。设备验证最长 30 天,不代替密码或人机验证。
|
||||
security: [{MiniLogin: []}]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [phone_e164, password, captcha_id]
|
||||
anyOf:
|
||||
- required: [captcha_code]
|
||||
- required: [captcha_ticket]
|
||||
properties:
|
||||
phone_e164: {type: string}
|
||||
password: {type: string, maxLength: 256}
|
||||
trusted_device_token: {type: string, maxLength: 43, writeOnly: true}
|
||||
captcha_id: {type: string, format: uuid}
|
||||
captcha_code: {type: string, pattern: '^[0-9]{6}$'}
|
||||
captcha_ticket: {type: string, maxLength: 4096, writeOnly: true}
|
||||
responses:
|
||||
'200': {description: 'data: {access_token: realm.opaque, portal: customer|operator, expires_in: 86400};会话只能成功消费一次'}
|
||||
default: {description: 验证码或密码错误、账号不可用或限流}
|
||||
/api/v1/mini/login/sms/send:
|
||||
post:
|
||||
summary: 小程序发送手机号登录验证码
|
||||
description: 与 SaaS 网页、设备绑定入口共用腾讯云短信通道、手机号发送限额和 6 位验证码规则;需先调用 login/captcha。不会返回验证码。
|
||||
security: [{MiniLogin: []}]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: './onboarding.yaml#/components/schemas/SMSSendInput'}
|
||||
responses:
|
||||
'200': {description: 'data: {sms_challenge_id, expires_at_ms, resend_after_ms}'}
|
||||
default: {description: 图片验证码错误、发送失败、登录会话失效或限流}
|
||||
/api/v1/mini/login/sms/verify:
|
||||
post:
|
||||
summary: 小程序验证短信并获得原生登录令牌
|
||||
description: 客户可按唯一自注册租户配置创建普通账号;管理账号必须预先绑定手机号。挑战与小程序登录会话绑定,成功后一次性消费,不发 Cookie。成功响应另含 trusted_device_token 和 trusted_device_expires_in(2592000 秒),供此设备后续密码登录使用。
|
||||
security: [{MiniLogin: []}]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: './onboarding.yaml#/components/schemas/SMSVerifyInput'}
|
||||
responses:
|
||||
'200': {description: 'data: {access_token: realm.opaque, portal: customer|operator, expires_in: 86400}'}
|
||||
default: {description: 验证码错误、过期、账户不可用或登录会话失效}
|
||||
/api/v1/mini/account:
|
||||
get:
|
||||
summary: 校验原生登录状态
|
||||
security: [{Mini: []}]
|
||||
responses:
|
||||
'200': {description: 'data: {authenticated: true, portal, display_name}'}
|
||||
default: {description: 登录已过期、撤销或账号被停用}
|
||||
/api/v1/mini/logout:
|
||||
post:
|
||||
summary: 撤销当前原生会话
|
||||
security: [{Mini: []}]
|
||||
requestBody: {$ref: '#/components/requestBodies/Empty'}
|
||||
responses:
|
||||
'200': {description: 'data: {signed_out: true}'}
|
||||
default: {description: 登录失效或服务异常}
|
||||
/api/v1/mini/ble-session:
|
||||
post:
|
||||
deprecated: true
|
||||
summary: 自动建立设备加密连接,无需手动输入设备编号或配网密码
|
||||
security: [{Mini: []}]
|
||||
description: 仅允许有设备租户内家庭管理权限的家庭账号和未绑定设备。验证设备随机连接证明,返回本次连接专用 SRP 密码;绝不返回工厂密钥或标签配网密码。
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [device_id, model, key_version, client_nonce, server_nonce, proof]
|
||||
properties:
|
||||
device_id: {type: string, pattern: '^KP01-[0-9A-F]{12}$'}
|
||||
model: {type: string}
|
||||
key_version: {type: integer, minimum: 1}
|
||||
client_nonce: {type: string, pattern: '^[A-Za-z0-9_-]{22}$'}
|
||||
server_nonce: {type: string, pattern: '^[A-Za-z0-9_-]{22}$'}
|
||||
proof: {type: string, pattern: '^[a-f0-9]{64}$'}
|
||||
responses:
|
||||
'200': {description: 'data: {device_id, model, session_password: 64字符小写十六进制};只在当前蓝牙连接内有效'}
|
||||
default: {description: 设备或家庭权限不满足、重放证明或绑定暂停}
|
||||
/api/v1/mini/ble-device-state:
|
||||
post:
|
||||
summary: 查询设备账号归属及管理权限;未添加的设备不要求家庭或老人(明文BLE v2)
|
||||
description: 按实际失败条件返回独立 code 和中文 message,不再合并为 DEVICE_UNAVAILABLE。错误信封含 ok=false、code、message、request_id;不包含其他账号身份或老人资料。详见 docs/device-ble-errors-20260918.md。
|
||||
security: [{Mini: []}]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [device_id]
|
||||
properties:
|
||||
device_id: {type: string, pattern: '^KP01-[0-9A-F]{12}$'}
|
||||
responses:
|
||||
'200': {description: 'data: {device_id, id: 平台设备UUID, model, bound: boolean};bound表示已有账号或老人归属,true时只更新Wi-Fi,不申请bind_token'}
|
||||
'400': {description: 'DEVICE_ID_INVALID:设备编号格式错误'}
|
||||
'403': {description: 'ACCOUNT_NOT_FOUND / ACCOUNT_DISABLED / ACCOUNT_DELETED / CUSTOMER_REQUIRED / DEVICE_TENANT_MISMATCH / TENANT_INACTIVE / DEVICE_REVOKED / DEVICE_LOST / DEVICE_QUARANTINED / DEVICE_OWNED_BY_OTHER_ACCOUNT / DEVICE_MANAGE_PERMISSION_REQUIRED;message 提供具体原因及处理方式'}
|
||||
'404': {description: 'DEVICE_NOT_REGISTERED:平台没有该设备的注册记录'}
|
||||
'409': {description: 'DEVICE_NOT_RELEASED:尚未出厂放行;DEVICE_ENROLLMENT_UNSUPPORTED:尚未启用蓝牙实体确认绑定;DEVICE_BINDING_STALE:归属记录与当前设备状态不一致'}
|
||||
default: {description: 参数错误、登录失效、限流或服务异常}
|
||||
/api/v1/device/ble-state:
|
||||
post:
|
||||
summary: 设备用工厂HMAC查询自身是否已绑定,只读,不改变归属
|
||||
security: [{DeviceHMAC: []}]
|
||||
requestBody: {$ref: '#/components/requestBodies/Empty'}
|
||||
responses:
|
||||
'200': {description: 'data: {bound: boolean};设备仅在true时保存空bind_token任务的新Wi-Fi'}
|
||||
default: {description: 工厂鉴权失败、设备不可用、限流或服务异常}
|
||||
/api/v1/mini/ble-bind-tokens:
|
||||
post:
|
||||
summary: 为当前客户账号签发5分钟设备绑定令牌,无需先创建家庭或老人
|
||||
description: 设备和账号校验使用与 ble-device-state 相同的具体错误码及提示。另有 ELDER_ID_INVALID(400,显式老人编号格式错误)及 ALREADY_BOUND(409,已有归属,无需重复添加)。
|
||||
security: [{Mini: []}]
|
||||
requestBody:
|
||||
$ref: './ble-binding.yaml#/paths/~1api~1v1~1web~1ble-bind-tokens/post/requestBody'
|
||||
responses:
|
||||
'200': {description: 'data: {bind_token};设备已有归属或使用者无管理权限时拒绝'}
|
||||
default: {description: 请求无效、登录失效、权限不足或限流}
|
||||
/api/v1/mini/ble-bind-status:
|
||||
post:
|
||||
summary: 查询当前账号签发的绑定令牌结果
|
||||
security: [{Mini: []}]
|
||||
requestBody: {$ref: './ble-binding.yaml#/components/requestBodies/Token'}
|
||||
responses:
|
||||
'200': {description: 'data: {status: pending|success|failed, message?};蓝牙断开后仍可查询'}
|
||||
default: {description: 请求无效、登录失效或令牌不可访问}
|
||||
/api/v1/mini/device-subject:
|
||||
post:
|
||||
summary: 将已添加到当前账号的设备绑定给有管理权限的老人
|
||||
security: [{Mini: []}]
|
||||
parameters:
|
||||
- in: header
|
||||
name: X-Request-ID
|
||||
required: true
|
||||
schema: {type: string, format: uuid}
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [device_id, elder_id, expected_account_binding_id]
|
||||
properties:
|
||||
device_id: {type: string, format: uuid, description: 设备列表中的平台UUID,不是工厂编号}
|
||||
elder_id: {type: string, format: uuid}
|
||||
expected_account_binding_id: {type: string, format: uuid, description: 设备列表返回的account_binding_id}
|
||||
responses:
|
||||
'200': {description: 'data: {status: success, device_id, elder_id};同一有效归属和同一老人可安全重试,不重复注册火山'}
|
||||
'403': {description: 非设备归属账号、无老人管理权限、跨组织或归属已失效}
|
||||
'409': {description: 设备有待确认操作或升级}
|
||||
default: {description: 参数错误、登录失效、限流或服务异常}
|
||||
components:
|
||||
securitySchemes:
|
||||
DeviceHMAC: {type: apiKey, in: header, name: Authorization, description: 'Device-HMAC-SHA256 hex;还需X-Device-ID、X-Key-Version、X-Timestamp-Ms、X-Nonce、X-Request-ID,详见docs/device-mini-ble-v2.md'}
|
||||
Mini: {type: apiKey, in: header, name: Authorization, description: 'Mini 后接 customer.或operator.开头的原生access_token。业务接口仍按原资源白名单和服务器权限验证。'}
|
||||
MiniLogin: {type: apiKey, in: header, name: Authorization, description: 'MiniLogin 后接 login_token,仅允许验证码和密码登录接口。'}
|
||||
requestBodies:
|
||||
Empty:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {type: object, additionalProperties: false}
|
||||
+117
-6
@@ -700,13 +700,15 @@ paths:
|
||||
/api/v1/web/setup/auth-link:
|
||||
post:
|
||||
operationId: onboardingOIDCPOSTapiv1websetupauthlink
|
||||
summary: 关联OIDC登录
|
||||
summary: 关联已登录账号
|
||||
tags:
|
||||
- Onboarding
|
||||
description: HTTPS,同源浏览器,Cookie不可读,CSRF仅保存在当前标签页。
|
||||
description: HTTPS,同源浏览器,必须提供设置会话 Cookie 和对应 CSRF;身份可来自 OIDC Bearer 或已登录账号 Cookie。
|
||||
security:
|
||||
- SetupCookie: []
|
||||
Bearer: []
|
||||
- SetupCookie: []
|
||||
AccountCookie: []
|
||||
parameters:
|
||||
- in: header
|
||||
name: X-Request-ID
|
||||
@@ -745,6 +747,70 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Empty'
|
||||
/api/v1/web/auth/captcha:
|
||||
post:
|
||||
operationId: onboardingSetupCaptcha
|
||||
summary: 获取或刷新设备绑定登录的图片验证码
|
||||
description: HTTPS、同源和 CSRF 校验;绑定当前设备设置会话,2 分钟有效,刷新和验证均使旧图失效。
|
||||
security: [{ SetupCookie: [] }]
|
||||
parameters:
|
||||
- { in: header, name: X-Request-ID, required: true, schema: { type: string, format: uuid } }
|
||||
- { in: header, name: X-CSRF-Token, required: true, schema: { type: string } }
|
||||
- { in: header, name: Origin, required: true, schema: { type: string } }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { type: object, additionalProperties: false }
|
||||
responses:
|
||||
'200':
|
||||
description: PNG 图片、captcha_id 和 expires_at_ms,不返回答案
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [ok, data]
|
||||
properties:
|
||||
ok: { type: boolean }
|
||||
data:
|
||||
type: object
|
||||
required: [captcha_id, mode, expires_at_ms]
|
||||
properties:
|
||||
captcha_id: { type: string, format: uuid }
|
||||
mode: { type: string, enum: [image, tencent, slide] }
|
||||
captcha_app_id: { type: string, description: 腾讯云 Web 验证码公开 ID }
|
||||
image: { type: string }
|
||||
thumb_image: { type: string, pattern: '^data:image/png;base64,' }
|
||||
image_width: { type: integer, minimum: 1 }
|
||||
image_height: { type: integer, minimum: 1 }
|
||||
thumb_width: { type: integer, minimum: 1 }
|
||||
thumb_height: { type: integer, minimum: 1 }
|
||||
thumb_x: { type: integer, minimum: 0, description: 拼图块的初始展示横坐标 }
|
||||
thumb_y: { type: integer, minimum: 0, description: 拼图块所在水平轨道 }
|
||||
expires_at_ms: { type: integer, format: int64 }
|
||||
default: { description: 校验失败或会话过期 }
|
||||
/api/v1/web/auth/captcha/verify:
|
||||
post:
|
||||
operationId: onboardingVerifyLocalSlideCaptcha
|
||||
summary: 校验设备设置会话的本地滑块位置
|
||||
description: HTTPS、同源、CSRF 和设备设置会话校验;每次提交即消费挑战。成功票据只对当前设置会话、客户端和策略版本有效,不能超过原 2 分钟期限。
|
||||
security: [{ SetupCookie: [] }]
|
||||
parameters:
|
||||
- { in: header, name: X-Request-ID, required: true, schema: { type: string, format: uuid } }
|
||||
- { in: header, name: X-CSRF-Token, required: true, schema: { type: string } }
|
||||
- { in: header, name: Origin, required: true, schema: { type: string } }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: './login-captcha.yaml#/components/schemas/SlideCaptchaVerifyInput' }
|
||||
responses:
|
||||
'200':
|
||||
description: 一次性位置校验票据
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: './login-captcha.yaml#/components/schemas/SlideCaptchaVerifyResponse' }
|
||||
default: { description: 校验失败或会话过期 }
|
||||
/api/v1/web/auth/sms/send:
|
||||
post:
|
||||
operationId: onboardingPOSTapiv1webauthsmssend
|
||||
@@ -1266,7 +1332,7 @@ paths:
|
||||
$ref: '#/components/schemas/Failure'
|
||||
post:
|
||||
operationId: onboardingPOSTapiv1opsdeviceinventory
|
||||
summary: 登记生产设备
|
||||
summary: 创建设备并直接进入等待绑定
|
||||
tags:
|
||||
- Onboarding
|
||||
description: 必须使用运维OIDC身份。对账仅ops_admin;其它写操作ops_admin或ops_operator。
|
||||
@@ -1888,12 +1954,35 @@ components:
|
||||
pattern: ^\+[1-9][0-9]{7,14}$
|
||||
purpose:
|
||||
type: string
|
||||
description: 固定LOGIN
|
||||
description: LOGIN 由服务端按手机号是否已有凭据选择注册或登录模板;CHANGE_PASSWORD 用于现有的短信登录后重置密码流程。更换手机号不可使用本接口。
|
||||
enum:
|
||||
- LOGIN
|
||||
- CHANGE_PASSWORD
|
||||
captcha_id:
|
||||
type: string
|
||||
format: uuid
|
||||
description: 当前登录或设备设置会话的人机验证挑战 ID
|
||||
captcha_code:
|
||||
type: string
|
||||
pattern: '^[0-9]{6}$'
|
||||
description: 图片中的 6 位数字;每次新的发送都须使用未消费的图片验证码
|
||||
captcha_ticket:
|
||||
type: string
|
||||
maxLength: 4096
|
||||
writeOnly: true
|
||||
description: 腾讯云模式使用对应端 SDK/插件票据;本地滑块模式使用 captcha/verify 返回的票据。绑定当前会话并一次性消费。
|
||||
captcha_randstr:
|
||||
type: string
|
||||
maxLength: 256
|
||||
writeOnly: true
|
||||
description: 腾讯云 Web 模式必填;微信小程序插件不需要
|
||||
anyOf:
|
||||
- required: [captcha_code]
|
||||
- required: [captcha_ticket]
|
||||
required:
|
||||
- phone_e164
|
||||
- purpose
|
||||
- captcha_id
|
||||
SMSVerifyInput:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
@@ -1972,6 +2061,21 @@ components:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
initial_consents:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [types, confirmed]
|
||||
properties:
|
||||
types:
|
||||
type: array
|
||||
maxItems: 5
|
||||
uniqueItems: true
|
||||
items:
|
||||
type: string
|
||||
enum: [transcript_storage, raw_audio_storage, story_extraction, personalized_memory, family_sharing]
|
||||
confirmed:
|
||||
type: boolean
|
||||
description: 用户明确确认所选授权;不选任何项目时仍可创建资料
|
||||
household_id:
|
||||
type: string
|
||||
description: 家庭公开UUID;省略时须提供新家庭名称
|
||||
@@ -2099,9 +2203,12 @@ components:
|
||||
device_name:
|
||||
type: string
|
||||
description: 冻结的物理设备名
|
||||
product_secret:
|
||||
device_secret:
|
||||
type: string
|
||||
description: 供应商产品注册密钥,只在设备认证后的HTTPS激活配置中下发
|
||||
description: 平台代注册取得的本设备火山密钥;不再下发product_secret
|
||||
RTCAppID:
|
||||
type: string
|
||||
description: 平台代注册取得的RTC应用ID
|
||||
bot_id:
|
||||
type: string
|
||||
description: 智能体ID
|
||||
@@ -2176,6 +2283,10 @@ components:
|
||||
description: 状态版本
|
||||
released:
|
||||
type: boolean
|
||||
description: 设备已完成内部初始化,可以开始绑定
|
||||
bound:
|
||||
type: boolean
|
||||
description: 当前是否存在有效绑定
|
||||
activation_id:
|
||||
type: string
|
||||
description: 激活任务UUID
|
||||
|
||||
+279
-25
@@ -1,12 +1,102 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: 数据采集终端—云端系统 API
|
||||
version: 0.78.0
|
||||
version: 0.79.0
|
||||
description: 工程框架、SaaS核心业务、设备v2 RTC/VoiceChat兼容链路、设备v3火山硬件对话智能体控制面、每次会话人设与授权记忆冻结、SDK和音频能力门禁、动态配置生效证明、可靠设备事件和终稿补传、通话中受控记忆工具、首次通话就绪与最低固件门禁、背景资料准备失败闭环、活动通话授权撤回安全停止、语音内容闭环、批量设备遥测、录音上传队列、隐私对账、固件、双轨录音、状态事件、具体资源分享、受控运营配置、Agent组合组件引用、质量证据门禁、运营自定义版本族投放、新通话运行时冻结与供应商启动传递、带并发版本校验的配置投放暂停恢复、带严重度和验收证据门禁的联调问题闭环、含阻断告警定位、当前主机健康及生产部署标记、实际应用环境、身份服务模式、异地备份、外部告警与模拟服务强制条件的发布候选技术验收快照、绑定候选版本与构建摘要并按业务时区生成的可审计试点日/周运行证据、可审计且不生成正式告警的接收器联通测试、外部依赖预检台账、证书到期清单,以及带价格版本冻结、供应商用量去重和硬额度控制的费用治理接口。
|
||||
servers:
|
||||
- url: http://localhost:58080
|
||||
description: 本地开发
|
||||
paths:
|
||||
/api/v1/ops/login-captcha-policy:
|
||||
$ref: './login-captcha.yaml#/paths/~1api~1v1~1ops~1login-captcha-policy'
|
||||
/api/v1/mini/login/session:
|
||||
$ref: './mini.yaml#/paths/~1api~1v1~1mini~1login~1session'
|
||||
/api/v1/mini/login/captcha:
|
||||
$ref: './mini.yaml#/paths/~1api~1v1~1mini~1login~1captcha'
|
||||
/api/v1/mini/login/password:
|
||||
$ref: './mini.yaml#/paths/~1api~1v1~1mini~1login~1password'
|
||||
/api/v1/mini/login/sms/send:
|
||||
$ref: './mini.yaml#/paths/~1api~1v1~1mini~1login~1sms~1send'
|
||||
/api/v1/mini/login/sms/verify:
|
||||
$ref: './mini.yaml#/paths/~1api~1v1~1mini~1login~1sms~1verify'
|
||||
/api/v1/mini/account:
|
||||
$ref: './mini.yaml#/paths/~1api~1v1~1mini~1account'
|
||||
/api/v1/mini/logout:
|
||||
$ref: './mini.yaml#/paths/~1api~1v1~1mini~1logout'
|
||||
/api/v1/mini/ble-session:
|
||||
$ref: './mini.yaml#/paths/~1api~1v1~1mini~1ble-session'
|
||||
/api/v1/mini/ble-bind-tokens:
|
||||
$ref: './mini.yaml#/paths/~1api~1v1~1mini~1ble-bind-tokens'
|
||||
/api/v1/mini/ble-bind-status:
|
||||
$ref: './mini.yaml#/paths/~1api~1v1~1mini~1ble-bind-status'
|
||||
/api/v1/web/ble-bind-tokens:
|
||||
$ref: './ble-binding.yaml#/paths/~1api~1v1~1web~1ble-bind-tokens'
|
||||
/api/v1/web/ble-bind-status:
|
||||
$ref: './ble-binding.yaml#/paths/~1api~1v1~1web~1ble-bind-status'
|
||||
/api/v1/device/ble-bind:
|
||||
$ref: './ble-binding.yaml#/paths/~1api~1v1~1device~1ble-bind'
|
||||
/api/v1/web/operator/login/session:
|
||||
$ref: './operator-login.yaml#/paths/~1api~1v1~1web~1operator~1login~1session'
|
||||
/api/v1/web/operator/login/captcha:
|
||||
$ref: './operator-login.yaml#/paths/~1api~1v1~1web~1operator~1login~1captcha'
|
||||
/api/v1/web/operator/login/captcha/verify:
|
||||
$ref: './operator-login.yaml#/paths/~1api~1v1~1web~1operator~1login~1captcha~1verify'
|
||||
/api/v1/web/operator/login/password:
|
||||
$ref: './operator-login.yaml#/paths/~1api~1v1~1web~1operator~1login~1password'
|
||||
/api/v1/web/operator/login/sms/send:
|
||||
$ref: './operator-login.yaml#/paths/~1api~1v1~1web~1operator~1login~1sms~1send'
|
||||
/api/v1/web/operator/login/sms/verify:
|
||||
$ref: './operator-login.yaml#/paths/~1api~1v1~1web~1operator~1login~1sms~1verify'
|
||||
/api/v1/web/operator/account/session:
|
||||
$ref: './operator-login.yaml#/paths/~1api~1v1~1web~1operator~1account~1session'
|
||||
/api/v1/web/operator/account/password:
|
||||
$ref: './operator-login.yaml#/paths/~1api~1v1~1web~1operator~1account~1password'
|
||||
/api/v1/web/operator/auth/logout:
|
||||
$ref: './operator-login.yaml#/paths/~1api~1v1~1web~1operator~1auth~1logout'
|
||||
/api/v1/web/login/session:
|
||||
$ref: './customer-login.yaml#/paths/~1api~1v1~1web~1login~1session'
|
||||
/api/v1/web/login/captcha:
|
||||
$ref: './customer-login.yaml#/paths/~1api~1v1~1web~1login~1captcha'
|
||||
/api/v1/web/login/captcha/verify:
|
||||
$ref: './customer-login.yaml#/paths/~1api~1v1~1web~1login~1captcha~1verify'
|
||||
/api/v1/web/login/password:
|
||||
$ref: './customer-login.yaml#/paths/~1api~1v1~1web~1login~1password'
|
||||
/api/v1/web/account/password:
|
||||
$ref: './customer-login.yaml#/paths/~1api~1v1~1web~1account~1password'
|
||||
/api/v1/web/login/sms/send:
|
||||
$ref: './customer-login.yaml#/paths/~1api~1v1~1web~1login~1sms~1send'
|
||||
/api/v1/web/login/sms/verify:
|
||||
$ref: './customer-login.yaml#/paths/~1api~1v1~1web~1login~1sms~1verify'
|
||||
/api/v1/device/calls/command-acks:
|
||||
$ref: './call-memory.yaml#/paths/~1api~1v1~1device~1calls~1command-acks'
|
||||
/api/v1/device/calls/end:
|
||||
$ref: './call-memory.yaml#/paths/~1api~1v1~1device~1calls~1end'
|
||||
/api/v1/device/calls/events:
|
||||
$ref: './call-memory.yaml#/paths/~1api~1v1~1device~1calls~1events'
|
||||
/api/v1/device/calls/heartbeat:
|
||||
$ref: './call-memory.yaml#/paths/~1api~1v1~1device~1calls~1heartbeat'
|
||||
/api/v1/device/calls/prepare:
|
||||
$ref: './call-memory.yaml#/paths/~1api~1v1~1device~1calls~1prepare'
|
||||
/api/v1/device/calls/status:
|
||||
$ref: './call-memory.yaml#/paths/~1api~1v1~1device~1calls~1status'
|
||||
/api/v1/device/calls/warmup:
|
||||
$ref: './call-memory.yaml#/paths/~1api~1v1~1device~1calls~1warmup'
|
||||
/api/v1/memories/access/grant:
|
||||
$ref: './call-memory.yaml#/paths/~1api~1v1~1memories~1access~1grant'
|
||||
/api/v1/memories/access/query:
|
||||
$ref: './call-memory.yaml#/paths/~1api~1v1~1memories~1access~1query'
|
||||
/api/v1/memories/mutations:
|
||||
$ref: './call-memory.yaml#/paths/~1api~1v1~1memories~1mutations'
|
||||
/api/v1/memories/mutations/confirm:
|
||||
$ref: './call-memory.yaml#/paths/~1api~1v1~1memories~1mutations~1confirm'
|
||||
/api/v1/memories/mutations/resolve:
|
||||
$ref: './call-memory.yaml#/paths/~1api~1v1~1memories~1mutations~1resolve'
|
||||
/api/v1/memories/mutations/status:
|
||||
$ref: './call-memory.yaml#/paths/~1api~1v1~1memories~1mutations~1status'
|
||||
/api/v1/memories/query:
|
||||
$ref: './call-memory.yaml#/paths/~1api~1v1~1memories~1query'
|
||||
/api/v1/memories/sync/status:
|
||||
$ref: './call-memory.yaml#/paths/~1api~1v1~1memories~1sync~1status'
|
||||
/api/v1/device/time-challenges:
|
||||
$ref: './onboarding.yaml#/paths/~1api~1v1~1device~1time-challenges'
|
||||
/api/v1/device/register:
|
||||
@@ -35,6 +125,10 @@ paths:
|
||||
$ref: './onboarding.yaml#/paths/~1api~1v1~1web~1setup~1session'
|
||||
/api/v1/web/setup/auth-link:
|
||||
$ref: './onboarding.yaml#/paths/~1api~1v1~1web~1setup~1auth-link'
|
||||
/api/v1/web/auth/captcha:
|
||||
$ref: './onboarding.yaml#/paths/~1api~1v1~1web~1auth~1captcha'
|
||||
/api/v1/web/auth/captcha/verify:
|
||||
$ref: './onboarding.yaml#/paths/~1api~1v1~1web~1auth~1captcha~1verify'
|
||||
/api/v1/web/auth/sms/send:
|
||||
$ref: './onboarding.yaml#/paths/~1api~1v1~1web~1auth~1sms~1send'
|
||||
/api/v1/web/auth/sms/verify:
|
||||
@@ -1089,6 +1183,77 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
/api/v1/me/profile:
|
||||
patch:
|
||||
operationId: updateCurrentUserDisplayName
|
||||
tags: [identity]
|
||||
summary: 更新当前登录身份的昵称
|
||||
description: 仅更新已认证身份的有效账号;不接受账号 ID。Cookie 登录写入仍需 CSRF token。
|
||||
security: [{ oidcBearer: [] }]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [display_name]
|
||||
properties:
|
||||
display_name: { type: string, minLength: 1, maxLength: 80 }
|
||||
responses:
|
||||
'200':
|
||||
description: 昵称已保存,响应不缓存
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok: { type: boolean }
|
||||
data:
|
||||
type: object
|
||||
required: [display_name]
|
||||
properties:
|
||||
display_name: { type: string }
|
||||
'400': { description: 昵称无效或请求包含未知字段 }
|
||||
'401': { $ref: '#/components/responses/AuthenticationError' }
|
||||
'403': { description: 当前身份没有有效账号 }
|
||||
/api/v1/events/history:
|
||||
get:
|
||||
operationId: listFamilyActivityHistory
|
||||
tags: [identity]
|
||||
summary: 最近七天的家庭动态
|
||||
description: 返回仍有有效成员关系的家庭的事件元数据,按事件 ID 倒序,最多 200 条;不含聊天内容;响应不缓存。旧版已过期的事件不回填。
|
||||
security: [{ oidcBearer: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: 家庭动态列表
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok: { type: boolean }
|
||||
data:
|
||||
type: object
|
||||
required: [items, limit, retention_days]
|
||||
properties:
|
||||
limit: { type: integer, enum: [200] }
|
||||
retention_days: { type: integer, enum: [7] }
|
||||
items:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [id, type, household_id, resource_type, resource_id, status, occurred_at]
|
||||
properties:
|
||||
id: { type: integer, format: int64 }
|
||||
type: { type: string }
|
||||
household_id: { type: string, format: uuid }
|
||||
subject_id: { type: string, format: uuid }
|
||||
resource_type: { type: string }
|
||||
resource_id: { type: string, format: uuid }
|
||||
status: { type: string }
|
||||
occurred_at: { type: string, format: date-time }
|
||||
'401': { $ref: '#/components/responses/AuthenticationError' }
|
||||
/api/v1/households:
|
||||
get:
|
||||
operationId: listHouseholds
|
||||
@@ -1341,6 +1506,7 @@ paths:
|
||||
'403': { $ref: '#/components/responses/AccessDeniedError' }
|
||||
post:
|
||||
operationId: createSubject
|
||||
description: 创建长者资料,创建流程逐项展示全部授权;仅为用户明确勾选并确认的项目记录授权。省略 initial_consents 或选择空列表时不开通数据授权,各项授权可独立撤回。
|
||||
tags: [subject]
|
||||
security: [{ oidcBearer: [] }]
|
||||
requestBody:
|
||||
@@ -1387,6 +1553,28 @@ paths:
|
||||
'403': { $ref: '#/components/responses/AccessDeniedError' }
|
||||
'412': { $ref: '#/components/responses/VersionConflictError' }
|
||||
'428': { $ref: '#/components/responses/PreconditionRequiredError' }
|
||||
/api/v1/subjects/{id}/voice-agent:
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/ResourceID'
|
||||
post:
|
||||
operationId: ensureSubjectVoiceAgent
|
||||
tags: [subject]
|
||||
description: 创建或恢复专属语音智能体;已就绪时重试同步最新档案。活动通话期间延后同步。资料同步失败保留 READY 创建状态,通过 persona_sync_status 返回。
|
||||
security: [{ oidcBearer: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: 当前创建状态与资料同步状态
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [request_id, data]
|
||||
properties:
|
||||
request_id: { type: string }
|
||||
data: { $ref: '#/components/schemas/SubjectVoiceAgent' }
|
||||
'401': { $ref: '#/components/responses/AuthenticationError' }
|
||||
'403': { $ref: '#/components/responses/AccessDeniedError' }
|
||||
'502': { description: 智能体创建或产品关联失败 }
|
||||
/api/v1/subjects/{id}/conversation-readiness:
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/ResourceID'
|
||||
@@ -1707,7 +1895,7 @@ paths:
|
||||
tags: [device-management]
|
||||
security: [{ oidcBearer: [] }]
|
||||
parameters: [{ $ref: '#/components/parameters/RequiredTenantSelectionHeader' }]
|
||||
description: 自动生成设备UUID和256位随机HMAC密钥;密钥明文仅在本响应出现一次。
|
||||
description: 直接创建可通过端到端蓝牙实体确认绑定的设备,并生成一次性烧录信息;设备密钥明文仅在本响应出现一次。
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/CreateOpsDeviceRequest' } } } }
|
||||
responses:
|
||||
'201': { description: 设备及一次性密钥, content: { application/json: { schema: { $ref: '#/components/schemas/CreateOpsDeviceResponse' } } } }
|
||||
@@ -2438,6 +2626,19 @@ paths:
|
||||
'403': { $ref: '#/components/responses/AccessDeniedError' }
|
||||
'412': { $ref: '#/components/responses/VersionConflictError' }
|
||||
'428': { $ref: '#/components/responses/PreconditionRequiredError' }
|
||||
/api/v1/households/{id}/privacy-requests:
|
||||
parameters: [{ $ref: '#/components/parameters/ResourceID' }]
|
||||
get:
|
||||
operationId: listHouseholdPrivacyRequests
|
||||
tags: [privacy]
|
||||
security: [{ oidcBearer: [] }]
|
||||
description: 需要有效家庭成员身份及 privacy.read 权限;包含正在删除及已删除长者的请求,便于持续查看处理终态。
|
||||
responses:
|
||||
'200':
|
||||
description: 返回当前家庭所有长者的隐私请求及处理结果,按创建时间倒序。
|
||||
content: { application/json: { schema: { $ref: '#/components/schemas/PrivacyRequestListResponse' } } }
|
||||
'401': { $ref: '#/components/responses/AuthenticationError' }
|
||||
'403': { $ref: '#/components/responses/AccessDeniedError' }
|
||||
/api/v1/subjects/{id}/privacy-requests:
|
||||
parameters: [{ $ref: '#/components/parameters/ResourceID' }]
|
||||
get:
|
||||
@@ -2446,7 +2647,7 @@ paths:
|
||||
security: [{ oidcBearer: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: 返回当前长者的隐私请求及处理结果。
|
||||
description: 返回当前长者的隐私请求及处理结果,包括正在删除或已删除的长者;仍需有效家庭成员身份及 privacy.read 权限。
|
||||
content: { application/json: { schema: { $ref: '#/components/schemas/PrivacyRequestListResponse' } } }
|
||||
'401': { $ref: '#/components/responses/AuthenticationError' }
|
||||
'403': { $ref: '#/components/responses/AccessDeniedError' }
|
||||
@@ -5131,6 +5332,19 @@ components:
|
||||
invitee_hint: { type: string, maxLength: 255 }
|
||||
role: { type: string, enum: [admin, editor, viewer] }
|
||||
expires_at: { type: string, format: date-time }
|
||||
SubjectVoiceAgent:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [status, personalization_included]
|
||||
properties:
|
||||
bot_id: { type: string }
|
||||
status: { type: string, enum: [PENDING, READY, FAILED] }
|
||||
message: { type: string }
|
||||
persona_sync_status: { type: string, enum: [PENDING, SYNCED, DEFERRED, FAILED] }
|
||||
persona_revision: { type: integer, format: int64, minimum: 1 }
|
||||
persona_synced_revision: { type: integer, format: int64, minimum: 0 }
|
||||
persona_synced_at: { type: string, format: date-time }
|
||||
personalization_included: { type: boolean, description: 已同步配置是否包含授权后的兴趣、背景、陪伴方向和优先话题。 }
|
||||
Subject:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
@@ -5144,6 +5358,7 @@ components:
|
||||
profile_data: { $ref: '#/components/schemas/SubjectProfileData' }
|
||||
conversation_preferences: { $ref: '#/components/schemas/SubjectConversationPreferences' }
|
||||
status: { type: string, enum: [active, suspended, deleting] }
|
||||
voice_agent: { $ref: '#/components/schemas/SubjectVoiceAgent' }
|
||||
version: { type: integer, format: int64, minimum: 1 }
|
||||
created_at: { type: string, format: date-time }
|
||||
updated_at: { type: string, format: date-time }
|
||||
@@ -5152,11 +5367,23 @@ components:
|
||||
additionalProperties: false
|
||||
required: [preferred_name, language, timezone, profile_data, conversation_preferences]
|
||||
properties:
|
||||
initial_consents: { $ref: '#/components/schemas/InitialConsentSelection' }
|
||||
preferred_name: { type: string, minLength: 1, maxLength: 120 }
|
||||
language: { type: string, minLength: 1, maxLength: 32, pattern: '^[A-Za-z0-9-]+$' }
|
||||
timezone: { type: string, minLength: 1, maxLength: 64 }
|
||||
profile_data: { $ref: '#/components/schemas/SubjectProfileData' }
|
||||
conversation_preferences: { $ref: '#/components/schemas/SubjectConversationPreferences' }
|
||||
InitialConsentSelection:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [types, confirmed]
|
||||
properties:
|
||||
types:
|
||||
type: array
|
||||
maxItems: 5
|
||||
uniqueItems: true
|
||||
items: { type: string, enum: [transcript_storage, raw_audio_storage, story_extraction, personalized_memory, family_sharing] }
|
||||
confirmed: { type: boolean, description: 有选中项目时必须为 true,表示用户已确认所选用途 }
|
||||
UpdateSubjectRequest:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
@@ -5311,10 +5538,11 @@ components:
|
||||
additionalProperties: false
|
||||
required: [id, binding_id, household_id, subject_id, subject_name, model, status, desired_revision, bound_at, registered_at, version]
|
||||
properties:
|
||||
account_binding_id: { type: string, format: uuid, description: 仅已添加到账号且待绑定老人的设备返回;绑定老人时用于归属版本校验。 }
|
||||
id: { type: string, format: uuid }
|
||||
binding_id: { type: string, format: uuid, description: 当前有效绑定编号;解绑或转移时用于并发校验。 }
|
||||
household_id: { type: string, format: uuid }
|
||||
subject_id: { type: string, format: uuid }
|
||||
household_id: { oneOf: [{ type: string, format: uuid }, { const: '' }], description: 待绑定老人时为空字符串。 }
|
||||
subject_id: { oneOf: [{ type: string, format: uuid }, { const: '' }], description: 待绑定老人时为空字符串。 }
|
||||
subject_name: { type: string }
|
||||
model: { type: string }
|
||||
hardware_revision: { type: string }
|
||||
@@ -5331,10 +5559,13 @@ components:
|
||||
OpsDevice:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [id, tenant_id, model, status, activation_state, activation_revision, activation_updated_at, credential_status, key_version, registered_at, updated_at, version, voice_runtime]
|
||||
required: [id, tenant_id, factory_id, enrollment_mode, bound, model, status, activation_state, activation_revision, activation_updated_at, credential_status, key_version, registered_at, updated_at, version, voice_runtime]
|
||||
properties:
|
||||
id: { type: string, format: uuid }
|
||||
tenant_id: { type: string, format: uuid }
|
||||
factory_id: { type: string, description: 烧录并用于设备认证的出厂设备编号;历史旧设备可能为空字符串。 }
|
||||
enrollment_mode: { type: string, enum: [legacy, physical_confirm] }
|
||||
bound: { type: boolean, description: 是否已有当前有效的家庭或账号归属。 }
|
||||
model: { type: string, minLength: 1, maxLength: 120 }
|
||||
hardware_revision: { type: string, maxLength: 80 }
|
||||
status: { type: string, enum: [registered, quarantined, revoked] }
|
||||
@@ -5375,13 +5606,6 @@ components:
|
||||
required: [model]
|
||||
properties:
|
||||
model: { type: string, minLength: 1, maxLength: 120 }
|
||||
hardware_revision: { type: string, maxLength: 80 }
|
||||
minimum_security_version: { type: string, maxLength: 80 }
|
||||
minimum_firmware_version: { type: string, maxLength: 80 }
|
||||
household_id: { type: string, format: uuid }
|
||||
subject_id: { type: string, format: uuid }
|
||||
voice_runtime: { type: string, enum: [legacy_voicechat, volc_hardware_agent] }
|
||||
activation_state: { type: string, enum: [FACTORY, CLAIMABLE, BOUND], description: 可选。未指定时,有归属为BOUND,无归属为CLAIMABLE;FACTORY仅允许未分配设备。 }
|
||||
UpdateOpsDeviceRequest:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
@@ -5434,12 +5658,13 @@ components:
|
||||
DeviceCredentialIssue:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [device_id, secret, key_version, issued_at]
|
||||
required: [factory_id, model, origin, device_key_hex, key_version]
|
||||
properties:
|
||||
device_id: { type: string, format: uuid }
|
||||
secret: { type: string, pattern: '^[0-9a-f]{64}$', description: 仅本响应返回一次。 }
|
||||
factory_id: { type: string, pattern: '^KP01-[0-9A-F]{12}$' }
|
||||
model: { type: string, minLength: 1, maxLength: 120 }
|
||||
origin: { type: string, format: uri }
|
||||
device_key_hex: { type: string, pattern: '^[0-9a-f]{64}$', description: 仅本响应返回一次。 }
|
||||
key_version: { type: integer, format: int64, minimum: 1 }
|
||||
issued_at: { type: string, format: date-time }
|
||||
DeviceClaimIssue:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
@@ -5472,7 +5697,7 @@ components:
|
||||
required: [request_id, data]
|
||||
properties:
|
||||
request_id: { type: string }
|
||||
data: { type: object, required: [device, credential], properties: { device: { $ref: '#/components/schemas/OpsDevice' }, credential: { $ref: '#/components/schemas/DeviceCredentialIssue' }, claim: { $ref: '#/components/schemas/DeviceClaimIssue' } } }
|
||||
data: { type: object, required: [device, credential], properties: { device: { $ref: '#/components/schemas/OpsDevice' }, credential: { $ref: '#/components/schemas/DeviceCredentialIssue' } } }
|
||||
DeviceCredentialIssueResponse:
|
||||
type: object
|
||||
required: [request_id, data]
|
||||
@@ -5493,8 +5718,8 @@ components:
|
||||
device_id: { type: string, format: uuid }
|
||||
binding_id: { type: string, format: uuid }
|
||||
action: { type: string, enum: [unbind, transfer] }
|
||||
source_household_id: { type: string, format: uuid }
|
||||
source_subject_id: { type: string, format: uuid }
|
||||
source_household_id: { oneOf: [{ type: string, format: uuid }, { const: '' }] }
|
||||
source_subject_id: { oneOf: [{ type: string, format: uuid }, { const: '' }] }
|
||||
source_subject_name: { type: string }
|
||||
target_household_id: { type: string, format: uuid }
|
||||
target_subject_id: { type: string, format: uuid }
|
||||
@@ -5503,9 +5728,10 @@ components:
|
||||
pending_command_count: { type: integer, minimum: 0 }
|
||||
active_firmware_task_count: { type: integer, minimum: 0 }
|
||||
allowed: { type: boolean }
|
||||
requires_physical_confirmation: { type: boolean, description: 转移需要经蓝牙提交并由设备实体确认,不能直接调用旧版转移接口。 }
|
||||
blockers:
|
||||
type: array
|
||||
items: { type: string, enum: [target_subject_required, active_conversation, pending_device_commands, active_firmware_task] }
|
||||
items: { type: string, enum: [target_subject_required, active_conversation, active_call, pending_device_commands, active_firmware_task, active_mqtt_ota] }
|
||||
evaluated_at: { type: string, format: date-time }
|
||||
ChangeDeviceBindingRequest:
|
||||
type: object
|
||||
@@ -5572,6 +5798,24 @@ components:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
power:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [mode]
|
||||
properties:
|
||||
mode:
|
||||
type: string
|
||||
enum: [active, standby]
|
||||
description: 远程唤醒或待机;仅设备已上报支持时可设置,设备空闲后执行。
|
||||
identity:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [display_name]
|
||||
properties:
|
||||
display_name:
|
||||
type: string
|
||||
maxLength: 96
|
||||
description: 设备名称,UTF-8编码最多96字节,不含首尾空白或控制字符;空字符串恢复默认名称。
|
||||
volume:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
@@ -6168,7 +6412,10 @@ components:
|
||||
additionalProperties: false
|
||||
required: [turn_id, sequence_no, speaker, text]
|
||||
properties:
|
||||
turn_id: { type: string, format: uuid }
|
||||
turn_id: { type: string, description: 原有话轮公开 ID 或设备会话内的原话标识 }
|
||||
call_session_id: { type: string, format: uuid }
|
||||
utterance_id: { type: string }
|
||||
source_revision: { type: integer, format: int64, minimum: 0 }
|
||||
sequence_no: { type: integer, format: int64, minimum: 1 }
|
||||
speaker: { type: string, enum: [subject, agent] }
|
||||
text: { type: string }
|
||||
@@ -6185,7 +6432,7 @@ components:
|
||||
statement_basis: { type: string, enum: [subject_statement, model_inference] }
|
||||
confidence: { type: number, minimum: 0, maximum: 1 }
|
||||
sensitivity: { type: string, enum: [normal, sensitive, high] }
|
||||
source_turn_ids: { type: array, minItems: 1, items: { type: string, format: uuid } }
|
||||
source_turn_ids: { type: array, minItems: 1, items: { type: string } }
|
||||
status: { type: string, enum: [CANDIDATE, CONFIRMED, REJECTED, SUPERSEDED] }
|
||||
version: { type: integer, format: int64, minimum: 1 }
|
||||
UpdateFactCandidateRequest:
|
||||
@@ -6203,11 +6450,15 @@ components:
|
||||
Story:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [id, subject_id, conversation_id, title, content, status, sensitivity, generation_version, revision_no, author_type, version, created_at, updated_at, sources, facts]
|
||||
required: [id, subject_id, title, content, status, sensitivity, generation_version, revision_no, author_type, version, created_at, updated_at, sources, facts]
|
||||
oneOf:
|
||||
- required: [conversation_id]
|
||||
- required: [call_session_id]
|
||||
properties:
|
||||
id: { type: string, format: uuid }
|
||||
subject_id: { type: string, format: uuid }
|
||||
conversation_id: { type: string, format: uuid }
|
||||
call_session_id: { type: string, format: uuid }
|
||||
title: { type: string, minLength: 1, maxLength: 300 }
|
||||
content: { type: string, minLength: 1, maxLength: 50000 }
|
||||
status: { $ref: '#/components/schemas/StoryStatus' }
|
||||
@@ -6404,7 +6655,10 @@ components:
|
||||
subject_id: { type: string, format: uuid }
|
||||
request_type: { type: string, enum: [ACCESS, CORRECTION, CONSENT_WITHDRAWAL, DELETE] }
|
||||
scope: { type: object, additionalProperties: true }
|
||||
status: { type: string, enum: [SUBMITTED, VERIFYING, EXECUTING, COMPLETED, PARTIAL_FAILED] }
|
||||
status:
|
||||
type: string
|
||||
enum: [SUBMITTED, VERIFYING, EXECUTING, COMPLETED, PARTIAL_FAILED]
|
||||
description: 非终态请求如有失败子任务,读取时返回 PARTIAL_FAILED;不会因此改写请求记录或触发重试。
|
||||
deadline_at: { type: string, format: date-time }
|
||||
legal_hold: { type: boolean }
|
||||
result_summary: { type: object, additionalProperties: true }
|
||||
|
||||
@@ -0,0 +1,310 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: 管理端手机号登录
|
||||
version: 1.1.0
|
||||
paths:
|
||||
/api/v1/web/operator/login/session:
|
||||
get:
|
||||
operationId: operatorLoginSession
|
||||
summary: 初始化手机号登录页面
|
||||
description: HTTPS,同源,不接受查询参数。签发 HttpOnly 登录 Cookie 和 CSRF token,20 分钟后过期,同一 Cookie 重载不会轮换 CSRF。短信不可用时仍可使用密码登录。
|
||||
security: []
|
||||
responses:
|
||||
'200':
|
||||
description: 页面状态;sms_enabled=false 不代表发送成功
|
||||
headers:
|
||||
Set-Cookie:
|
||||
schema: { type: string }
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [ok, data]
|
||||
properties:
|
||||
ok: { type: boolean }
|
||||
data:
|
||||
type: object
|
||||
required: [sms_enabled, password_enabled, csrf_token]
|
||||
properties:
|
||||
sms_enabled: { type: boolean }
|
||||
password_enabled: { type: boolean }
|
||||
signup_enabled: { type: boolean, const: false }
|
||||
csrf_token: { type: string }
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
/api/v1/web/operator/login/sms/send:
|
||||
post:
|
||||
operationId: operatorSendLoginSMS
|
||||
summary: 发送管理端登录验证码
|
||||
description: 6 位随机验证码,5 分钟有效;每个手机号至少间隔 60 秒、每小时最多 5 次,家庭端和设备绑定入口共用此限额。同一请求号重试不重复发送。手机号加密、验证码仅存 keyed hash;不在响应中返回验证码。
|
||||
security: [{ OperatorLoginCookie: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/RequestID' }
|
||||
- { $ref: '#/components/parameters/CSRF' }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: './onboarding.yaml#/components/schemas/SMSSendInput' }
|
||||
responses:
|
||||
'200':
|
||||
description: 网关已接受发送请求
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: './onboarding.yaml#/components/schemas/SMSResponse' }
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
/api/v1/web/operator/login/sms/verify:
|
||||
post:
|
||||
operationId: operatorVerifyLoginSMS
|
||||
summary: 验证验证码并创建管理端登录会话
|
||||
description: 验证码只能在发起发送的浏览器会话使用,最多尝试 5 次,成功后一次性消费。已有短信账号复用原身份;管理端不开放自助注册,必须预先绑定已有有效管理身份。账号 Cookie 24 小时有效,调用家庭写接口还需 CSRF;保留原管理角色,写操作仍按现有角色权限校验。读取 /api/v1/me 或事件流需附带 X-Login-Portal=operator。
|
||||
security: [{ OperatorLoginCookie: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/RequestID' }
|
||||
- { $ref: '#/components/parameters/CSRF' }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: './onboarding.yaml#/components/schemas/SMSVerifyInput' }
|
||||
responses:
|
||||
'200':
|
||||
description: 签发 HttpOnly 账号 Cookie,消费匿名登录会话;前端继续读取 /api/v1/me 校验业务账号
|
||||
headers:
|
||||
Set-Cookie:
|
||||
schema: { type: string }
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [ok, data]
|
||||
properties:
|
||||
ok: { type: boolean }
|
||||
data:
|
||||
type: object
|
||||
required: [csrf_token, data]
|
||||
properties:
|
||||
csrf_token: { type: string }
|
||||
data:
|
||||
type: object
|
||||
required: [authenticated]
|
||||
properties:
|
||||
authenticated: { type: boolean }
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
/api/v1/web/operator/login/captcha:
|
||||
post:
|
||||
operationId: operatorLoginCaptcha
|
||||
summary: 获取或更换密码登录、发送短信前的图片验证码
|
||||
description: 返回 PNG 图片和随机 ID,不返回答案。绑定登录 Cookie,2 分钟有效;刷新使旧图失效;每次校验均消费验证码。校验状态保存在 Redis,依赖不可用时拒绝登录。
|
||||
security: [{ OperatorLoginCookie: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/RequestID' }
|
||||
- { $ref: '#/components/parameters/CSRF' }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { type: object, additionalProperties: false }
|
||||
responses:
|
||||
'200':
|
||||
description: 图片验证码
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [ok, data]
|
||||
properties:
|
||||
ok: { type: boolean }
|
||||
data:
|
||||
type: object
|
||||
required: [captcha_id, mode, expires_at_ms]
|
||||
properties:
|
||||
captcha_id: { type: string, format: uuid }
|
||||
mode: { type: string, enum: [image, tencent, slide] }
|
||||
captcha_app_id: { type: string, description: 腾讯云模式对应客户端的公开 CaptchaAppId,不含密钥 }
|
||||
image: { type: string, pattern: '^data:image/(png|jpeg);base64,' }
|
||||
thumb_image: { type: string, pattern: '^data:image/png;base64,' }
|
||||
image_width: { type: integer, minimum: 1 }
|
||||
image_height: { type: integer, minimum: 1 }
|
||||
thumb_width: { type: integer, minimum: 1 }
|
||||
thumb_height: { type: integer, minimum: 1 }
|
||||
thumb_x: { type: integer, minimum: 0, description: 拼图块的初始展示横坐标 }
|
||||
thumb_y: { type: integer, minimum: 0, description: 拼图块所在水平轨道 }
|
||||
expires_at_ms: { type: integer, format: int64 }
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
/api/v1/web/operator/login/captcha/verify:
|
||||
post:
|
||||
operationId: operatorVerifyLocalSlideCaptcha
|
||||
summary: 校验本地滑块位置并换取一次性票据
|
||||
description: 同源、CSRF 和运营登录会话校验;挑战每次提交即消费。成功票据绑定原会话、客户端、策略版本和原到期时间,只能用于一次短信发送或密码登录。
|
||||
security: [{ OperatorLoginCookie: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/RequestID' }
|
||||
- { $ref: '#/components/parameters/CSRF' }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: './login-captcha.yaml#/components/schemas/SlideCaptchaVerifyInput' }
|
||||
responses:
|
||||
'200':
|
||||
description: 位置正确,返回一次性校验票据
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: './login-captcha.yaml#/components/schemas/SlideCaptchaVerifyResponse' }
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
/api/v1/web/operator/login/password:
|
||||
post:
|
||||
operationId: operatorLoginPassword
|
||||
summary: 手机号、密码和图片验证码登录
|
||||
description: 使用与短信登录一致的手机号身份,密码登录不自动注册。每手机号 10 分钟最多 10 次密码尝试;每登录会话最多 20 次。失败返回统一的手机号或密码错误,不暴露手机号是否注册。密码正确但没有该账号的有效设备验证 Cookie 时返回 403 NEW_DEVICE_SMS_REQUIRED,不消费登录会话、不发账号 Cookie;完成现有 LOGIN 短信验证后签发 30 天 HttpOnly 设备验证 Cookie。已验证设备成功消费登录会话,签发 24 小时账号 Cookie。
|
||||
security: [{ OperatorLoginCookie: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/RequestID' }
|
||||
- { $ref: '#/components/parameters/CSRF' }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [phone_e164, password, captcha_id]
|
||||
anyOf:
|
||||
- required: [captcha_code]
|
||||
- required: [captcha_ticket]
|
||||
properties:
|
||||
phone_e164: { type: string, pattern: '^\+[1-9][0-9]{7,14}$' }
|
||||
password: { type: string, minLength: 1, maxLength: 256, writeOnly: true }
|
||||
captcha_id: { type: string, format: uuid }
|
||||
captcha_code: { type: string, pattern: '^[0-9]{6}$', writeOnly: true }
|
||||
captcha_ticket: { type: string, maxLength: 4096, writeOnly: true }
|
||||
captcha_randstr: { type: string, maxLength: 256, writeOnly: true, description: 腾讯云 Web 模式必填,本地滑块模式无需提供 }
|
||||
responses:
|
||||
'200':
|
||||
$ref: '#/paths/~1api~1v1~1web~1operator~1login~1sms~1verify/post/responses/200'
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
/api/v1/web/operator/account/password:
|
||||
get:
|
||||
operationId: operatorPasswordState
|
||||
summary: 查看当前手机号和密码设置状态
|
||||
security: [{ OperatorAccountCookie: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: 仅返回脱敏手机号、是否已设置密码、是否具有最近 10 分钟内且未消费的短信验证,不返回密码或摘要
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok: { type: boolean }
|
||||
data:
|
||||
type: object
|
||||
required: [available]
|
||||
properties:
|
||||
available: { type: boolean }
|
||||
phone_masked: { type: string }
|
||||
password_configured: { type: boolean }
|
||||
sms_verified_recently: { type: boolean }
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
post:
|
||||
operationId: operatorSetPassword
|
||||
summary: 设置、修改或重置当前手机号的密码
|
||||
description: 需要当前有效账号 Cookie、同源及 CSRF;同时需要最近 10 分钟内且未消费的短信验证,或正确的当前密码。新密码 6–64 个 Unicode 字符且不超过 256 字节。修改后清除短信证明并撤销该身份的其他管理登录会话,保留本次会话。密码使用随机盐 Argon2id 存储。
|
||||
security: [{ OperatorAccountCookie: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/RequestID' }
|
||||
- { $ref: '#/components/parameters/CSRF' }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [password]
|
||||
properties:
|
||||
password: { type: string, minLength: 6, maxLength: 64, writeOnly: true }
|
||||
current_password: { type: string, maxLength: 256, writeOnly: true }
|
||||
responses:
|
||||
'200':
|
||||
description: 密码已保存
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok: { type: boolean }
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
password_configured: { type: boolean }
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
/api/v1/web/operator/account/session:
|
||||
get:
|
||||
operationId: operatorAccountSession
|
||||
summary: 恢复管理端登录会话并获取 CSRF
|
||||
security: [{ OperatorAccountCookie: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: 有效管理账号会话
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok: { type: boolean }
|
||||
data:
|
||||
type: object
|
||||
required: [authenticated, csrf_token]
|
||||
properties:
|
||||
authenticated: { type: boolean }
|
||||
csrf_token: { type: string }
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
/api/v1/web/operator/auth/logout:
|
||||
post:
|
||||
operationId: operatorLogout
|
||||
summary: 撤销当前管理端会话并清除其 Cookie
|
||||
description: 同源与 CSRF 校验;家庭端会话不受影响。
|
||||
security: [{ OperatorAccountCookie: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/RequestID' }
|
||||
- { $ref: '#/components/parameters/CSRF' }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { type: object, additionalProperties: false }
|
||||
responses:
|
||||
'200':
|
||||
description: 当前管理会话已退出
|
||||
default: { $ref: '#/components/responses/Failure' }
|
||||
components:
|
||||
securitySchemes:
|
||||
OperatorAccountCookie:
|
||||
type: apiKey
|
||||
in: cookie
|
||||
name: __Host-platform-operator
|
||||
description: 仅本地 HTTP 模式使用 platform-operator。与家庭端会话、密码独立;写操作需要同源及 CSRF。
|
||||
OperatorLoginCookie:
|
||||
type: apiKey
|
||||
in: cookie
|
||||
name: __Host-platform-operator-login
|
||||
description: Secure、HttpOnly、SameSite=Lax;仅本地 HTTP 模式使用 platform-operator-login。
|
||||
parameters:
|
||||
RequestID:
|
||||
in: header
|
||||
name: X-Request-ID
|
||||
required: true
|
||||
schema: { type: string, format: uuid }
|
||||
description: UUID v4,发送结果未知时用同一 ID 和正文重试。
|
||||
CSRF:
|
||||
in: header
|
||||
name: X-CSRF-Token
|
||||
required: true
|
||||
schema: { type: string }
|
||||
responses:
|
||||
Failure:
|
||||
description: 400/401/403/409/413/415/429/500/503;SMS_CODE_INVALID、LOGIN_SESSION_EXPIRED、SMS_RATE_LIMITED、SMS_SEND_UNCERTAIN、SMS_UNAVAILABLE、CAPTCHA_INVALID、CAPTCHA_UNAVAILABLE、PASSWORD_INVALID、PASSWORD_POLICY、CURRENT_PASSWORD_INVALID、SMS_REAUTH_REQUIRED、RATE_LIMITED 等,不返回验证码或密码。
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: './onboarding.yaml#/components/schemas/Failure' }
|
||||
@@ -0,0 +1,162 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: 平台代注册火山与设备凭据下发
|
||||
version: 1.1.0
|
||||
description: 已部署到82.157.201.114。设备HTTPS接口使用既有DEVREQ1签名请求头;成功响应均有ok/code/request_id/server_time_ms/data外层。设备不再调用DynamicRegister。
|
||||
servers:
|
||||
- url: https://82.157.201.114
|
||||
security:
|
||||
- DeviceRequest: []
|
||||
paths:
|
||||
/api/v1/device/chat/recording:
|
||||
post:
|
||||
summary: 在加入RTC房间前启动云端完整对话录音
|
||||
description: 使用现有DEVREQ1设备签名,只传房间标识,不上传音频。必须先申请chat/start,并使用硬件网关返回的RoomID、UserID及RTC AppID。平台核对当前绑定、会话、房间归属与原音频保存同意,发起纯音频合流录制。相同会话与房间重试使用固定任务ID。云端未配置或未授权保存时返回DISABLED或NOT_AUTHORIZED,设备仍可正常聊天。
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [session_id, rtc_app_id, room_id, rtc_user_id]
|
||||
properties:
|
||||
device_id: {type: string}
|
||||
session_id: {type: string, format: uuid}
|
||||
rtc_app_id: {type: string, maxLength: 128}
|
||||
room_id: {type: string, maxLength: 128}
|
||||
rtc_user_id: {type: string, maxLength: 128}
|
||||
responses:
|
||||
'200': {description: 'data.recording为STARTED、DISABLED或NOT_AUTHORIZED'}
|
||||
'400': {description: 请求格式错误或房间不匹配}
|
||||
'409': {description: 会话已结束、绑定已变化或录音身份冲突}
|
||||
'503': {description: 火山录制启动暂不可用}
|
||||
default: {description: 设备鉴权失败}
|
||||
/api/v1/device/chat/start:
|
||||
post:
|
||||
summary: 绑定后直接申请或续期聊天参数,无需平台注册开机与SDK初始化回执
|
||||
description: 平台检查当前老人绑定、火山设备注册结果和老人智能体。设备保存ble-bind下发的5个凭据,在本地初始化SDK后请求本接口。相同session_id每10秒续期,不重复创建火山任务。旧boot_id可兼容但不用于准入。未绑定返回409 DEVICE_UNBOUND。
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [session_id]
|
||||
properties:
|
||||
device_id: {type: string, description: 设备factory_id,应与签名头一致;旧固件可省略}
|
||||
session_id: {type: string, format: uuid, description: 每通新聊天生成;重试及续期不变}
|
||||
boot_id: {type: string, format: uuid, deprecated: true, description: 仅兼容旧固件;新设备省略}
|
||||
responses:
|
||||
'200': {description: 'data包含session_id、bot_id、params、lease_expires_at_ms和expires_at_ms。params.AgentConfig的回调地址与签名按本通session_id原样传给火山。'}
|
||||
'409': {description: DEVICE_UNBOUND、DEVICE_NOT_READY(平台注册未完成)、VOICE_AGENT_NOT_READY、CHAT_ENDED等}
|
||||
default: {description: 设备鉴权失败、请求格式错误、并发通话、配额或供应商配置失败}
|
||||
/api/v1/device/chat/end:
|
||||
post:
|
||||
summary: 设备停止本次聊天后上报结束
|
||||
description: 同一session_id可重复上报;解绑后仍允许本设备补报旧会话结束。没有boot_id或初始化回执要求。
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [session_id, reason]
|
||||
properties:
|
||||
device_id: {type: string}
|
||||
session_id: {type: string, format: uuid}
|
||||
reason: {type: string, enum: [hangup, start_failed, disconnected, reboot, timeout]}
|
||||
sdk_stopped: {type: boolean, default: false, description: 仅确认SDK已停止时填true}
|
||||
responses:
|
||||
'200': {description: 'data包含session_id和ended=true'}
|
||||
default: {description: 设备鉴权失败或请求格式错误}
|
||||
/api/v1/device/voice-config:
|
||||
post:
|
||||
summary: 可选恢复接口:重新取得本设备的火山凭据
|
||||
description: 正常ble-bind已直接返回5个字段,无需再查本接口。此接口保留原voice_status/voice格式;body为空对象。不要求先登记boot_id;未绑定返回409 DEVICE_UNBOUND;非ready状态voice为null。
|
||||
requestBody:
|
||||
$ref: '#/components/requestBodies/Empty'
|
||||
responses:
|
||||
'200':
|
||||
description: data包含voice_status和voice
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/VoiceEnvelope'
|
||||
default: {description: 设备鉴权失败、未绑定或状态冲突}
|
||||
/api/v1/device/voice-runtime:
|
||||
post:
|
||||
deprecated: true
|
||||
summary: 旧固件兼容:当前开机SDK初始化配置(新设备不调用)
|
||||
description: 仅供旧固件兼容。新设备直接保存ble-bind返回的凭据,在本地初始化SDK后请求chat/start,不调用register、voice-runtime或activation-acks。旧返回仍含state、command和call_contract。
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [boot_id]
|
||||
properties:
|
||||
boot_id: {type: string, format: uuid}
|
||||
responses:
|
||||
'200': {description: 当前绑定的语音状态及签名配置;preparing时每5秒查询}
|
||||
default: {description: 设备未绑定、开机编号不匹配或设备鉴权失败}
|
||||
/api/v1/device/voice-credentials:
|
||||
post:
|
||||
summary: 已注册旧固件一次性迁移本机凭据
|
||||
description: 只接受平台已有已注册记录、当前绑定有效、实例/产品/设备名匹配的原凭据。重复相同内容幂等,不覆盖已有不同凭据。新设备不调用此接口。
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/VoiceCredential'
|
||||
responses:
|
||||
'200': {description: 'data: {accepted: true},然后重新获取voice-runtime'}
|
||||
default: {description: 未注册、未绑定、身份不匹配或VOICE_CREDENTIAL_CONFLICT}
|
||||
components:
|
||||
securitySchemes:
|
||||
DeviceRequest:
|
||||
type: apiKey
|
||||
in: header
|
||||
name: Authorization
|
||||
description: Device-HMAC-SHA256签名;另需X-Device-ID/X-Key-Version/X-Timestamp-Ms/X-Nonce/X-Request-ID和Content-Type。
|
||||
requestBodies:
|
||||
Empty:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {type: object, additionalProperties: false}
|
||||
schemas:
|
||||
VoiceCredential:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [instance_id, product_key, device_name, device_secret, RTCAppID]
|
||||
properties:
|
||||
instance_id: {type: string}
|
||||
product_key: {type: string}
|
||||
device_name: {type: string}
|
||||
device_secret: {type: string, minLength: 16, maxLength: 256}
|
||||
RTCAppID: {type: string, minLength: 1, maxLength: 128}
|
||||
VoiceEnvelope:
|
||||
type: object
|
||||
required: [ok, code, request_id, server_time_ms, data]
|
||||
properties:
|
||||
ok: {const: true}
|
||||
code: {const: OK}
|
||||
request_id: {type: string, format: uuid}
|
||||
server_time_ms: {type: integer, format: int64}
|
||||
data:
|
||||
type: object
|
||||
required: [voice_status, voice]
|
||||
properties:
|
||||
voice_status:
|
||||
type: string
|
||||
enum: [preparing, ready, paused, reconcile_required, migration_required]
|
||||
voice:
|
||||
oneOf:
|
||||
- {$ref: '#/components/schemas/VoiceCredential'}
|
||||
- {type: 'null'}
|
||||
Reference in New Issue
Block a user