Files
story/docs/onboarding-api-fields.md
T
2026-09-12 08:57:29 +08:00

413 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 首次接入接口字段清单
由 `node scripts/generate-onboarding-contract.mjs` 根据实际Go请求结构生成。共 31 项操作。完整响应结构见 [OpenAPI](../openapi/onboarding.yaml),流程、签名、错误恢复见 [实施说明](onboarding-implementation.md)。
## C01 校时挑战
`POST /api/v1/device/time-challenges`
调用身份:校时请求,无请求签名;设备必须核验TIME1响应MAC
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| device_id | string | 是 | 生产编号,KP01-加12位大写MAC;不是平台UUID |
| key_version | integer | 是 | 设备认证密钥版本 |
| boot_id | string | 是 | 每次启动生成并保持的UUID v4 |
| client_nonce | string | 是 | 设备生成的16字节随机数,Base64URL无填充 |
响应:根对象直接返回 `{payload_b64,mac_hex}`。
## C02 首次认证和启动注册
`POST /api/v1/device/register`
调用身份:设备DEVREQ1签名
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| challenge_id | string | 是 | C01签名校时返回的一次性挑战 |
| boot_id | string | 是 | 每次启动生成并保持的UUID v4 |
| hardware_model | string | 是 | 生产登记型号,当前为KP01 |
| hardware_revision | string | 是 | 硬件修订号,注册必须与库存一致 |
| firmware_version | string | 是 | 固件版本,用于兼容诊断 |
| sdk_version | string | 是 | SDK版本,用于兼容诊断 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `RegisterResponse.data`。
## C03 创建临时设置会话
`POST /api/v1/device/setup-sessions`
调用身份:设备DEVREQ1签名
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| boot_id | string | 是 | 每次启动生成并保持的UUID v4 |
| local_setup_id | string | 是 | 设备本次设置入口UUID v4;重试保持不变 |
| transport_profile | string | 是 | 固定LOCAL_WEB,表示设备提供本地网页入口 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `SetupResponse.data`。
## C04 获取一次性手机入口
`POST /api/v1/device/handoffs`
调用身份:设备DEVREQ1签名
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| setup_id | string | 是 | 云端15分钟临时设置会话UUID |
| local_setup_id | string | 是 | 设备本次设置入口UUID v4;重试保持不变 |
| code_challenge | string | 是 | SHA256(ASCII verifier)的Base64URL无填充值 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `HandoffResponse.data`。
## C05 查询状态和命令
`POST /api/v1/device/poll`
调用身份:设备DEVREQ1签名
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| setup_id | string | 是 | 云端15分钟临时设置会话UUID |
| boot_id | string | 是 | 每次启动生成并保持的UUID v4 |
| known_revision | integer | 是 | 设备已知状态版本;允许0 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `PollResponse.data`。
## C06 物理按键确认绑定
`POST /api/v1/device/claim-confirmations`
调用身份:设备DEVREQ1签名
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| claim_id | string | 是 | 待物理确认的绑定申请UUID |
| challenge | string | 是 | C05给设备的短时按键挑战,手机不能获取 |
| binding_digest | string | 是 | 云端生成的绑定摘要,按键回报原值 |
| expected_binding_generation | integer | 是 | 提交时预期绑定代数,防止跨解绑或重新绑定重放 |
| press_event_id | string | 是 | 该次真实物理按键事件UUID v4,重试保持不变 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `ConfirmationResponse.data`。
## C07 绑定状态持久化回执
`POST /api/v1/device/state-acks`
调用身份:设备DEVREQ1签名
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| device_revision | integer | 是 | 云端设备状态版本号 |
| binding_generation | integer | 是 | 绑定代数;解绑、重新绑定后旧代数无效 |
| local_generation | integer | 是 | 本次启动的本地持久化序号,不能倒退 |
| state_hash | string | 是 | STATE1规范字符串的SHA256小写十六进制摘要 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `StateAckResponse.data`。
## C08 申请设备执行许可
`POST /api/v1/device/activation-attempts`
调用身份:设备DEVREQ1签名
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| activation_id | string | 是 | 该物理设备唯一的激活任务UUID |
| config_version | integer | 是 | 配置版本,必须与当前云端版本一致 |
| attempt_id | string | 是 | 设备生成的UUID v4,表示一次引擎初始化或首通执行 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `AttemptResponse.data`。
## C09 回报设备执行结果
`POST /api/v1/device/activation-results`
调用身份:设备DEVREQ1签名
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| activation_id | string | 是 | 该物理设备唯一的激活任务UUID |
| attempt_id | string | 是 | 设备生成的UUID v4,表示一次引擎初始化或首通执行 |
| stage | string | 是 | SDK_REGISTER或CONVERSATION_TEST;与C08平台当前阶段一致 |
| sdk_result | integer | 是 | SDK执行返回码;SUCCESS_OBSERVED时必须为0 |
| outcome | string | 是 | SUCCESS_OBSERVED、DEFINITE_FAILURE或UNKNOWN;未知结果不得盲目重试 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `ResultResponse.data`。
## C10 激活结果保存回执
`POST /api/v1/device/activation-acks`
调用身份:设备DEVREQ1签名
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| activation_id | string | 是 | 该物理设备唯一的激活任务UUID |
| local_generation | integer | 是 | 本次启动的本地持久化序号,不能倒退 |
| config_version | integer | 是 | 配置版本,必须与当前云端版本一致 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `ActivationAckResponse.data`。
## C11 关闭临时设置入口
`POST /api/v1/device/setup-close`
调用身份:设备DEVREQ1签名
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| setup_id | string | 是 | 云端15分钟临时设置会话UUID |
| reason | string | 是 | 关闭、轮换或人工处理原因,见对应枚举 |
| final_revision | integer | 是 | 设备关闭设置入口前看到的最新状态版本 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `CloseResponse.data`。
## 手机兑换一次性入口
`POST /api/v1/web/handoffs/exchange`
调用身份:同源网页;一次性token和verifier
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| token | string | 是 | 90秒内只能兑换一次的handoff令牌 |
| verifier | string | 是 | 设备交给手机的PKCE校验值;32字节随机数的Base64URL无填充字符串 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `BrowserResponse.data`。
## 恢复手机设置会话
`GET /api/v1/web/setup/session`
调用身份:设置Cookie + 写请求CSRF
无请求正文。
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `BrowserResponse.data`。
## 关联OIDC登录
`POST /api/v1/web/setup/auth-link`
调用身份:设置Cookie + CSRF + OIDC Bearer
正文:`{}`。
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `BrowserResponse.data`。
## 发送登录短信
`POST /api/v1/web/auth/sms/send`
调用身份:设置Cookie + 写请求CSRF
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| phone_e164 | string | 是 | 含国家区号的手机号,例如+8613800000000 |
| purpose | string | 是 | 固定LOGIN |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `SMSResponse.data`。
## 验证短信并登录
`POST /api/v1/web/auth/sms/verify`
调用身份:设置Cookie + 写请求CSRF
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| sms_challenge_id | string | 是 | 发送短信得到的挑战UUID |
| code | string | 是 | 6位短信验证码;5分钟有效,最多验证5次 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `BrowserResponse.data`。
## 查询可选择的家庭使用者
`POST /api/v1/web/profiles`
调用身份:设置Cookie + 写请求CSRF
正文:`{}`。
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `ProfilesResponse.data`。
## 创建家庭或使用者
`POST /api/v1/web/profiles/create`
调用身份:设置Cookie + 写请求CSRF
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| household_id | string | 条件或可选 | 家庭公开UUID;省略时须提供新家庭名称 |
| household_name | string | 条件或可选 | 新建家庭的名称 |
| preferred_name | string | 是 | 使用者称呼,用于设备人设和家庭展示 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `ProfileResponse.data`。
## 提交绑定申请
`POST /api/v1/web/claims`
调用身份:设置Cookie + 写请求CSRF
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| elder_id | string | 是 | 使用者公开UUID,复用subject_profile |
| expected_binding_generation | integer | 是 | 提交时预期绑定代数,防止跨解绑或重新绑定重放 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `ClaimResponse.data`。
## 取消自己的绑定申请
`POST /api/v1/web/claims/cancel`
调用身份:设置Cookie + 写请求CSRF
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| claim_id | string | 是 | 待物理确认的绑定申请UUID |
| expected_binding_generation | integer | 是 | 提交时预期绑定代数,防止跨解绑或重新绑定重放 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `StateOnlyResponse.data`。
## 查询手机绑定进度
`POST /api/v1/web/setup/status`
调用身份:设置Cookie + 写请求CSRF
正文:`{}`。
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `WebStatusResponse.data`。
## 网页确认收到绑定结果
`POST /api/v1/web/setup/ack`
调用身份:设置Cookie + 写请求CSRF
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| binding_id | string | 是 | 当前已生效的绑定公开UUID |
| binding_generation | integer | 是 | 绑定代数;解绑、重新绑定后旧代数无效 |
| received_revision | integer | 是 | 网页已收到的设备状态版本 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `AckResponse.data`。
## 设置结束后查询我的设备
`GET /api/v1/web/onboarding/devices`
调用身份:账号Cookie;设备列表也支持OIDC Bearer
无请求正文。
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `DevicesResponse.data`。
## 恢复账号会话及CSRF
`GET /api/v1/web/account/session`
调用身份:账号Cookie;设备列表也支持OIDC Bearer
无请求正文。
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `AccountResponse.data`。
## 退出本浏览器登录
`POST /api/v1/web/auth/logout`
调用身份:账号Cookie;设备列表也支持OIDC Bearer
正文:`{}`。
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `LogoutResponse.data`。
## 查询生产设备和激活状态
`GET /api/v1/ops/device-inventory`
调用身份:运维OIDC Bearer + X-Tenant-ID
无请求正文。
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `DevicesResponse.data`。
## 登记生产设备
`POST /api/v1/ops/device-inventory`
调用身份:运维OIDC Bearer + X-Tenant-ID
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| factory_mac | string | 是 | 12位大写十六进制MAC;相同MAC不能创建第二台物理设备 |
| hardware_model | string | 是 | 生产登记型号,当前为KP01 |
| hardware_revision | string | 是 | 硬件修订号,注册必须与库存一致 |
| batch_no | string | 是 | 生产批次,方便追溯 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `InventoryResponse.data`。
## 向工装交付加密密钥
`POST /api/v1/ops/device-inventory/{id}/credential-deliveries`
调用身份:运维OIDC Bearer + X-Tenant-ID
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| enrollment_job_id | string | 是 | 生产登记或密钥轮换任务UUID |
| receiver_public_key_pem | string | 是 | 工装RSA公钥,PKIX PEM,2048至4096位,指数65537 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `DeliveryResponse.data`。
## 确认烧录读回并放行
`POST /api/v1/ops/device-inventory/{id}/release`
调用身份:运维OIDC Bearer + X-Tenant-ID
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| enrollment_job_id | string | 是 | 生产登记或密钥轮换任务UUID |
| evidence_ref | string | 是 | 烧录读回或人工对账的证据引用,不放密钥 |
| expected_key_version | integer | 是 | 交付放行目标版本;轮换时为当前生效版本 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `ReleaseResponse.data`。
## 准备轮换凭据
`POST /api/v1/ops/device-inventory/{id}/credential-rotations`
调用身份:运维OIDC Bearer + X-Tenant-ID
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| reason | string | 是 | 关闭、轮换或人工处理原因,见对应枚举 |
| expected_key_version | integer | 是 | 交付放行目标版本;轮换时为当前生效版本 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `InventoryResponse.data`。
## 人工记录激活对账结论
`POST /api/v1/ops/onboarding-activations/{id}/reconcile`
调用身份:运维OIDC Bearer + X-Tenant-ID
| 字段 | 类型 | 必填 | 用途 |
|---|---|---|---|
| expected_version | integer | 是 | 运维列表中的激活任务版本,防止覆盖并发处理 |
| conclusion | string | 是 | OBSERVED_REGISTERED、CONFIRMED_NOT_REGISTERED或DEVICE_ATTEMPT_STOPPED |
| evidence_ref | string | 是 | 烧录读回或人工对账的证据引用,不放密钥 |
| reason | string | 是 | 关闭、轮换或人工处理原因,见对应枚举 |
| attempt_id | string | 条件或可选 | 设备生成的UUID v4,表示一次引擎初始化或首通执行 |
| device_secret | string | 条件或可选 | 已核实的供应商单设备密钥,仅人工对账写入,加密保存 |
| rtc_app_id | string | 条件或可选 | 供应商RTC应用ID;不填则使用已保存值 |
响应:成功外层 `{ok,code,request_id,server_time_ms,data}`;失败 `{ok,code,request_id,message}`。data结构为 `StateOnlyResponse.data`。