docs: record implemented client key contracts (#237)
@@ -859,3 +859,102 @@ X-GoAuto-Device-Recovery-Code: <one-time-code>
|
||||
Agent 携带既有 Token(可已失效)及恢复码重新调用注册接口。服务端必须同时校验同一 `installId`、未停用状态、恢复码摘要、未过期和未使用;成功后使用原 `deviceId` 写入新 Token 摘要并返回一次新 Token,清除恢复码摘要和有效期。旧 Token 与恢复码都立即失效,已分配的 pending 采集或采购任务保持原 `deviceId`,不创建替代设备记录。缺少或错误恢复码仍为 `DEVICE_INSTALL_ID_CONFLICT`;过期码为 `DEVICE_RECOVERY_EXPIRED`;停用设备为 `DEVICE_DISABLED`。
|
||||
|
||||
自 #223 起,新建 SYB 任务在保持 `mappedColor` / `mappedSize` 为空和首趟 `spec_probe` 不变的同时,把创建时与目标规格对应的 confirmed 商品映射冻结为仅供服务端决策的指导快照。服务端收到当次候选后按角色验证该快照:只有规范化后唯一对应当次候选时才复用,并固化当次候选原文;否则该角色继续执行确定性匹配,仍未解决才把该角色及其封闭候选交给 AI。已解决角色不得重复发送给 AI,最终颜色和尺码仍须逐字属于各自当次候选。任务决策快照通过 `roleSources` 记录每个角色的 `manual_mapping` / `exact_match` / `ai_match` 来源;任务级 `specSource` 使用现有枚举汇总,不新增 Agent 决策权限。
|
||||
|
||||
## 客户端 API 与管理员密钥管理(#237)
|
||||
|
||||
实现基线 `57b0f15`;以下接口已通过隔离测试,尚未完成真实迁移/部署联调。Android 接口不变。
|
||||
|
||||
### 管理接口
|
||||
|
||||
前缀 `/api/admin/v1/client-keys`,要求 Admin JWT、admin 角色及 HTTPS,响应 `Cache-Control: no-store`。
|
||||
|
||||
| 方法与相对路径 | 输入 | 成功 data |
|
||||
|---|---|---|
|
||||
| GET 空路径 | page,固定每页 20 | items、total、page、pageSize |
|
||||
| GET /modules | 无 | 模块数组:key、title、group、writable、actions |
|
||||
| POST 空路径 | name(1~80 字符)、grants | key 元数据与仅本次返回的 secret |
|
||||
| PATCH /:keyId/grants | version、grants | 更新后的元数据 |
|
||||
| POST /:keyId/disable | version | 停用后的元数据 |
|
||||
|
||||
授权示例:`{"module":"pdd_products","write":false,"actions":[]}`;grants 为非空数组。元数据包括 id、name、prefix、enabled、version、grants、createdBy、updatedBy、createdAt、updatedAt、lastUsedAt,不返回摘要或完整密钥。管理请求只接受单个 JSON 对象、拒绝未知字段、最大 64 KiB。成功 code=200;无效输入 422、不存在 404、授权版本冲突或已停用 409。
|
||||
|
||||
### 客户端访问与错误语义
|
||||
|
||||
- 前缀 `/api/client/v1`,只接受 `Authorization: Bearer <客户端密钥>`,不接受 Cookie 或 URL 凭据,不与 JWT、Device Token 通用。
|
||||
- 所有环境均要求 TLS;仅在 `GOAUTO_TRUST_FORWARDED_PROTO=true` 且实际 TCP 对端为 loopback 时接受反向代理设置的 `X-Forwarded-Proto: https`。Agent HTTP 例外不适用。
|
||||
- HTTP 426 表示未使用 HTTPS;401 为缺失、无效或停用密钥;403 为模块/动作未授权;400 为查询参数携带凭据;503 为认证或审计暂不可用。业务错误沿用各既有接口。
|
||||
- 一般请求体最大 16 MiB;响应只支持有限 JSON(32 MiB),递归过滤凭据与原始载荷字段。不支持直接流式/二进制文件接口。响应不可序列化或超限时返回 502;业务可能已执行,必须先核对结果,不要自动重试。
|
||||
- 通过密钥认证的请求由服务端生成 `X-Client-Request-Id` 关联审计;它不是业务幂等键,原业务接口要求的 requestId 等字段仍须提供。允许请求必须先落审计意图;完成状态更新失败可留下 status=0。无效密钥没有 key_id 关联审计;拒绝授权的 403 审计为尽力记录。
|
||||
- GET `/ai-matching-settings` 只返回 `data.enabled`。POST `/ai-matching-settings/resolve` 接受 targetColor、targetSize、colors、sizes;每组最多 200 项,每个值最多 255 字符,总请求最大 64 KiB;确定性优先,必要时使用当前 Provider,返回 mappedColor、mappedSize、source;不保存映射、不创建任务,无法可靠匹配返回 422 安全提示。
|
||||
|
||||
### 明确开放的接口清单
|
||||
|
||||
下表路径均相对 `/api/client/v1`;普通业务请求字段沿用本文对应 Admin 业务契约。read=选中模块,write=模块读写,其他值均需 actions 逐项授权。没有列出的 Admin 接口不能用客户端密钥调用;新增 Admin 路由不会自动开放。
|
||||
|
||||
| 方法 | 路径 | 模块键 | 能力 |
|
||||
|---|---|---|---|
|
||||
| POST | `/ai-matching-settings/resolve` | ai_matching | match |
|
||||
| GET | `/devices` | devices | read |
|
||||
| GET | `/pdd-products` | pdd_products | read |
|
||||
| GET | `/pdd-products/:productId` | pdd_products | read |
|
||||
| POST | `/pdd-products` | pdd_products | write |
|
||||
| PATCH | `/pdd-products/:productId` | pdd_products | write |
|
||||
| GET | `/shopee-products` | shopee_products | read |
|
||||
| GET | `/shopee-products/:productId` | shopee_products | read |
|
||||
| POST | `/shopee-products` | shopee_products | write |
|
||||
| PATCH | `/shopee-products/:productId` | shopee_products | write |
|
||||
| POST | `/shopee-products/:productId/link-pdd` | shopee_products | write |
|
||||
| POST | `/shopee-products/:productId/specs/values` | shopee_products | write |
|
||||
| PUT | `/shopee-products/:productId/specs/mapping` | shopee_products | write |
|
||||
| DELETE | `/shopee-products/:productId/specs/values` | shopee_products | delete |
|
||||
| DELETE | `/shopee-products/:productId/specs/mapping` | shopee_products | delete |
|
||||
| POST | `/shopee-products/batch-delete` | shopee_products | delete |
|
||||
| POST | `/shopee-products/:productId/specs/mapping/auto-match` | shopee_products | match |
|
||||
| POST | `/shopee-products/:productId/specs/mapping/confirm` | shopee_products | match |
|
||||
| GET | `/syb-products` | syb_products | read |
|
||||
| GET | `/syb-products/:productId` | syb_products | read |
|
||||
| PATCH | `/syb-products/:productId/correction` | syb_products | write |
|
||||
| POST | `/syb-products/:productId/reparse` | syb_products | reparse |
|
||||
| POST | `/syb-products/reparse-batch` | syb_products | reparse |
|
||||
| GET | `/syb-products/sync-runs` | syb_sync_runs | read |
|
||||
| GET | `/syb-products/sync-runs/:runId` | syb_sync_runs | read |
|
||||
| POST | `/syb-products/import` | syb_sync_runs | sync |
|
||||
| GET | `/syb-inner-codes` | syb_inner_codes | read |
|
||||
| GET | `/syb-inner-codes/:recordId` | syb_inner_codes | read |
|
||||
| GET | `/syb-inner-codes/match-jobs/:jobId` | syb_inner_codes | read |
|
||||
| GET | `/syb-inner-codes/apply-batches/:batchId` | syb_inner_codes | read |
|
||||
| POST | `/syb-inner-codes/rematch` | syb_inner_codes | match |
|
||||
| POST | `/syb-inner-codes/import` | syb_inner_codes | import |
|
||||
| POST | `/syb-inner-codes/batch-delete` | syb_inner_codes | delete |
|
||||
| POST | `/syb-inner-codes/apply-preview` | syb_inner_codes | writeback |
|
||||
| POST | `/syb-inner-codes/apply` | syb_inner_codes | writeback |
|
||||
| POST | `/syb-inner-codes/:recordId/recheck` | syb_inner_codes | match |
|
||||
| GET | `/syb-shops` | syb_shops | read |
|
||||
| POST | `/syb-shops` | syb_shops | write |
|
||||
| PATCH | `/syb-shops/:shopId/name` | syb_shops | write |
|
||||
| PATCH | `/syb-shops/:shopId/enabled` | syb_shops | write |
|
||||
| DELETE | `/syb-shops/:shopId` | syb_shops | delete |
|
||||
| GET | `/collection-rules` | collection_rules | read |
|
||||
| POST | `/collection-rules` | collection_rules | write |
|
||||
| PATCH | `/collection-rules/:ruleId` | collection_rules | write |
|
||||
| DELETE | `/collection-rules/:ruleId` | collection_rules | delete |
|
||||
| GET | `/purchase-rules` | purchase_rules | read |
|
||||
| GET | `/purchase-rules/current` | purchase_rules | read |
|
||||
| POST | `/purchase-rules` | purchase_rules | write |
|
||||
| PATCH | `/purchase-rules/:ruleId` | purchase_rules | write |
|
||||
| DELETE | `/purchase-rules/:ruleId` | purchase_rules | delete |
|
||||
| PUT | `/purchase-rules/current` | purchase_rules | activate |
|
||||
| GET | `/collection-tasks` | collection_tasks | read |
|
||||
| GET | `/collection-tasks/:taskId` | collection_tasks | read |
|
||||
| POST | `/collection-tasks` | collection_tasks | collect |
|
||||
| POST | `/collection-tasks/batch` | collection_tasks | collect |
|
||||
| POST | `/collection-tasks/:taskId/reset` | collection_tasks | collect |
|
||||
| DELETE | `/collection-tasks/:taskId` | collection_tasks | delete |
|
||||
| GET | `/purchase-tasks` | purchase_tasks | read |
|
||||
| GET | `/purchase-tasks/:taskId` | purchase_tasks | read |
|
||||
| POST | `/purchase-tasks/batch-preview` | purchase_tasks | purchase |
|
||||
| POST | `/purchase-tasks` | purchase_tasks | purchase |
|
||||
| POST | `/purchase-tasks/batch` | purchase_tasks | purchase |
|
||||
| POST | `/purchase-tasks/batch-retry` | purchase_tasks | purchase |
|
||||
| POST | `/purchase-tasks/stock` | purchase_tasks | purchase |
|
||||
| GET | `/ai-matching-settings` | ai_matching | read |
|
||||
|
||||
Reference in New Issue
Block a user