diff --git a/docs/00-ai-start-here.md b/docs/00-ai-start-here.md index 23e47a2..7b6daaa 100644 --- a/docs/00-ai-start-here.md +++ b/docs/00-ai-start-here.md @@ -61,8 +61,8 @@ T-205 原子领取/租约状态机、T-206 Android 登录/有限离线、T-207 规格组合/价格核验均已完成。T-208 的原始候选观测、模型评估、确定性推荐、逐候选 结构化人工理由和修订历史也已完成。T-214 商品持久身份和重新定位指纹、T-215 Admin 候选确认、不可变待投递授权、T-216 设备命令可靠投递及 T-217 已授权商品 -重新定位与订单 dry-run、T-218 单次订单提交围栏和订单回读均已完成;下一项是 -T-219 Admin 待付款提醒与端到端验收。 +重新定位与订单 dry-run、T-218 单次订单提交围栏和订单回读均已完成;T-219 Admin +待付款提醒与端到端验收正在开发。 不得直接把候选链接或列表 ordinal 当成授权。 手机从管理后端领取任务并回传结果,VLM、拼多多自动化和人工确认在 App 本地完成。 T-206 增加有限离线执行;T-207 已复用 Roubao 端上 OpenAI 兼容适配器并加密本地 Key。 diff --git a/docs/02-requirements.md b/docs/02-requirements.md index 3403772..d901dd7 100644 --- a/docs/02-requirements.md +++ b/docs/02-requirements.md @@ -244,3 +244,5 @@ T-004 已固定首版规则:推荐私有目录为被 Git 忽略的 `private-fi - 创建待付款订单前必须在 T-215 至 T-218 固定 SKU、数量、价格、地址可见性、运费/ 优惠不确定性、一次性提交和订单列表对账规则;不满足时安全停止。 - 自动支付明确排除;人员必须在拼多多订单列表复核后付款。 +- Admin 只有在唯一订单对账成功后才显示订单号、下单时间和“待人工确认付款”;对账 + 中或人工核对状态不得冒充成功,也不得提供重试提交或付款入口。 diff --git a/docs/04-architecture.md b/docs/04-architecture.md index 0056240..f4a0102 100644 --- a/docs/04-architecture.md +++ b/docs/04-architecture.md @@ -663,6 +663,15 @@ submission fence 是 exactly-once 安全边界,不是“点击成功”回执 只进入 App 加密状态与鉴权后端,不进入普通日志或模型请求。T-219 读取该对账记录展示 待付款提醒,所有支付仍由采购人员在拼多多完成。 +### 待付款提醒(T-219) + +Admin 任务详情从同一 `TaskDetail` 聚合读取 v11 submission,不按浏览器传入的订单号 +查询。`FENCED`、`MANUAL_REVIEW` 和 `RECONCILED` 分别映射为正在对账、人工对账和 +待人工确认付款;只有最后一种展示订单号、平台时间、金额和对账证据。受控截图继续走 +现有鉴权 evidence 路由,订单号不进入 URL。Roubao 从本地加密 submission 展示同一 +待付款摘要,不增加支付导航。旧 `SUCCEEDED` 的“未提交订单”文案只有在不存在 +reconciled submission 时保留。 + 人工理由使用版本化 allowlist。接受或拒绝至少有一个理由且指定主要理由; `OTHER` 才要求 4-200 字备注。拒绝推荐后改选必须同时产生一条原推荐项负标签和一条 替代项正标签;全部无匹配时每个曝光候选都有负标签。人工修正追加新 review 并引用 diff --git a/docs/06-tasks.md b/docs/06-tasks.md index 593dff8..fcf3492 100644 --- a/docs/06-tasks.md +++ b/docs/06-tasks.md @@ -51,7 +51,7 @@ | T-216 | 设备下单命令投递、确认与恢复 | T-215 | App 主动拉取;先加密落盘再 ACK;断网/重启重放同一授权且不执行拼多多动作 | | T-217 | 已授权商品重新定位与订单 dry-run | T-216 | 重新核对持久指纹并唯一选择 SKU/数量,停在最终提交前 | | T-218 | 单次订单提交与订单回读 | T-217 | 一次性提交后从订单列表读取订单号/时间并对账,不支付 | -| T-219 | Admin 待付款提醒与端到端验收 | T-218 | 展示可核对订单并提醒采购员去拼多多确认付款 | +| T-219 | Admin 待付款提醒与端到端验收 | T-218 | 三态展示可核对订单并提醒采购员去拼多多确认付款;不提供支付入口 | ## Phase 3:端到端验证 diff --git a/docs/08-interaction-checklist.md b/docs/08-interaction-checklist.md index 79ddb38..c64f61c 100644 --- a/docs/08-interaction-checklist.md +++ b/docs/08-interaction-checklist.md @@ -17,7 +17,7 @@ | IX-008 | US-006 | App/管理端错误状态 | 自动失败、取消、重试上传 | 显示结构化原因和恢复动作 | P0 | 已定 | | IX-009 | US-008 | App 候选理由/管理端决策详情 | 接受、拒绝、改选或修正 | 保存逐候选结构化人工标签 | P1 | T-208 已实现 | | IX-010 | US-009 | App 独立执行设置/同步状态 | 配置模式、离线执行或补报 | 授权内独立执行并可审计同步 | P0 | T-206 离线控制已实现,结果补报待 T-207 | -| IX-011 | US-010 | Admin 候选授权/App 订单执行 | 选择候选并授权、设备领取执行 | 创建一笔可对账的待付款订单并提醒人工付款 | P0 | T-215 至 T-218 已完成;T-219 待实现 | +| IX-011 | US-010 | Admin 候选授权/App 订单执行 | 选择候选并授权、设备领取执行 | 创建一笔可对账的待付款订单并提醒人工付款 | P0 | T-215 至 T-218 已完成;T-219 开发中 | ## IX-001 管理 Web 登录 diff --git a/docs/api.md b/docs/api.md index e71172c..97bfccb 100644 --- a/docs/api.md +++ b/docs/api.md @@ -346,6 +346,13 @@ execution/generation、submission、期望快照、证据归属和幂等键; 三个接口都不接收支付方式、支付密码或付款结果,也不授权客户端点击付款控件。 +Admin `GET /api/v1/tasks/{task_id}` 在 T-219 增加 `order_submissions` 数组。数组按 +`fenced_at`、ID 升序;包含 submission/authorization/dry-run/execution 身份、状态、 +预期标题/SKU/数量/单价/总额和围栏时间。`RECONCILED` 项另外返回订单号、平台下单 +时间、`PENDING_PAYMENT`、对账 evidence asset/hash 和对账时间; +`MANUAL_REVIEW` 返回受限 reason code。响应必须 `Cache-Control: no-store`,订单号 +不进入任何资源 URL。无记录时返回 `[]`,不能省略字段或返回 `null`。 + ## 设备与领取 ### `POST /api/v1/devices/heartbeat` diff --git a/docs/current-state.md b/docs/current-state.md index eba235d..a27a04c 100644 --- a/docs/current-state.md +++ b/docs/current-state.md @@ -5,8 +5,8 @@ ## 当前快照 - 日期:2026-07-28 -- 阶段:T-218 单次订单提交与订单回读已完成;下一项 T-219 -- Git:当前分支为 `main`;T-001 至 T-004、T-101 至 T-104、T-201 至 T-217 +- 阶段:T-219 Admin 待付款提醒与端到端验收已领取,合约冻结中 +- Git:当前分支为 `main`;T-001 至 T-004、T-101 至 T-104、T-201 至 T-218 均按文档提交、实现提交的顺序纳入历史 - 生产代码:`android-buyer/` 已接入 Roubao Android 源码 - Android:固定 `main@c8a6d7f03422eb01744b01f3ee77bf7757741f7e`;MIT 许可证已保留 @@ -108,7 +108,7 @@ 已用 CLI 真实导入并逐字段/图片哈希验证,生成物位于被忽略的 `.local/` - 标准启动路径:`$env:RUN_START_COMMAND="1"; .\init.ps1` - 标准验证路径:`.\init.ps1` -- 当前 blocker:T-219 无代码阻塞;当前真机确认页缺少已配置收货地址且显示 +- 当前 blocker:T-219 实现无代码阻塞;当前真机确认页缺少已配置收货地址且显示 “立即支付/先用后付”,T-218 已按合约证明不创建围栏、不点击。不能为测试自动添加 地址或跨过付款边界。真实 VLM 服务地址、模型、 设备级测试凭证、成本上限和数据留存尚未确认;当前只支持单 SKU/JPEG;候选探针 @@ -157,8 +157,8 @@ ## 任务摘要 - 已完成:T-001 至 T-004、T-101 至 T-104、T-201 至 T-218。 -- 进行中:无。 -- 下一步:T-219 Admin 待付款提醒与端到端验收。 +- 进行中:T-219 Admin 待付款提醒与端到端验收。 +- 下一步:完成 T-219 后进入 T-301 P0 UI 完整交互验收。 ## 当前可运行内容 diff --git a/docs/routes.md b/docs/routes.md index 4bea7f6..9c67c20 100644 --- a/docs/routes.md +++ b/docs/routes.md @@ -10,7 +10,7 @@ T-202 的离线 P0 页面入口见[原型索引](design/index.html)。原型仅 | `/login` | 管理登录 | 建立服务端管理会话 | US-007 | IX-001 | | `/tasks` | 任务列表 | 查看状态、筛选并进入详情 | US-002 | IX-003 | | `/tasks/new` | 新建任务 | 提交图片和采购约束 | US-001 | IX-002 | -| `/tasks/{id}` | 任务详情 | 查看输入/候选/证据,并按 candidate key 创建待投递下单授权 | US-002、US-006、US-010 | IX-003、IX-008、IX-011 | +| `/tasks/{id}` | 任务详情 | 查看输入/候选/证据、创建下单授权,并展示对账中/人工对账/待人工付款状态 | US-002、US-006、US-010 | IX-003、IX-008、IX-011 | MVP 登录后默认进入 `/tasks`。未登录访问受保护页面时跳转 `/login` 并携带安全的 站内返回路径;只接受 `/tasks` 及其本站子路径,拒绝绝对 URL、`//` 和反斜杠。 @@ -84,6 +84,7 @@ T-207 的 events/candidates/complete/fail 接受原设备对授权内已产生 | `TaskRequirementSummary` | Android/Web | 展示原始输入和 AI 派生信息,视觉上明确区分 | | `CandidateReview` | Android/Web | 展示候选与硬约束校验,不执行自动化动作 | | `ExecutionController` | Android | UI 命令入口,委托 workflow,不直接调用 Accessibility | +| `PendingPaymentSummary` | 管理 Web/App | 只读展示对账订单与人工付款提醒,不提供付款或重提动作 | 具体状态反馈以[交互清单](08-interaction-checklist.md)为准,组件命名可在接入真实框架后 调整并同步本文。 diff --git a/docs/tasks/T-219.md b/docs/tasks/T-219.md new file mode 100644 index 0000000..c627c91 --- /dev/null +++ b/docs/tasks/T-219.md @@ -0,0 +1,127 @@ +--- +id: T-219 +title: Admin 待付款提醒与端到端验收 +phase: 2 +deps: + - T-218 +status: DOING +created: 2026-07-28 +context_ref: a77d8be +work_branch: null +write_paths: + - docs/tasks/T-219.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/internal/domain/** + - backend-api/internal/repository/sqlite/** + - backend-api/internal/transport/httpapi/** + - backend-api/internal/transport/webui/** + - android-buyer/app/src/main/** + - android-buyer/app/src/test/** +--- + +## 问题 / 背景 + +T-218 已把唯一对账成功的待付款订单保存到 `order_submissions`,但 Admin 任务详情尚未 +读取这张表;成功任务仍沿用旧文案“验证完成,未提交订单”。采购员因此无法从后台 +区分“未提交”“提交后正在对账”“需要人工对账”和“已有待付款订单”。 + +本任务把 T-215 至 T-218 的结果收敛到一个可核对的 Admin 终点,并在 Roubao 端显示 +同一结果。提醒只要求人员打开拼多多订单列表复核并付款,不提供支付跳转、自动付款或 +任何支付凭证处理。 + +## 关联需求与交互 + +- `FR-22`:一个授权最多创建一个订单,未知结果禁止重提。 +- `FR-23`:唯一回读后 Admin 展示待付款提醒,付款由人员完成。 +- `US-010` / `IX-011`:展示订单号、下单时间、SKU、数量、金额和证据。 + +## 冻结合约 + +### 详情读取与鉴权 + +1. `TaskDetail` 在原任务、execution、report 和 authorization 之外读取该任务全部 + `order_submissions`,按 `fenced_at ASC, id ASC` 稳定排序;不存在时返回空数组。 +2. repository 必须同时限定 task creator subject,不能先按 submission ID 读取再由 + handler 判断。Admin JSON 与 SSR 页面继续使用现有 ADMIN session/bearer 鉴权。 +3. `GET /api/v1/tasks/{task_id}` 新增 `order_submissions`。每项包含围栏状态、预期 + 标题/SKU/数量/单价/总额、围栏时间;仅 `RECONCILED` 包含订单号、平台下单时间、 + `PENDING_PAYMENT` 和对账 evidence 引用。 +4. 响应使用 `Cache-Control: no-store`。订单号不能进入 URL、页面标题、日志、事件 + message、VLM 请求、埋点或截图文件名;404/403 不泄露订单是否存在。 + +### Admin 状态与提醒 + +1. `FENCED` 显示“订单提交结果正在对账,禁止重复提交”,不显示成功或付款提醒。 +2. `MANUAL_REVIEW` 显示“需要人工核对订单,仍禁止重复提交”,同时显示稳定中文理由; + 不提供“重试提交”操作。 +3. `RECONCILED` 在任务详情标题之后、原始要求之前显示醒目的 + “待人工确认付款”状态区,并展示完整订单号、平台下单时间、待付款状态、已授权 + 商品标题、SKU、数量、单价、总额和受控对账截图。 +4. 旧的 `SUCCEEDED -> 验证完成,未提交订单` 只适用于没有 reconciled submission + 且 `execution_outcome.order_submitted=false` 的历史流程;有 reconciled submission + 时不得出现该文案。 +5. 提醒文案固定为“请采购员打开拼多多订单列表,核对商品、规格、数量和金额后人工 + 付款”。页面不提供付款按钮、深链、二维码、自动跳转或可执行的订单操作。 +6. 状态不能只靠颜色;订单字段用 `dl`,平台时间使用带 RFC3339 `datetime` 的 + `time` 元素,截图有可访问替代文本。360 px、390 px 和 1440 px 宽度不横向溢出。 + +### Roubao 终态 + +1. 本地 `RECONCILED` 使用 Keystore-backed submission 展示订单号、平台下单时间、 + 待付款状态和核验总额,并提示“请到拼多多订单列表人工确认付款”。 +2. `MANUAL_REVIEW` 继续显示原因并明确禁止重新提交;App 不增加付款按钮或自动打开 + 支付页。 +3. 订单号只在已有鉴权会话和当前加密任务状态中展示;清理任务时随 submission 一起 + 清除。 + +### 端到端验收 + +1. 自动化 fixture 覆盖 + `Admin create -> device claim/start -> candidates -> Admin authorize -> + command ACK -> dry-run READY -> submission FENCED -> RECONCILED -> + Admin API/Web reminder`,并断言同一 authorization 只有一个 submission。 +2. 同一 fixture 验证 `FENCED`、`MANUAL_REVIEW` 和 `RECONCILED` 三种 SSR 文案, + `RECONCILED` 不再显示“未提交订单”,所有页面都没有支付表单或付款链接。 +3. Playwright 在桌面和两种手机宽度检查真实 SSR 页面:无脚本错误、横向溢出或文字/ + 控件重叠,对账截图请求成功且受 ADMIN session 保护。 +4. 生产真机没有受控收货地址时继续沿用 T-218 的 fail-closed 结果,不为制造演示订单 + 添加地址或跨过“立即支付/先用后付”边界;端到端成功态使用隔离测试数据库。 + +## 数据与 API + +- 不新增 migration;复用 v11 `order_submissions` 和 + `reconciliation_evidence_asset_id`。 +- `domain.TaskDetail.OrderSubmissions []OrderSubmission` 是读取模型。 +- Admin `GET /api/v1/tasks/{task_id}` 增加 `order_submissions` 数组。 +- SSR `Task` 增加只读 `OrderSubmissions`,证据 URL 使用现有 task/execution-scoped + 鉴权资源路由;不建立以订单号为参数的新路由。 + +## 验收要点 + +- [ ] repository 按任务和 Admin subject 读取稳定排序的 submission,空值不报错。 +- [ ] Admin API 仅鉴权返回对账字段且 `no-store`,订单号不进 URL/日志。 +- [ ] SSR 正确区分 FENCED、MANUAL_REVIEW、RECONCILED 和历史未下单 SUCCEEDED。 +- [ ] RECONCILED 展示订单号、时间、SKU、数量、金额、截图及人工付款提醒。 +- [ ] Web/App 均没有付款按钮、重试提交或自动支付动作。 +- [ ] Go test/race/vet、Android test/Debug/Release、根验证与响应式 Playwright 通过。 +- [ ] 最小跨端 fixture 证明唯一 submission 和 Admin 提醒闭环。 + +## 边界 + +- 不修改 T-218 单次提交和对账状态机,不创建第二个订单。 +- 不读取支付结果,不把任务自动改成“已付款/采购完成”。 +- 不实现付款跳转、支付方式选择、自动付款、验证码或风控绕过。 +- 不因生产真机缺少安全地址而伪造成功态。 + +## 执行记录 + +- 2026-07-28:T-218 实现提交 `a77d8be` 后领取。冻结 Admin 三态展示、鉴权订单字段、 + 历史成功文案兼容、Roubao 终态提醒和隔离数据库端到端验收。