# Round 68 工作计划:SAP Outbound P3 Evidence Envelope 日期:2026-08-03 ## 1. 背景与风险 `sap.sync.outbound` 会调用 SAP client `push_receipt`,属于外部副作用,但当前被标为 P2:单审批、无 execution grant、无批准载荷摘要、无世界指纹绑定。执行阶段重新预览,审批后版本/工单/数量变化可能被静默带入外部回写。 GitNexus 影响: - `apply_outbound`:HIGH,2 个直接依赖、24 个总影响。 - `stage_sap_sync`:HIGH,3 个直接依赖、33 个总影响,影响 handle_intent 流程。 - `execute_confirmed`:HIGH,17 个直接依赖、22 个总影响。 - `power_of`:LOW,4 个直接依赖、10 个总影响。 动态 action 分派会低估流程影响,本轮按 HIGH 门禁处理。 ## 2. 目标 1. 将 `sap.sync.outbound` 从 P2 升为 P3;inbound 保持 P2。 2. stage 时冻结版本、canonical outbound items、idempotency keys、payload digest、world fingerprint 和 evidence refs,并由 confirmation paramsHash 绑定。 3. 第二位不同审批人批准后,任何 SAP 调用之前校验:confirmId、execution grant、checkpoint、version、payload digest、world fingerprint、evidence refs、idempotency keys。 4. 校验通过后一次性消费 execution grant;重放失败。 5. 成功/拒绝/异常/部分失败均写 P3 审计,包含 approvers、confirmId、beforeSnapshot、evidenceRefs、payloadDigest、worldFingerprint 和 pushed/duplicate/failed idem keys。 6. 维持 Mock SAP 幂等;同 idem key 不产生第二次真实 receipt。 ## 3. 契约 ### Approval params `{direction:'outbound', versionId, versionNo, payloadDigest, worldFingerprint, idemKeys, evidenceRefs}` ### Evidence refs - `sap-outbound-version:` - `sap-outbound-payload:` - `sap-outbound-world:` ### World fingerprint 只包含审批相关切片:目标 flex schedule version、该版本非冻结 work orders、关联 flex orders 的数量/外部 AUFNR;剔除 audit/journal/技术时间。 ### 执行顺序 stage-time checkpoint + canonical approvalParams -> final execution recompute once -> validate current/checkpoint/approvalParams completely -> persist READY execution record -> consume grant with the exact stored approvalParams -> push the frozen approved items without rereading world -> per-item durable result -> final audit/save。任何 pre-push 失败调用次数必须为 0。 ## 4. 写边界 - W68-SAP:`server/aps_domain/sap_sync.py` - W68-WORKFLOW:`server/aps_domain/workflow.py`、`server/agent_core/harness.py` - W68-TEST:`tests/golden/test_sap_sync.py` 与新增 `tests/golden/test_sap_outbound_evidence.py` - 主 agent:集成、运行验证、文档、detect_changes、独立审计。 ## 5. 验收 - P3 双人 SOD:第一次审批零调用,第二个不同用户后才 push。 - approval 后版本/WO/订单数量/外部 AUFNR 任一漂移均拒绝,push=0。 - digest/action/params/grant/checkpoint/evidence 替换或缺失均拒绝。 - grant 重放拒绝;成功后相同 idem key 幂等。 - success/failed audit evidence envelope 字段齐全。 - direct apply 不携带 P3 envelope 必须拒绝。 - SAP focused、gateway/confirmation/evidence 相关 suites、full golden、真实 Mock SAP 运行、服务健康、现场 hash 不变。 ## 6. Out of scope - 真实 SAP RFC/PI 凭据、白名单、网络和客户回执 schema。 - 分布式 Saga 补偿/撤销 SAP receipt;部分失败仅留结构化审计和幂等重试证据。 - inbound P2、folder.schedule TOCTOU、Automation G4。 - commit/push/merge/publish。 ## 7. 首轮 Plan Audit 修订(权威覆盖前文歧义) 1. **Checkpoint 在 stage 时创建**:`stage_sap_sync` 在出确认卡前创建 approval-time checkpoint;`beforeSnapshot` 写入唯一 `approvalParams`。final confirm 只能读取并验证该 pairId,禁止重新创建。 2. **唯一 canonical approvalParams**:helper 生成并排序全部字段;`stage_confirmation` 原样存储,workflow/apply 原样透传,`consume_execution_grant` 使用同一对象。当前重算 projection 仅用于逐字段比较,不能替代批准对象。 3. **consume 前完成全部 world 读取和校验**:execution 使用已批准 items 的深拷贝;consume 后不再读取 world。任何漂移都在 grant 消费前拒绝。 4. **可恢复 execution/outbox**:`sapOutboundExecutions` 以 `confirmId + payloadDigest` 为身份;push 前持久化 READY/PENDING;grant consumed 后持久化 GRANT_CONSUMED;每个 idem key 逐条持久化 PUSHED/DUPLICATE/FAILED。部分失败写 FAILED/PARTIAL_FAILED 审计;恢复必须重新 P3 审批,并通过 `previousExecutionId` 关联前次 attempt,外部幂等键复用。 5. **纯 projection**:新增无 client 调用的 projection helper。完整候选 WO 稳定排序,fingerprint 覆盖 version id/no/status、候选总数、每个 WO 的 versionId/id/orderNo/flexOrderNo/operation/equipment/start/end/frozen、关联订单 quantity/AUFNR;排除 audit/journal/sapLinks/actor/time/client status。保持现有 50 条发送上限:先全量 canonical sort,再选前 50;fingerprint 同时包含 fullCandidateDigest/totalCount/limit,确保第 51 条漂移也被发现。 6. **Client 边界**:stage/preview 可调用只读 `status()`;安全门禁明确针对 `push_receipt`。纯 projection 与所有失败路径不得调用 push;client 实例化应位于 grant consume 后。 7. **HTTP/调用边界**:`apply_outbound` 的 P3 envelope 均为无默认值 keyword-only 必填;盘点全部 callers。preview/stage 路由永不 push,只有 `/api/actions/confirm` 最终 P3 分支可执行 push。 8. **可信审批身份**:requester/approvals 只取 `take_confirmation` 返回的审批存储 decision record,不能取请求 params;沿用现有策略:两名 approver userId 必须不同,requester 是否可参与由既有 RBAC/allowed 决定。审计记录 requester、两名 approver、顺序/角色、confirmId 和 grant consumption。