docs(architecture): approve controlled trial SKU entry

This commit is contained in:
QiuSW
2026-08-04 10:59:40 +08:00
parent d81fc722dc
commit 82f57c7233
8 changed files with 198 additions and 100 deletions
+40 -15
View File
@@ -168,6 +168,27 @@
- 无可领任务返回 `200` 且 `task` 为 `null`,**不是 404**。
- 后续所有该任务的调用必须携带 `X-Claim-Token` 与匹配的 `claim_generation`。
### `POST /api/v1/tasks/{id}/evidence`(只接收脱敏派生物)
规格面板和订单确认页可能固定展示地址与掩码手机号。采购工具必须先在本机隔离目录保存原始证据,
再由确定性脱敏器生成派生 screenshot/XML;本接口只接受派生截图及如下审计元数据:
```json
{
"kind": "SKU_PANEL_SCREENSHOT",
"privacy_tier": "SANITIZED",
"artifact_sha256": "<派生截图 SHA-256>",
"sanitizer_version": "sku-panel-pdd-8.17.0-v1"
}
```
- `privacy_tier` 必须精确为 `SANITIZED`;缺失、其他值或 sanitizer 元数据不完整均拒绝。
- 上传内容的 SHA-256 必须等于 `artifact_sha256`。服务端不接收原始文件、原始哈希、原始路径、
原始 XML、地址、手机号或支付凭据;原始/派生哈希映射只存在于采购工具本机 manifest。
- 原始目录不得被 `HttpResultSink` 或证据上传器枚举;调用方必须显式传入已原子发布的派生目录。
- 完整 XML 永不上传。经自动复检的最小脱敏 XML 只用于采购工具离线 fixture;仍命中手机号模式或
脱敏结果不确定时,客户端调用 `/needs-manual`,不得上传截图或继续试选。
### `POST /api/v1/tasks/{id}/spec-trial`(第一趟回传)
```json
@@ -187,7 +208,7 @@
- `unit_price` 来自闸门一(规格面板)。**读不到时不要发这个接口**,改发
`/needs-manual` 并带原因码 `UNIT_PRICE_UNREADABLE`。
- `total_price` = `unit_price` × 任务数量,服务端会重算校验。
- 证据须先经 `/evidence` 上传。
- 证据须先经 `/evidence` 上传,且对应资产必须为 `privacy_tier=SANITIZED`。
- 服务端接收后创建 `spec_trials` 记录,任务转 `WAITING_CONFIRMATION`。
### dry-run 与真实提交协议
@@ -282,25 +303,29 @@ class ResultSink(ABC):
### 真机流程模块
`client/src/android/pdd_flow.py` 的公开入口,每个都不得越界:
`client/src/android/pdd_flow.py` 的公开入口按 capability 分离,每个都不得越界:
| 函数 | 输入 | 输出 | 副作用边界 |
| --- | --- | --- | --- |
| `open_product(url)` | 商品 URL | 页面快照路径 | 只打开页面,不点击购买 |
| `open_sku_panel()` | - | 面板快照 | 只点规格入口,不提交 |
| `select_sku_options(items)` | `{维度: 值}` | 选中证据 | 按维度精确匹配,找不到抛错 |
| `set_quantity(n)` | 数量 | 读回值 | 必须复核等于 n |
| `read_sku_unit_price(xml)` | 规格面板 XML | 单价或 `None` | **闸门一**;读不到返回 `None`,不猜 |
| `leave_product()` | - | - | 第一趟结束时退出并释放手机 |
| `go_to_order_confirm()` | - | 确认页摘要 | **可能创建订单**,需显式授权 |
| `read_order_confirm_info(xml)` | 页面 XML | 非敏感摘要 | **闸门三**;不提取地址原文、手机号 |
| `submit_order(auth, submission)` | 授权 + 已建立的提交围栏 | 提交结果 | **唯一创建真实订单入口**,四条件与围栏全通过后只点一次 |
| 函数 | 可用趟次 | 输入 | 输出 | 副作用边界 |
| --- | --- | --- | --- | --- |
| `open_product(url)` | TRIAL / ORDER | 商品 URL | 页面快照路径 | 只打开页面,不点击控件 |
| `open_trial_sku_panel(evidence_key)` | **仅 TRIAL** | 版本与证据绑定键 | 面板快照 | 只点击精确唯一、已取证的受控入口;当前仅 `快要抢光`,无通用 click |
| `select_sku_options(items)` | TRIAL / ORDER | `{维度: 值}` | 选中证据 | 按维度精确匹配,找不到抛错 |
| `sanitize_evidence(raw_manifest)` | TRIAL / ORDER | 本机隔离目录 manifest | 派生 manifest | 原子发布脱敏派生物;失败不发布,原始内容不进入日志/上传 |
| `read_sku_unit_price(xml)` | TRIAL / ORDER | 脱敏规格面板 XML | 单价或 `None` | **闸门一 / 二**;读不到返回 `None`,不猜 |
| `leave_product()` | TRIAL / ORDER | - | - | 第一趟结束时退出并释放手机 |
| `set_quantity(n)` | **仅 ORDER** | 数量 | 读回值 | 必须复核等于 n;TRIAL capability 不暴露 |
| `go_to_order_confirm()` | **仅 ORDER** | - | 确认页摘要 | 需显式授权;TRIAL capability 不暴露 |
| `read_order_confirm_info(xml)` | **仅 ORDER** | 脱敏页面 XML | 非敏感摘要 | **闸门三**;不提取地址原文、手机号 |
| `submit_order(auth, submission)` | **仅 ORDER** | 授权 + 已建立的提交围栏 | 提交结果 | **唯一创建真实订单入口**,四条件与围栏全通过后只点一次 |
两个不可逆入口:
能力隔离规则:
- `go_to_order_confirm()` 必须校验授权存在;`submit_order()` 还必须校验授权已由服务端围栏
且 `submission` 与当前任务、命令、授权完全一致。
- **第一趟的代码路径不得引用这两个函数。** 必须有测试证明试选流程不可达它们。
- 第一趟只能拿到 `TrialSkuFlow` 窄接口,接口中不得出现通用 `click`、`set_quantity()`、
`go_to_order_confirm()`、`submit_order()` 或支付能力;静态依赖测试必须证明试选流程不可达它们。
- `open_trial_sku_panel()` 的点击是唯一批准的购买语义控件例外,只用于打开已取证规格面板;入口
缺失/重复、App 版本不符、面板判据不唯一或出现未知终态控件时停止。其他入口文案不得推断复用。
- `search_by_image()` 属 B 路径,V2 再实现。
## 四、待实现时确认