5.9 KiB
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. 目标
- 将
sap.sync.outbound从 P2 升为 P3;inbound 保持 P2。 - stage 时冻结版本、canonical outbound items、idempotency keys、payload digest、world fingerprint 和 evidence refs,并由 confirmation paramsHash 绑定。
- 第二位不同审批人批准后,任何 SAP 调用之前校验:confirmId、execution grant、checkpoint、version、payload digest、world fingerprint、evidence refs、idempotency keys。
- 校验通过后一次性消费 execution grant;重放失败。
- 成功/拒绝/异常/部分失败均写 P3 审计,包含 approvers、confirmId、beforeSnapshot、evidenceRefs、payloadDigest、worldFingerprint 和 pushed/duplicate/failed idem keys。
- 维持 Mock SAP 幂等;同 idem key 不产生第二次真实 receipt。
3. 契约
Approval params
{direction:'outbound', versionId, versionNo, payloadDigest, worldFingerprint, idemKeys, evidenceRefs}
Evidence refs
sap-outbound-version:<versionId>sap-outbound-payload:<sha256>sap-outbound-world:<sha256>
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 修订(权威覆盖前文歧义)
- Checkpoint 在 stage 时创建:
stage_sap_sync在出确认卡前创建 approval-time checkpoint;beforeSnapshot写入唯一approvalParams。final confirm 只能读取并验证该 pairId,禁止重新创建。 - 唯一 canonical approvalParams:helper 生成并排序全部字段;
stage_confirmation原样存储,workflow/apply 原样透传,consume_execution_grant使用同一对象。当前重算 projection 仅用于逐字段比较,不能替代批准对象。 - consume 前完成全部 world 读取和校验:execution 使用已批准 items 的深拷贝;consume 后不再读取 world。任何漂移都在 grant 消费前拒绝。
- 可恢复 execution/outbox:
sapOutboundExecutions以confirmId + payloadDigest为身份;push 前持久化 READY/PENDING;grant consumed 后持久化 GRANT_CONSUMED;每个 idem key 逐条持久化 PUSHED/DUPLICATE/FAILED。部分失败写 FAILED/PARTIAL_FAILED 审计;恢复必须重新 P3 审批,并通过previousExecutionId关联前次 attempt,外部幂等键复用。 - 纯 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 条漂移也被发现。
- Client 边界:stage/preview 可调用只读
status();安全门禁明确针对push_receipt。纯 projection 与所有失败路径不得调用 push;client 实例化应位于 grant consume 后。 - HTTP/调用边界:
apply_outbound的 P3 envelope 均为无默认值 keyword-only 必填;盘点全部 callers。preview/stage 路由永不 push,只有/api/actions/confirm最终 P3 分支可执行 push。 - 可信审批身份:requester/approvals 只取
take_confirmation返回的审批存储 decision record,不能取请求 params;沿用现有策略:两名 approver userId 必须不同,requester 是否可参与由既有 RBAC/allowed 决定。审计记录 requester、两名 approver、顺序/角色、confirmId 和 grant consumption。