feat: 移除 Client 真实采购手工授权 (#114)

This commit is contained in:
chengma
2026-08-10 18:37:35 +08:00
parent 8188153b08
commit 10bb892e6c
29 changed files with 124 additions and 702 deletions
+1 -1
View File
@@ -282,7 +282,7 @@ CMAutoBuy/ 整个文件夹拷到任何机器都能用
**已定案(不再是待确认项):**
- Admin 新建采购任务固定为 `execution_mode=live`,不再提供演练选择;Client 本地授权仍默认关闭,只有绑定 Client ID、Android 设备且通过安全门禁后才声明 live 能力和领取任务。
- Admin 新建采购任务固定为 `execution_mode=live`,不再提供演练选择;Client 不提供手工 live 授权,身份、已选 Android 设备和真实采购 Adapter 就绪时自动声明 live 并领取任务。
- Admin 只分配任务给指定 Client,Client 不读全局任务池。见 [04](04-admin-api-contract.md) §5.1。
- **没有租约、没有心跳、没有状态回查。** 任务流程只有领取、提交结果、提交失败三个调用;设置页另有无任务副作用的幂等 Client 登记调用。见 [04](04-admin-api-contract.md) §1、§4.1。
- 本地只存已领取任务,已完成任务**永久保留**。诊断产物(截图、XML、日志)仍按 `diagnostics.retention_days` 清理,两者不是一回事。见 [03](03-data-model.md) §3.1。
+3 -3
View File
@@ -367,8 +367,8 @@ Client 与 Admin 的任务交互只有三种调用:领一个任务、提交结
`TaskDispatcher` 是能力声明的唯一入口。没有可用采购 Adapter、没有已保存
Android 设备或本地持久化未准备好时,只声明 `collect`;条件满足时才声明
`collect,purchase`。Admin 新建采购任务固定为 live,但 Client 本地授权仍默认关闭;
只有本地授权同时匹配当前 Client ID、已保存 Android 设备且 live Adapter 就绪时才声明
`collect,purchase`。Admin 新建采购任务固定为 live;Client 不再读取手工授权,只有当前
Client 身份有效、已保存 Android 设备且 live Adapter 就绪时才自动声明
`purchase_mode=live`,否则声明 `dry_run` 且不能领取新建的 live 采购任务。领取响应必须先完整校验并
写入 SQLite,Repository 提交成功后才能分派,避免任务已在 Admin 领取却在本地丢失。
@@ -449,7 +449,7 @@ PDD 页面可能出现登录失效、验证码、控件树不完整、A/B 页面
4. 使用 Outbox 保证结果最终提交,并隔离“提交重试”与“业务重做”。
5. MVP 单设备串行执行,不并行控制多个设备。
6. 采集规格采用通用维度和 SKU 组合结构,不把模型锁死为颜色与尺码两个数组。
7. Admin 新建采购任务固定为真实下单(不支付);Client 只有通过独立安全验收和本地设备绑定后才声明 live 能力。
7. Admin 新建采购任务固定为真实下单(不支付);Client 身份、已选设备和 live Adapter 就绪后自动声明 live,真实设备结果仍按独立工单验收。
## 11. 相关文档
+1 -5
View File
@@ -422,17 +422,13 @@ CREATE TABLE app_settings (
- `automation.poll_interval_seconds`
- `automation.max_retries`
- `automation.dry_run`
- `purchase.live_enabled`
- `purchase.live_client_id`
- `purchase.live_device_serial`
- `purchase.live_confirmed_at`
- `safety.max_quantity`
- `safety.price_tolerance_cent`
- `diagnostics.artifact_directory`
- `diagnostics.retention_days`
访问令牌、密码和 Cookie 不得存入本表。
`purchase.live_*` 只保存非敏感的本地安全门禁状态;缺失、损坏或绑定不一致时一律按关闭处理。
历史版本可能遗留 `purchase.live_*` 设置;当前版本不再读取或写入这些键,也不依赖它们决定领取能力。
## 7. 任务状态转换
+6 -5
View File
@@ -211,8 +211,8 @@ POST /api/v1/client/tasks/claim
Client 的 `HttpAdminGateway.claim_next` 已实现本接口,并原样序列化应用层已经
安全确认的 `ClaimCapabilities`。没有采购 Adapter 或设备未准备好时只声明
`supported_types: ["collect"]`;条件满足时声明 `collect,purchase`。只有设置页
授权同时匹配当前 Client ID、已保存 Android 设备且 live Adapter 就绪时才声明
`supported_types: ["collect"]`;条件满足时声明 `collect,purchase`。Client 不发送手工
真实采购启用请求;当前 Client 身份有效、已保存 Android 设备且 live Adapter 就绪时自动声明
`purchase_mode: "live"`,其他情况均为 `dry_run`。一次调用最多领取一个任务,结果或失败通过
本页 §6 或 §7 提交,完整请求会先进入本地 Outbox。
@@ -232,7 +232,7 @@ Client 的 `HttpAdminGateway.claim_next` 已实现本接口,并原样序列化
规则:
- `[必须]` 领取必须在 Admin 内部原子完成,一次调用最多返回一个任务。
- `[必须]` Admin 不得向只声明 `dry_run` 的 Client 分配要求真实下单的任务。
- `[必须]` Admin 可以把真实采购任务预先指派给当前账号可见的任意 Client;领取时仍不得把 live 任务返回给只声明 `dry_run` 的 Client。
- `[必须]` `execution_mode` 只允许 `dry_run`、`live`。Admin Web 新建采购任务固定为 `live`;历史任务和接口缺省兼容值仍是 `dry_run`,Client 不得自行把模式从演练提升为真实。
- `[必须]` 声明 `dry_run` 的 Client 只能领取 `dry_run`;声明 `live` 的 Client 可以领取两种模式。能力只缩小可领取范围,不修改任务模式。
- `[必须]` 响应**不包含**租约。Client 拿到任务就开始做,做完再来领下一个。
@@ -247,8 +247,9 @@ Client 的 `HttpAdminGateway.claim_next` 已实现本接口,并原样序列化
| **无主** | 空 | `pending` | **谁先抢到算谁的**,领取时才记下领取者 |
领取还必须同时满足执行能力:`dry_run` Client 永远看不到 `live` 任务;
`live` Client 可以领取 `dry_run` 和 `live`。Admin 当前只允许真实采购任务显式指定
一个已经登记并声明 `purchase_mode: "live"` 的 Client,因此真实任务不会进入无主任务池。
`live` Client 可以领取 `dry_run` 和 `live`。Admin Web 创建真实采购任务时显式指定
当前账号可见的 Client,不要求创建时已经声明 live;未就绪或离线 Client 的任务保持
`assigned`,直到该 Client 自动声明 live 后领取,因此真实任务不会进入无主任务池。
`[必须]` **指定给本机的优先于无主的。** 显式分配是人为决定,应当先兑现;
无主任务谁抢都一样,可以等。
+5 -6
View File
@@ -293,13 +293,12 @@ class TaskTableModel(QAbstractTableModel):
- 最大重试次数;
- 演练模式开关。
### 真实采购授权(不支付)
### 真实采购运行就绪(不支付)
- Admin 新建采购任务固定为 live;Client 本地授权默认关闭,并明确显示当前状态、绑定 Client、绑定 Android 设备和确认时间;
- 只有输入完整确认文字“创建未付款订单”后才能启用,不能通过环境变量或调试参数开启;
- 启用和关闭在后台线程保存,执行期间禁用重复操作,失败时保留原状态并说明恢复办法;
- 启用仅代表允许创建一笔未付款订单,不允许自动付款;设备或 Client 绑定变化后撤销 live 能力并停止领取新采购任务;
- 关闭操作始终可见,状态不能只用颜色表达。
- 设置页不显示真实采购授权、确认文字或启用/关闭按钮;
- Client 身份和 Android 设备保存后,真实采购 Adapter 就绪的 Client 自动登记 live 能力;
- 身份、设备或 Adapter 任一未就绪时不领取真实采购任务,页面继续通过现有设备状态说明缺失项;
- 自动就绪只允许创建未付款订单,不允许自动付款。
### 安全与诊断
+12 -10
View File
@@ -70,7 +70,7 @@ PDD 解析测试优先使用脱敏的 XML 固件,不要求每次连接真实
## 3. 采购安全门禁
Admin 新建采购任务固定为真实下单(不支付);Client 本地 live 授权仍默认关闭。全部满足后才能声明 live 能力并领取真实采购任务:
Admin 新建采购任务固定为真实下单(不支付),Client 不再提供手工 live 授权。Client 身份有效、已选择 Android 设备且真实采购 Adapter 就绪时自动声明 live;领取并执行后仍必须满足下列安全门禁:
1. Admin 原子领取和结果幂等已经通过联合测试。
2. Outbox 断网和重启恢复测试通过。
@@ -78,14 +78,10 @@ Admin 新建采购任务固定为真实下单(不支付);Client 本地 liv
4. 最终下单前后均有持久化步骤标记。
5. 进程在不可逆阶段退出后只执行订单核对,不会重新下单。
6. 订单匹配能识别唯一候选;多个候选进入人工处理。
7. 演练模式在代表性商品和设备上通过验收。
8. 操作人员明确确认真实下单范围和安全设置。
7. 历史演练模式和真实模式在代表性商品与设备上通过自动化验收。
8. 真实设备首单按独立验收工单执行,并明确停止在支付前。
Client 本地 live 授权不得通过调试参数、默认配置或界面误操作意外开启。当前版本仅在设置页
精确输入确认文字后保存授权,并绑定 Client ID 和已保存 Android 设备;任一绑定
不一致都降级为 `purchase_mode=dry_run`。演练 Adapter 不提供提交方法,live Adapter
只提供一次性提交方法,两者都不提供付款或取消订单方法。开发者不能把自动化测试
通过当成真机门禁放行;仍需项目负责人和实际操作人员共同确认。
Client 不保存或读取 `purchase.live_*` 手工授权设置。`purchase_mode` 只表达本次注册或领取时的运行就绪能力:身份、设备或真实采购 Adapter 任一缺失都声明 `dry_run`,全部就绪才自动声明 `live`。演练 Adapter 不提供提交方法,live Adapter 只提供一次性提交方法,两者都不提供付款或取消订单方法。开发者不能把自动化测试通过当成真机验收完成。
### 3.1 当前自动化安全检查
@@ -103,7 +99,7 @@ Client 本地 live 授权不得通过调试参数、默认配置或界面误操
演练的 `enter_confirmation` 与 `stop_before_submit` 均为只读检查。
- 单元测试必须断言演练没有最终点击、live 只有一次最终点击,且模糊目标不会点击。
上述只证明本地安全边界;真实设备联调仍须按独立验收工单获得当次明确授权。
上述只证明本地安全边界;真实设备联调仍须按独立验收工单记录结果,且不得进入付款操作。
## 4. 自动化防护
@@ -127,6 +123,12 @@ Client 本地 live 授权不得通过调试参数、默认配置或界面误操
商品失效。打开前后的商品页控件树签名相同则视为旧页面,不能据此执行规格选择或
下单;采购进入不可逆阶段前仍须按商品编号等业务字段再次确认目标身份。
页面轮询不得在每一轮依赖 `app_current()`:部分设备的前台查询会阻塞十秒以上,
还可能把已经显示 PDD 的页面报告为系统设置。连接时可以读取一次前台状态;后续
商品页和规格面板判断优先使用最新控件树中的包名与组合语义。单次设备调用即使跨过
截止时间,也要先分析刚返回的最新控件树,再决定成功或超时。规格面板超时必须记录
最后页面类型、控件树读取次数和脱敏 XML 引用,不保存商品、账号或收货相关原文。
> **运营提醒(不是代码规则):** Admin 超时重派可能导致同一任务被两台 Client 各下一单,
> 产生重复的未付款订单。人工审核时取消多余订单即可。但未付款订单长期堆积可能触发平台风控,
> 需要操作人员留意,不要放着不管。
@@ -276,7 +278,7 @@ Artifact 写入前应脱敏,数据库只保存引用。保留周期由设置
| 8 | 开源和商业许可证已确认 | 新增依赖的许可证是否允许本项目的使用方式 | **项目负责人**(不是开发者自己判断) |
| 9 | 真实下单版本额外满足采购安全门禁 | 逐条核对 §3 的 8 项 | **项目负责人 + 操作人员共同确认** |
第 8、9 项开发者**不要自己判断放行**。新增依赖时把包名和许可证类型报给项目负责人;真实下单开关必须由项目负责人和实际操作的人一起确认,见 §3。
第 8、9 项开发者**不要自己判断验收通过**。新增依赖时把包名和许可证类型报给项目负责人;真实设备下单验收必须由项目负责人和实际操作的人共同确认,见 §3。
## 11. 任务完成定义