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

155 lines
9.3 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-206
title: App 接入领取、有限离线执行和进度
phase: 2
deps:
- T-202
- T-205
status: DONE
created: 2026-07-27
context_ref: 45d1436
work_branch: main
write_paths:
- README.md
- android-buyer/**
- backend-api/**
- docs/00-ai-start-here.md
- docs/02-requirements.md
- docs/03-tech-stack.md
- docs/04-architecture.md
- docs/05-coding-rules.md
- docs/07-user-stories.md
- docs/08-interaction-checklist.md
- docs/api.md
- docs/current-state.md
- docs/routes.md
- docs/tasks/T-206.md
- progress.md
---
## 问题 / 背景
T-205 已实现 BUYER + 设备联合鉴权、readiness heartbeat、原子 claim、任务参考图、
start、90 秒运行租约、release 和取消确认,但 Android 仍只消费本地 fixture。
管理员创建的 `PENDING` 任务无法在手机领取。
90 秒运行租约要求手机持续连接管理后端,与“手机独立完成采购,只从管理后端领取并
回传结果”的目标冲突。T-206 需要接入后端任务,同时把运行租约扩展为有限离线执行
授权;后台失联不能导致任务被另一台设备重复执行,也不能让手机无限离线运行。
Roubao 原有独立模式和端上 VLM 设置必须保留。后台任务不得下发或覆盖 VLM provider、
Base URL、model、prompt 或 API Key。
## 关联需求与交互
- 功能:F-003、F-007、F-009。
- 用户故事:US-003、US-006、US-007、US-009。
- 交互:IX-004、IX-005、IX-006、IX-008、IX-010。
- 架构/API:`HttpTaskSource`、设备联合身份、claim/运行租约、有限离线执行、前台服务
和本地 outbox。
## 已定合约
1. 管理后端只负责身份、任务分配、状态、取消和结果审计;App 独立负责 VLM、拼多多
自动化、人工确认、本地状态和待上传结果。
2. BUYER 登录同时提交预授权 device ID/secret;access token、device secret、
claim token 和幂等 key 使用 Android Keystore 支撑的加密存储,不进入 SavedState、
普通 SharedPreferences、崩溃报告或日志。
3. App 每次领取前发送设备 heartbeat。未就绪、已有活跃任务或服务端离线时不能领取;
用户点击后才生成并持久化 claim token 与幂等 key。
4. `CLAIMED` 默认租约仍为 10 分钟。start 后默认运行授权从 T-205 的 90 秒调整为
30 分钟,可在 5 至 120 分钟范围配置;成功 heartbeat 使用服务端时间滑动续期。
5. App 计划每 30 秒 best-effort heartbeat,以同步步骤和取消请求。heartbeat 失败时
可在服务端下发的 `execution_expires_at` 前继续,不能因为短时断网停止或生成新
execution;到期仍未恢复连接时必须在安全检查点停止自动化。
6. `RUNNING/WAITING_CONFIRMATION` 无论授权是否过期都不自动回队列。重新分配必须先
由人员结束旧 execution,避免两台手机同时操作同一任务。
7. 管理取消在 App 离线期间不能保证即时生效。恢复连接后 App 必须先 heartbeat,
收到取消标志便在下一个安全检查点停止并 `cancel-ack`,不得先继续页面动作。
8. App 在授权内完成但暂时无法上传时,把结果、事件和证据引用写入加密 outbox。
T-207 允许原设备在授权过期后补交终态结果,并标记
`received_after_execution_expiry=true`;过期后不得继续自动化。
9. App 重启先恢复加密本地 execution,再与服务端核对。无法证明任务归属、授权时间
或本地步骤安全时停止并等待人工处理,不领取第二条任务。
10. Roubao 独立模式与后台任务共享现有本地 workflow/VLM 能力,但任务源和同步边界
独立。后台任务不能携带 provider 配置,也不能触发 App 修改本地模型设置。
11. T-206 验证登录、领取、预览、start、前台步骤、有限离线、恢复、release 和取消;
真实候选/截图/事件/终态回传由 T-207 完成。
## 方案
1. 增加严格的后端地址、认证 client、Keystore-backed secret store、持久 task state
和稳定错误映射。Release 后端地址只接受 HTTPS;开发证书路径与生产隔离。
2. 实现 `HttpTaskSource`,把 claim 和 task-scoped 参考图规范化为现有领域输入;
workflow/AI/automation 不判断任务来自 fixture 还是 HTTP。
3. 接入登录、任务主页、预览、运行和恢复状态;重复点击、空队列、登录失效、授权
到期和服务端冲突均使用已确认页面反馈。
4. 扩展后端运行租约配置及 start/heartbeat 响应,显式返回
`execution_expires_at`;保持 RUNNING 不自动回收的 T-205 安全规则。
5. 前台服务持有 execution,best-effort heartbeat 并使用服务端时间偏移判断离线
截止点。网络恢复后先同步取消/归属,再恢复允许的步骤。
6. 增加加密本地状态/outbox 基础接口;T-206 只验证恢复和安全停止,不实现 T-207
的完整结果 payload。
## 验收要点
- [x] 预授权 BUYER 在真机登录成功;错误账号、错误设备、禁用和过期均被拒绝,秘密
不出现在日志和普通存储。
- [x] 真机 heartbeat 后点击“获取任务”只领取管理 Web 创建的一条 `PENDING` 任务,
显示标题、SKU、数量、描述和参考图;无任务显示空状态。
- [x] 重复点击和模拟响应丢失不会重复领取;App 重启能恢复同一 `CLAIMED`/RUNNING。
- [x] start 返回默认约 30 分钟 `execution_expires_at`;断开管理后端超过 90 秒后,
受控 fake workflow 仍能在授权内继续,任务不会分配给第二台设备。
- [x] 离线授权到期后 App 安全停止;恢复网络先同步服务端状态,不擅自续作。
- [x] 管理取消在在线时及时处理;离线时恢复连接后的首个同步点处理并确认。
- [x] Roubao 原独立模式、端上 provider 选择和本地 fixture 探针回归通过;后台任务
不下发、覆盖或读取来自任务内容的 provider 配置。
- [x] Android/后端测试、根 `init.ps1` 和 OnePlus PKG110 Android 16 真机 smoke
通过,验证过程中不提交订单。
## 边界
- 不实现候选、截图、事件、complete/fail 和人工理由回传;属于 T-207。
- 不把模型调用代理到管理后端,不实现后台 provider 配置、推送、自动领取或多任务。
- 不承诺离线期间即时取消;不允许离线授权无限延长、自动下单或支付。
- 不提交真实账号、设备 secret、VLM Key、订单或证据。
## 执行记录
### 2026-07-27:任务开始
- 基于提交 `9e698c1` 开始,工作区干净;T-202/T-205 依赖均已完成。
- codebase-memory MCP 本轮未暴露 graph 工具,按仓库规则回退到 `rg` 和定点读取。
- 开工基线 `.\init.ps1` 通过:Android Debug/Release 测试与 Debug APK 构建成功,
Go 全包测试、vet、gofmt 检查和 API/migration/authctl 构建成功。
- 先固定并实现后端默认 30 分钟运行授权和 `execution_expires_at`,再让 Android
登录、领取、恢复和前台服务依赖该契约。
### 2026-07-27:实现与验证完成
- 后端默认运行授权改为 30 分钟、允许 5-120 分钟;start/task heartbeat 的
`execution` 显式返回 `execution_expires_at`。授权过期后原设备 heartbeat 只同步
状态、不延长旧授权;匹配原 execution/claim 的取消确认仍可完成,RUNNING 不回队列。
- Android 新增独立“任务”入口、严格 backend 地址策略、无明文 fallback 的
`ProcurementSecureStore`、`ProcurementApiClient`、`HttpTaskSource`、参考图
MIME/JPEG/20 MiB/SHA-256 校验和加密 task/execution 恢复。密码不存储;设备
secret、access/claim token 和各操作幂等 key 只进加密存储。
- 前台服务每 30 秒 best-effort heartbeat;使用保守的服务端时钟偏移和持久
`SAFE_STOPPED` 判断离线截止。登录 token 过期时只允许同后台、同 BUYER、同设备
重新认证;过期恢复同步不会自动继续外部动作。
- 领取前先持久化 256 bit claim token/独立幂等 key,响应不确定时复用;参考图和
task 快照落盘后才可预览。start 增加二次确认和至少 2 秒稳定预览门禁,避免页面
重组或自动化注入导致误启动;T-206 受控步骤不打开拼多多、不调用 VLM、不提交订单。
- MockWebServer 覆盖 Android 登录、幂等领单、参考图 hash/同源限制和 start 到期契约;
端点策略与服务端时钟/预览门禁有纯 Kotlin 单测。最终根 `.\init.ps1` 通过:
Android 32 份报告、184 次测试零失败,Go 含子测试 193 次通过,vet、gofmt 和
API/migration/authctl Windows 构建成功。
- PKG110 Android 16 真机使用临时 18080 后端、一次性 DPAPI 保护凭证和脱敏任务
完成:BUYER 登录、readiness、领取、字段/参考图预览、start、前台通知、95 秒
后端断线、恢复滑动续期、管理取消/`cancel-ack`、release 和进程重启恢复。断线
后仍为同一 `CONTROLLED_WORKFLOW`,倒计时从约 29:38 到 27:54;重连恢复到约
29:41。验证未打开拼多多、未调用 VLM、未提交订单。
- 最终 Debug APK 已覆盖安装;一次性 API/数据库/DPAPI 凭证和 App 临时后台登录
状态已清理,Roubao 其他设置保留,采购无障碍恢复启用。T-207 接入真实端上
VLM/候选并实现事件、证据、结果和完整加密 outbox。