Page:
T-215
Pages
00-ai-start-here
01-vision
02-requirements
03-tech-stack
04-architecture
05-coding-rules
06-tasks
07-user-stories
08-interaction-checklist
Design
Home
Integrations-shunyunbao-contract
PPT
T-001
T-002
T-003
T-004
T-101
T-102
T-103
T-104
T-201
T-202
T-203
T-204
T-205
T-206
T-207
T-208
T-209
T-210
T-211
T-212
T-213
T-214
T-215
T-216
T-217
T-218
T-219
T-220
T-221
T-222
T-223
T-224
T-225
T-226
T-227
T-228
T-229
T-230
T-231
T-232
T-233
T-234
T-235
T-236
T-237
T-238
T-239
T-240
T-241
T-242
T-243
T-244
T-245
T-246
T-247
T-248
T-249
T-250
T-251
T-252
T-253
T-254
T-255
T-256
T-257
T-258
T-259
T-260
T-261
T-262
T-263
T-264
T-265
T-266
T-267
T-268
T-269
T-270
T-271
T-272
T-273
T-274
T-275
T-276
T-277
T-278
T-279
T-280
T-281
Task-Template
Tasks
agent-context
api
clean-state-checklist
current-state
routes
Clone
Table of Contents
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.
同步来源:
docs/tasks/T-215.md· commitafc651f75a3a
id: T-215 title: Admin 候选确认与一次性下单授权 phase: 2 deps:
- T-214
status: DONE
created: 2026-07-28
context_ref:
56e7a2bwork_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 才把待投递授权转换为设备命令。
冻结合约
等待确认
- 当前 execution 首次成功保存非空候选批次后,任务在同一事务从
RUNNING进入WAITING_CONFIRMATION,增加 task version,并追加CANDIDATES_READY事件。 - 设备 heartbeat 在该状态继续有效,但不能凭候选回传重新开始页面动作。空候选
仍允许现有
NO_MATCH/MANUAL_REQUIRED终态,不创建授权。 - Admin 只能为当前活跃 execution、当前 task content hash 和 v7 identity 完整的 observation 授权;取消已请求、授权到期、终态或旧 execution 一律拒绝。
Admin 决策与授权
新增管理会话鉴权、CSRF/幂等保护的
POST /api/v1/tasks/{task_id}/order-authorizations:
{
"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": ""
}
]
}
items必须按 candidate key 恰好覆盖当前 execution 的全部 observation,且只有 顶层candidate_key对应项为ACCEPT。理由沿用 T-208 schema v1 allowlist 和OTHER备注规则;无预算任务仍禁止价格类理由。- 仓储在一个 immediate transaction 内把 candidate key 映射回原 ordinal,追加一版
candidate_human_reviews(actor_device_id=NULL),再创建一条不可变order_authorizations。不得信任请求传入的 ordinal、SKU、数量、价格或 URL。 - 授权快照由服务端读取:task/execution/content hash、candidate key、review ID/ version、原始 SKU、任务数量、候选规格摘要、组合价格和四个身份指纹。数量只能来自 原始任务,Admin 不能在选品表单中改写。
- 授权初始状态为
PENDING_DELIVERY,版本从 1 递增;同一 execution 同时最多一条 active 授权。相同幂等键和请求返回原结果,不新增 review、授权或事件。 - 设备领取前允许 Admin 改选,但请求必须引用当前 active
supersedes_authorization_id;旧授权原子变为SUPERSEDED,review/授权历史均不 覆盖。非当前引用、已投递或已执行授权拒绝修改。 - 每次创建或改选追加
ORDER_AUTHORIZATION_CREATED任务事件,事件只记录授权 ID、 版本和 candidate key 的短前缀,不记录第三方 URL 或页面全文。
Admin API/Web
- Admin 任务详情返回结构化 observations、当前/历史 review 和 order authorization, 每项展示标题、SKU 摘要、组合价格、受控详情/规格截图、candidate key 和模型理由。
WAITING_CONFIRMATION且存在候选时显示单选候选、选择理由、对其余候选批量拒绝 理由、可选备注和“确认商品并授权下单”按钮。表单服务端展开为逐候选 items。- 页面必须明确“仅授权创建待付款订单,不授权付款”;没有可授权候选、数据版本冲突 或已有不可修改授权时禁用提交并给出可操作状态。
- 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 与一次性授权放在同一事务;设备投递和 页面动作继续保持为后续独立权限层。 - 2026-07-28:完成 v8 migration、候选就绪原子状态迁移、Admin API/SSR 表单、
不可变授权快照、修订/幂等/并发保护和审计历史。
go test ./...、go test -race ./...、go vet ./...与根init.ps1通过。 - 2026-07-28:真实 Gin handler、嵌入模板和 CSS 在 Playwright
1440x900、390x844通过;均无横向溢出,主要控件高度至少 44px,控制台无错误。