Files
cmautobuy/docs/task/257-client安全应用运行时规格解析.md
T
2026-08-17 17:44:08 +08:00

66 lines
5.5 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.
# 257 Client:安全应用 Admin 规格解析结果并继续采购
- 类型:需求
- 父级大工单:#96(关联 Client Epic #1)
- 所属 MVP / 版本:#253 采购运行时 AI 规格纠偏闭环
- 状态:已完成
- 日期:2026-08-17
- Gitea 工单:<http://ilaer.eicp.net:8418/chengma/cmautobuy/issues/257>
## 背景与目标
#256 已能在目标尺码无法精确匹配时,生成当前商品、颜色和完整可购买尺码候选快照。本任务把该快照先保存到本地,再通过专用 Admin 命令请求一次规格解析;只有返回本次候选中的唯一匹配项,并且真机页面复查未变化时,才继续原有采购安全流程。
## 最终方案
- 为 Admin Gateway、HTTP Gateway 和 Mock Gateway 增加一次性 `resolve_purchase_spec` 命令,统一解析结果和错误语义。
- SQLite 升级到 schema v6,新增 `purchase_spec_resolutions` 表。请求在网络发送前落库,使用任务、执行尝试和候选哈希生成确定性幂等键;响应也先保存,再允许操作手机。
- `PurchaseTaskService` 捕获 #256 的结构化候选观察,单次调用 Admin。`uncertain`、`rejected`、`failed`、网络错误和非法响应均安全结束,不循环请求,也不自动重新采购。
- Admin 返回 `matched` 后,U2 Adapter 重新读取商品页、已选颜色和全部尺码候选,复算快照哈希,只按返回候选的页面原文精确点击并确认选中。
- 数量、订单总价上限、地址、不可逆标记、单次下单和只读核单继续走原有门禁。原任务规格不被覆盖;成功结果和失败诊断记录解析编号与实际采用规格。
- 实现与建单方案一致。真实 Admin 与真机端到端验证按 #258 单独执行。
## 改了哪些
- `client/src/admin_gateway.py`、`http_admin_gateway.py`、`mock_admin_gateway.py`:增加规格解析 DTO、HTTP 命令、严格响应校验和 Mock 幂等行为。
- `client/src/db_schema.py`、`task_models.py`、`task_repository.py`:增加 schema v6、解析记录模型以及请求先落库、响应审计和冲突保护。
- `client/src/purchase_task_service.py`:接入一次性解析流程,保持原规格和有效规格分离,并复用原采购安全门禁。
- `client/src/pdd_purchase_adapter.py`、`pdd_u2_purchase_adapter.py`:增加解析结果应用边界,重新读取并核对真机候选后精确选择。
- `client/src/pdd_purchase_reconcile_adapter.py`、`purchase_reconcile_service.py`:核单结果保留原请求规格、实际规格和解析审计信息。
- `client/test/` 相邻测试:覆盖 Gateway 契约、HTTP 响应、Mock 幂等、SQLite 迁移、Repository、采购服务、页面变化和核单结果。
- `docs/client/03-data-model.md`、`docs/client/06-quality-security.md`:补充本地表结构、持久化边界和采购安全规则。
## 验收结果
| 验收标准 | 结果 |
|---|---|
| 请求发送前持久化,相同任务、尝试和候选哈希复用同一内容与幂等键 | 通过 |
| HTTP 与 Mock 支持 matched、uncertain、rejected、failed、超时和幂等语义 | 通过 |
| 网络、SQLite 和 uiautomator2 仍由既有后台任务链调用,不新增 Qt 主线程阻塞 | 通过 |
| 只有响应哈希、候选编号、原文和 options 全部匹配时才继续 | 通过 |
| 继续前重新核对商品、颜色和候选快照,变化或无法确认选中时停止 | 通过 |
| 继续复用数量、总价、地址、不可逆标记、单次提交和只读核单门禁 | 通过 |
| 网络或业务解析失败不循环请求、不自动重新采购,并形成可追溯失败 | 通过 |
| 不可逆运行保持只读核单路径,不因规格解析重新调用采购 Adapter | 通过 |
| 最终结果包含解析编号和实际规格,不保存凭据、原始 XML 或个人数据 | 通过 |
| Python 3.10 定向测试、迁移测试、编译和离屏 UI 冒烟 | 通过 |
## 测试
- 执行的命令:
- `C:/Python310/python.exe -m pytest test/test_admin_gateway_contract.py test/test_http_admin_gateway.py test/test_db.py test/test_task_repository.py test/test_purchase_task_service.py test/test_pdd_u2_purchase_adapter.py test/test_pdd_u2_purchase_reconcile_adapter.py -q`
- `C:/Python310/python.exe -m pytest test -q`
- `C:/Python310/python.exe -m py_compile src/admin_gateway.py src/db_schema.py src/http_admin_gateway.py src/mock_admin_gateway.py src/pdd_purchase_adapter.py src/pdd_purchase_reconcile_adapter.py src/pdd_u2_purchase_adapter.py src/purchase_reconcile_service.py src/purchase_task_service.py src/task_models.py src/task_repository.py`
- 设置 `QT_QPA_PLATFORM=offscreen` 后创建并关闭 `MainWindow`。
- 结果:定向测试 162 项全部通过;编译和离屏 UI 冒烟通过。Client 全量测试 492 项通过、2 项失败,失败均为工作区现有 `0.1.2` 版本号与旧测试固定期望 `0.1.0` 不一致,与 #257 无关。直接从 `client/` 执行无路径限制的 `pytest -q` 还会因 `test/` 和 `tools/` 中同名测试脚本产生既有收集冲突,因此全量单元测试明确使用 `pytest test -q`。
- **没验证到的部分**:未连接真实 Admin 和 Android 真机执行完整解析后下单链路;该验证属于 #258。没有进行自动付款。
## 遗留问题
- 真实 Admin、不同 PDD 页面结构和网络中断时的端到端表现由 #258 验证。
- 版本号相关的 2 个既有测试失败和同名脚本收集冲突不在本工单范围内。
## 相关提交
- `afc1cdf` 安全应用采购规格解析结果并继续采购。