Files
cmroubao/docs/tasks/T-215.md
T

147 lines
6.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.
---
id: T-215
title: Admin 候选确认与一次性下单授权
phase: 2
deps:
- T-214
status: DOING
created: 2026-07-28
context_ref: 56e7a2b
work_branch: null
write_paths:
- docs/tasks/T-215.md
- docs/00-ai-start-here.md
- docs/02-requirements.md
- docs/04-architecture.md
- docs/06-tasks.md
- docs/07-user-stories.md
- docs/08-interaction-checklist.md
- docs/api.md
- docs/current-state.md
- docs/routes.md
- backend-api/migrations/**
- backend-api/internal/domain/**
- backend-api/internal/usecase/**
- backend-api/internal/repository/sqlite/**
- backend-api/internal/transport/httpapi/**
- backend-api/internal/transport/webui/**
---
## 问题 / 背景
T-214 已给每个候选建立 execution-scoped `candidate_key`,但任务仍由手机上的采购员
提交 human review 并结束。新需求要求 Admin 采购员查看 Top 5 后选择商品,再把明确
授权同步给同一台 Roubao 设备;候选列表或 URL 本身不能成为下单许可。
本任务实现后台选择、逐候选理由和不可变的一次性授权。它不实现设备拉取或拼多多
点击;T-216 才把待投递授权转换为设备命令。
## 冻结合约
### 等待确认
1. 当前 execution 首次成功保存非空候选批次后,任务在同一事务从 `RUNNING` 进入
`WAITING_CONFIRMATION`,增加 task version,并追加 `CANDIDATES_READY` 事件。
2. 设备 heartbeat 在该状态继续有效,但不能凭候选回传重新开始页面动作。空候选
仍允许现有 `NO_MATCH/MANUAL_REQUIRED` 终态,不创建授权。
3. Admin 只能为当前活跃 execution、当前 task content hash 和 v7 identity 完整的
observation 授权;取消已请求、授权到期、终态或旧 execution 一律拒绝。
### Admin 决策与授权
新增管理会话鉴权、CSRF/幂等保护的
`POST /api/v1/tasks/{task_id}/order-authorizations`:
```json
{
"execution_id": "uuid",
"task_content_sha256": "64-char-lowercase-hex",
"expected_task_version": 4,
"candidate_key": "64-char-lowercase-hex",
"reason_schema_version": 1,
"primary_reason_code": "SELECTED_BEST_MATCH",
"note": "",
"supersedes_authorization_id": null,
"items": [
{
"candidate_key": "selected-key",
"label": "ACCEPT",
"primary_reason_code": "SKU_MATCH",
"reason_codes": ["SKU_MATCH", "IMAGE_MATCH"],
"note": ""
},
{
"candidate_key": "rejected-key",
"label": "REJECT",
"primary_reason_code": "NOT_BEST_MATCH",
"reason_codes": ["NOT_BEST_MATCH"],
"note": ""
}
]
}
```
1. `items` 必须按 candidate key 恰好覆盖当前 execution 的全部 observation,且只有
顶层 `candidate_key` 对应项为 `ACCEPT`。理由沿用 T-208 schema v1 allowlist 和
`OTHER` 备注规则;无预算任务仍禁止价格类理由。
2. 仓储在一个 immediate transaction 内把 candidate key 映射回原 ordinal,追加一版
`candidate_human_reviews`(`actor_device_id=NULL`),再创建一条不可变
`order_authorizations`。不得信任请求传入的 ordinal、SKU、数量、价格或 URL。
3. 授权快照由服务端读取:task/execution/content hash、candidate key、review ID/
version、原始 SKU、任务数量、候选规格摘要、组合价格和四个身份指纹。数量只能来自
原始任务,Admin 不能在选品表单中改写。
4. 授权初始状态为 `PENDING_DELIVERY`,版本从 1 递增;同一 execution 同时最多一条
active 授权。相同幂等键和请求返回原结果,不新增 review、授权或事件。
5. 设备领取前允许 Admin 改选,但请求必须引用当前 active
`supersedes_authorization_id`;旧授权原子变为 `SUPERSEDED`,review/授权历史均不
覆盖。非当前引用、已投递或已执行授权拒绝修改。
6. 每次创建或改选追加 `ORDER_AUTHORIZATION_CREATED` 任务事件,事件只记录授权 ID、
版本和 candidate key 的短前缀,不记录第三方 URL 或页面全文。
### Admin API/Web
1. Admin 任务详情返回结构化 observations、当前/历史 review 和 order authorization,
每项展示标题、SKU 摘要、组合价格、受控详情/规格截图、candidate key 和模型理由。
2. `WAITING_CONFIRMATION` 且存在候选时显示单选候选、选择理由、对其余候选批量拒绝
理由、可选备注和“确认商品并授权下单”按钮。表单服务端展开为逐候选 items。
3. 页面必须明确“仅授权创建待付款订单,不授权付款”;没有可授权候选、数据版本冲突
或已有不可修改授权时禁用提交并给出可操作状态。
4. Admin API/Web 不请求第三方商品/图片 URL,也不提供由浏览器直接触发设备动作的
通道。
## 数据模型
v8 新增:
- `order_authorizations`:授权 ID、task/execution、版本、candidate key、内容 hash、
review、原始 SKU/数量、候选 SKU/价格、四个指纹、状态、创建人、时间和可空
supersedes ID。
- `admin_order_authorization_requests`:管理员、幂等键、请求 hash、task 和授权引用。
状态预留 `PENDING_DELIVERY/DELIVERED/ACKNOWLEDGED/EXECUTING/CONSUMED/FAILED/
REVOKED/SUPERSEDED`;T-215 只产生 `PENDING_DELIVERY` 和 `SUPERSEDED`。存在授权数据
时 v8 destructive down 必须失败。
## 验收要点
- [ ] 非空候选批次原子进入 `WAITING_CONFIRMATION`,重复回传不重复增加事件/version。
- [ ] Admin 请求只用 candidate key,完整覆盖候选且每项接受/拒绝都有合法理由。
- [ ] review、授权、旧授权 supersede、任务事件和幂等记录原子提交。
- [ ] 跨任务/execution、旧 hash/version、伪造 key、缺 identity 和并发双授权被拒绝。
- [ ] 授权数量/SKU/价格/指纹均由服务端快照,Admin 不能篡改。
- [ ] Admin API/Web 可选候选、查看证据和理由,明确只创建待付款订单且不授权付款。
- [ ] v8 migration、Go test/race/vet、根验证和管理页面桌面/移动视口通过。
## 边界
- 不让设备拉取或确认授权;属于 T-216。
- 不重新打开拼多多、选择 SKU/数量或进入订单确认页;属于 T-217。
- 不提交订单、读取订单号或付款;属于 T-218/T-219。
- 不使用 URL、ordinal、模型推荐或旧手机 review 直接代替 Admin 明确授权。
## 执行记录
- 2026-07-28:T-214 实现提交 `56e7a2b` 后领取。决定复用
`WAITING_CONFIRMATION`,并把 Admin review 与一次性授权放在同一事务;设备投递和
页面动作继续保持为后续独立权限层。