aps-agent/docs/round-67-approval-migration...

4.7 KiB
Raw Permalink Blame History

Round 67 工作计划:审批迁移 Fail-Closed 与 Grant Digest 归一化

日期:2026-08-03

1. 方向选择

Round 66 已完成并通过独立复审。并行候选审计发现:

  • 审批文件迁移把原始 grant token 直接写入数据库 token_hash,迁移后 P3 grant 无法被数据库后端消费;
  • 损坏 JSON/非法结构会被当成空审批源并报告迁移成功;
  • 数据库 TTL 仍依赖应用主机时钟,留到后续 R67-B2;
  • SAP outbound P3 evidence envelope、folder.schedule TOCTOU 与 Automation G4 payload 绑定列入后续 P0。

本轮选择 R67-B1,因为两个 CRITICAL 缺陷可在本地 SQLite 完整复现和闭环,且写边界最小。

2. GitNexus 门禁

  • load_file_store:LOW,1 个直接调用、6 个总影响,无执行流。
  • migrate_file_to_db:MEDIUM,5 个直接测试调用,无执行流。
  • 不修改审批 API、Harness、数据库 consume/TTL 或真实 MySQL 部署路径。

3. 目标

  1. 迁移 grant 时只存 token_digest(raw_token),不持久化原始 token。
  2. 文件不存在维持空源语义;文件存在但 JSON/schema/记录损坏必须明确失败。
  3. 所有源记录先完成规范化与交叉引用预检;grant 缺 pending request 时依据 grant/history 重建终态 APPROVED request,满足数据库外键。
  4. 全部请求、grant 修复和事件在一个 SQLAlchemy Session 事务中 flush/commit;后段异常整体回滚。
  5. 幂等比较拆分为不可变身份字段与单调状态:允许数据库端合法前进到 APPROVED/CONSUMED/EXPIRED,禁止状态回退或覆盖。
  6. 同时预检 expected digest、历史 raw-token 主键与 confirm_id;一致 legacy 行在事务内原子修复为 digest,冲突则 fail-closed,禁止对 DB 中已知 digest 再哈希。
  7. history 使用完整 canonical event digest 去重;同秒同状态但 approver/note/payload 不同的事件必须保留。
  8. 迁移要求 APS_APPROVAL_MIGRATION_QUIESCED=1,并持有与文件后端相同的 .lock 到事务提交;读取、flush 后复核 source SHA-256 一致,再 commit。
  9. 迁移后 active P3 grant 可成功消费一次,重放失败。

4. 写边界

  • 业务实现:server/agent_core/approval_migrate.py
  • 黄金测试:tests/golden/test_approval_migration.py
  • 文档:本计划、并行计划、状态/运行证据、plan/matrix/changelog

5. Out of scope

  • 数据库权威时钟、TTL/CAS 跨主机语义(R67-B2)。
  • 真实 MySQL 多主机、网络断连/死锁恢复。
  • SAP outbound、folder.schedule、Automation G4 evidence envelope。
  • 提交、推送、合并、发布或修改现场审批文件。

6. 验收

  • 文件后端 active P3 grant -> 迁移 -> 数据库后端 consume 一次成功、第二次失败。
  • DB 仅包含 64 位 SHA-256 digest,不包含 raw token。
  • 损坏 JSON、错误顶层 schema、非法 pending/grant/history 均失败且三张审批表不变。
  • 同键不同不可变身份字段报冲突;数据库端合法状态前进不误报冲突,状态回退不覆盖。
  • legacy raw-token 行一致时原子修复,不一致时 fail-closed。
  • history canonical digest 保留合法近似事件并保证重跑幂等。
  • 后段事件构造/flush 故障注入后,三表及迁移前目标数据整体不变。
  • 未设置 quiesced 明确拒绝;锁持有期间 source digest 漂移则回滚。
  • dry-run、幂等迁移、缺失文件原有行为保持。
  • focused、相关 approval suites、全量黄金、Node/Web(如受影响)、真实临时数据库运行、diff-check、detect_changes 和独立审计通过。

7. 数据保护

所有测试使用临时审批文件和临时 SQLite;fixture 显式设置 quiesced。不得读取后写回 server/data/approvals.json 或现场 master.db。验收前后记录现场审批文件 hash 与 server/data/.env Git 状态。

8. 首轮 Plan Audit 修订

首轮 PLAN AUDIT: FAIL 的六项阻断已纳入:终态 request 重建、单调状态幂等、legacy raw-token 修复/冲突、canonical event digest、单事务后段回滚、quiesced + 同锁稳定快照。真实跨主机停写编排仍是部署验收,不在本地 SQLite 冒充完成。

9. 执行结果

  • 首轮计划审计 6 项 blocking 已修订,最终 PLAN AUDIT: PASS。
  • 并行 worker 超时失效后由主 agent 接管其已落入工作区的代码/测试并完成集成。
  • 初始 focused 3 failures 已修复;最终 migration 29、approval related 74、full golden 1053 全绿。
  • 真实临时 SQLite 迁移/consume/corrupt fail-closed 通过;现场 approvals/world hashes 不变。
  • 首轮代码审计发现 legacy payload 身份未校验,补 request/grant payload immutable gate 与正负回归后最终 AUDIT: PASS。