4 Commits
Author SHA1 Message Date
chengma 10bb892e6c feat: 移除 Client 真实采购手工授权 (#114) 2026-08-10 18:37:35 +08:00
chengmaandClaude Opus 5 5a5c1f1f68 feat: 新增幂等 Client 登记接口 (#12)
PUT /api/v1/client/registration —— 设置页点"保存"时调用,
只登记客户端,不碰任务。

为什么需要它
原设计"注册就在 claim 里做"有个真问题:设置页保存被迫调 claim,
而 claim 可能真的领到一个任务——Admin 那边已把任务标成 claimed,
Client 必须可靠落库否则任务就丢了。一个"保存设置"的动作
不该承担"领取任务并保证不丢"的责任。这违反了本项目自己的原则
(05 §1:界面上只有一个会产生外部后果的命令)。

实现
- ClientProfileRequest + Validate() 由**登记和领取共用**,
  避免两个入口的结构和校验各写一份、迟早漂移
- 校验:名称 <=50 字(按字符不按字节,中文一个字三字节)、
  supported_types 非空且只含 collect/purchase、platform 只支持 android、
  purchase_mode 必填且只允许 dry_run/live、schema_versions 均为正整数
- 非法内容返回 422 INVALID_CLIENT_PROFILE,错误消息指明具体字段
- UpsertClient 加 explicit 参数区分名称规则:
  显式登记(用户点保存)带非空名称时更新名称;
  隐式登记(claim 顺带)永不更新,否则操作员改的名字会被反复冲掉

已验证(Go 1.23.0)
- 单元测试 40 个全过,含"登记不产生任何任务副作用"的快照比对
- 端到端逐条走完手册 §5.2~5.7:重复登记记录数恒为 1;
  更新/空名称行为正确;插入任务后登记 3 次任务字段完全未变且仍可领取;
  四种非法输入均 422 且不写库;claim 不受影响

一处行为变更需注意
名称归属规则改了:原来是"Admin 操作员永远赢",现在是"最后一次
显式操作赢"——用户在 Client 点保存会覆盖 Admin 侧改的名字。
按 #12 文档实现,已拆成三个独立测试盯住三种情况。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 17:31:38 +08:00
chengma 02073eab37 docs: define idempotent Client registration contract (#12) 2026-08-06 17:21:36 +08:00
chengmaandClaude Opus 5 62d46bf10a docs: 新增设备登记联调手册,并定案 client.name
面向 Client 开发者的实操文档,目标是让一台新设备出现在 Admin 的
客户端列表里。文中所有请求和响应都是在真实运行的 Admin 上跑出来的。

新增 docs/admin/07-设备登记联调手册.md
- 先讲清"没有注册接口,登记是 claim 的副作用"
- **重点提示 204 不是错误**:新设备第一次 claim 必然 204,
  它同时意味着登记成功。这是最容易被 Client 误判成失败的地方
- 设备号必须持久化、永不变——变了 Admin 会当成新机器,
  列表里会堆一串僵尸记录
- 设备名只在首次登记时采纳,之后 Admin 侧改名不会被覆盖。
  这个行为会让人困惑("我改了 Client 怎么 Admin 没变"),先说清楚
- 四步验证流程 + 可直接复制的 curl + 手工插测试任务的 SQL
- 7 条常见问题,含"列表里多出好几台一样的机器"这类实际会碰到的
- 列出 Client 侧待办清单,标明前两条做完就能登记成功

定案 client.name(原 [待定])
Client 设置页本来就有「设备名」输入框(deviceNameInput,50 字上限),
只是没接进 ClientInfo。Admin 仍容忍它缺失,缺了用 X-Client-Id 兜底,
所以 Client 先不发也不影响登记。

同步更新
- docs/client/04-admin-api-contract.md §5:请求示例补 client 字段,
  加"204 不是错误"的必须项,并指向本手册
- docs/README.md:两处导航加入口,Client 侧"对接 Admin"那行也指过来

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 17:08:58 +08:00