Skip to content

Security: evilstar9527/delivery-loop

Security

docs/Security.md

Security

可替换 Agent executor 边界

  • Executor profile、route、release和capabilities只能由控制面可信配置/D1快照选择;Task、PRD、 Agent输出、Queue payload和provider assertion均不能选择provider、镜像、网络策略或fallback。
  • 通用插件只能做幂等start/observe/cancel/identity/evidence。审批、scope、quota、retry、Attempt lease/generation/CAS与D1 mutation属于控制面;插件返回的handle/fact必须匹配冻结的execution、 Attempt、generation、role、repository、profile和release digest,否则在持久化前拒绝。
  • profile与handle是Secret-free持久对象,配置key拒绝secret/token/password/credential/key等形状; provider身份载荷是瞬时credential,不得进入handle、outbox、Evidence、日志或错误。
  • 同一Attempt冻结provider后不得因超时、429或启动结果不确定而切换provider。重试必须由原插件按 stable execution identity先reconcile;切换GitHub/Cloudflare/E2B只能创建控制面明确授权的新Attempt。
  • provider observation必须反向绑定immutable execution handle,facts仅允许有界Secret-free string map; D1只保存canonical digest和白名单facts,不保存raw provider response。external timestamp与独立sequence 双重单调,running/terminal不可回退;provider terminal不能替代Runner result、Evidence或Attempt状态机。
  • observe transport失败不等于execution失败。控制面只持久固定错误分类、次数与有界退避,成功后清除;不得把 raw provider body/cause放入D1或日志,也不得因连续HTTP失败切换provider。真正失联由既有Attempt lease/ heartbeat fence裁决并先撤销grant,再以唯一cancel intent清理旧provider。cancel不具备创建replacement的权限。
  • Cloudflare Sandbox目标边界为独立Executor Worker、固定digest镜像、ephemeral workspace与 default-deny egress。真实repo-write credential不进入work sandbox:executor work token在broker任何approval、 D1 issuance或GitHub provider effect前固定policy_denied,finalization/revocation另有二次identity fence。 work只提交D1不含正文的immutable patch引用/digest,publisher以独立role/profile/execution消费;上传body无branch、 profile或provider选择权,target branch从Attempt/review lineage复算,publisher profile只取active role route。 patch/publication/execution/outbox四表调度冲突必须事务回滚,publisher重算digest不一致时不得记录published。 patch正文只进专用私有R2,ID由work execution稳定 派生;上传前后重验executor token/lease,R2 metadata/body回读及publisher下载各自重算digest。容器不能选择任意key, work identity和其他publisher不能下载,patch bucket不进长期backup。publisher从clean exact checkout应用冻结patch, 独立authority只接受GitHub App短期credential;PAT/provider-reference在provider effect前拒绝。authority与exact publication/execution/approval/repository/branch/generation绑定,D1只保存digest和AES-GCM密文;明文不进argv、URL、日志、 patch或Evidence。read path的callback与receive-pack的Basic token不能互换,控制面解析ref command并拒绝其他branch、 delete、多ref与错误old SHA。push后只有exact head上的targeted+required Evidence完整通过才可完成,完成先撤销token且重放 收敛。上述均为本地契约,不能冒充Worker/镜像/identity/egress已部署或真实GitHub push事实。
  • executor work Runner没有“临时借用”Git write credential的兼容路径:身份分支在构造broker request/Git writer前切换到 credential-free lane。它只保留detached frozen HEAD上的未提交改动,并从raw Git mode/path与base blob生成content-only proposal;delete/rename/mode change/symlink/binary/protected path/Secret均不能上传。setup须保持clean,targeted/required verification每步前后proposal digest不变才继续;测试若生成或改写文件即fail-closed。只有全部本地命令exit 0才使用 当前短token/version/generation上传,且这次验证不冒充publisher提交后的authoritative Evidence。
  • Executor Worker先以独立control token鉴权,未经认证时不解析body;请求最多64 KiB且strict schema没有 metadata/credential扩展口。Docker基础镜像按manifest digest固定,不使用latest;依赖按lockfile安装并 在build中核对pnpm/tsx/Codex版本。runtime image digest必须由实际构建/registry事实注入,缺失则503,不能 用Dockerfile digest或占位值冒充。
  • Sandbox设enableInternet=false且空allowlist。唯一control-plane outbound handler重验request-bound HTTPS origin和exact Attempt path并删除cookie/proxy authorization;callback token只覆盖identity exchange和 publisher patch GET,普通Attempt请求保留短grant token,否则真实heartbeat/context/result会失效。所有请求都覆盖 容器伪造的identity header并注入ctx.containerId/executionId。grant缺失时镜像入口固定失败,不能临时把GitHub OIDC、 PAT、模型key或Tool Bridge SK塞进container env绕过。
  • Repository checkout不开放GitHub公网egress,也不把installation/PAT放进container。work Runner只以短Attempt token访问固定control-plane smart-HTTP path;控制面逐请求绑定executor token、真实execution header、work role、 active lease与Frozen repository,再以contents-read、repository-narrowed credential访问固定Git origin。只允许 protocol-v2 git-upload-pack,redirect/receive-pack/submodule递归均关闭,请求和流式响应有界且raw upstream错误不回显。 短token通过Git --config-env而不是URL/argv传递;remote保持无credential。Runner只接受exact frozen SHA、detached clean checkout,遇到非空或stale workspace直接失败,不用git clean/reset删除未知内容。
  • 控制面到Executor Worker优先使用私有service binding;HTTPS fallback必须固定唯一无userinfo/path/query/ fragment的origin,不能由Task或provider response改写。binding与fallback不能混用,control token缺失时 destination不启用。每次请求固定10秒、manual redirect、1 MiB响应上限、strict JSON,token只进入 Authorization header;3xx、超限、畸形schema、非200和raw response/cause均fail-closed且不回显。
  • Registry只注册环境中实际可用的provider。agent_executor outbox按D1冻结profile解析,Cloudflare transport 缺失或失败只重试原provider,不允许借已配置GitHub credential静默fallback;callback identity配置缺失时 verifySandboxIdentity固定拒绝。
  • Task、Agent output、历史outbox payload都不能选择executor kind/profile/route。新Attempt只能读取控制面 active route;缺route时Attempt/progress/execution/outbox原子零写。兼容github_actions intent必须先在 D1冻结route并结算自身,才允许新的semantic outbox调用provider;因此容器输入或旧业务Store不能借destination 绕过route policy。已冻结Attempt的redispatch只增加lease generation并复用原profile/route,即使active route 已切换也不重绑、不fallback。GitHub handle的run/head只有在插件返回值通过Registry全绑定校验后才进入兼容投影。
  • Cloudflare身份根是Executor Worker独立callback token,不是control token、GitHub OIDC或container自报header。 outbound handler先删除容器提供的identity header,再注入真实placement/execution并把internal URL改写到spec 绑定的控制面origin。控制面只对D1 immutable validated handle执行plugin验证;callback值不进入spec、DO storage、 container env/file、D1、日志或错误。execution-grant.json名称不表示其包含credential,它只有strict bootstrap引用。
  • 成功identity exchange沿用现有run/tool双token协议;两枚明文只在一次200响应和Runner内存,D1保存三个digest、 identity kind与execution binding。唯一约束和Attempt CAS保证20路只有一胜者;replay、错container/execution、旧 generation、非work role、lease过期或terminal execution全部拒绝。GitHub OIDC与Executor identity不能为同一 Attempt generation各签一套token。
  • model Responses不属于callback操作。容器先用普通Attempt短token为exact quota reservation申请独立model grant; Executor Worker对grant签发和Responses两条路径都必须保留原Bearer,任何callback覆盖都会让Agent shell绕过Codex 子进程边界。grant只注入Codex子进程CODEX_API_KEY,shell environment policy排除*KEY*/*TOKEN*;控制面以 digest验证并绑定work execution/Attempt/generation/reservation/Frozen model profile,只有reservation仍reserved时 才可调用exact model。grant密文使用独立EXECUTOR_MODEL_GRANT_ENCRYPTION_KEY,不得复用GitHub credential key; provider key只存在控制面EXECUTOR_MODEL_API_KEY Secret。若上游要求命名空间化model ID,只有部署者受信配置 EXECUTOR_MODEL_UPSTREAM_MODEL可在D1授权后改写出站model;容器仍必须请求grant绑定的内部exact model,Task、Agent、 profile payload和请求body都不能选择上游alias。结算、lease/generation/execution状态变化或TTL到期都会让 grant失效,raw provider错误及credential不能回显到容器、D1、R2或日志。GitHub Actions兼容lane的repository provider Secrets不进入Cloudflare容器,也不能作为executor grant使用。

GitHub Actions兼容插件

  • GITHUB_AGENT_EXECUTOR_REPOSITORY/REF是部署者固定的受信配置,Task、PRD、反馈、 Agent或dispatch payload不能选择执行仓库;业务目标仍必须命中独立repository allowlist。
  • workflow自身只保留contents:read + id-token:write。私有业务仓库的 TARGET_REPOSITORY_READ_TOKEN只允许出现在目标actions/checkouttoken输入, persist-credentials:false,不得进入Agent env、argv、日志、artifact、prompt或控制面。
  • Runner源码与业务repo使用不同目录。Agent只得到业务目录的绝对路径和业务repository, 不把GITHUB_WORKSPACE/GITHUB_REPOSITORY的执行仓库身份误当成业务authority。
  • OIDC与workflow run observation绑定集中executor;repo-write短凭证仍只绑定 Attempt/Plan/Item/approval及业务repository。读取executor Action的权限不授予向业务repo写入。
  • 旧Attempt只允许在pending + github_run_id/head_sha均为空时由持有唯一outbox lease的 dispatcher原子重绑。任何已启动或终态Attempt都fail-closed,不通过migration伪造恢复。

1. 安全目标

系统的主要风险不是传统 webhook 本身,而是“外部自然语言可以间接驱动拥有代码和基础设施权限的 Agent”。安全边界必须在模型之外执行:模型输出只能提出动作,请求由策略、凭证 scope 和平台保护共同裁决。

2. 信任边界

输入/主体 信任级别 处理
飞书/Meegle/GitHub webhook 连接 未认证直到验签 验签、时间窗、delivery ID 去重
任务正文、评论、网页、日志、代码注释 不可信内容 作为数据引用;不能覆盖 system policy
Agent executor实例 单 attempt 临时受信 provider identity绑定profile/handle/attempt/generation;短 token;退出即撤销
Agent 进程 受限执行者 无长期 Secret;所有 effect 经过 gate
Cloudflare Workflow 受信编排器、非敏感正文存储 输入/step/event 只放引用与 digest;副作用幂等;D1 投影
控制面 高信任 最小网络面、加密 Secret、append-only audit
tool-bridge 受控上下文网关 run 级 scope、TTL、调用审计、敏感字段脱敏

3. 身份与权限

3.1 GitHub

  • 默认使用 GitHub App,不使用个人 PAT 作为长期机器身份。受控兼容模式可通过 GITHUB_AUTH_MODE=pat 使用一个 Worker Secret GITHUB_PAT;该模式只复用相同的 repository allowlist、approval、outbox、CAS、审计和 runner fencing,GitHub 本身不会提供 App installation token 的真实 scope 隔离、短期签发或撤销能力。
  • PAT 模式只允许二选一:GITHUB_PAT + GITHUB_ALLOWED_REPOSITORIES(可选 GITHUB_PAT_EXPIRES_AT);不能与 GITHUB_APP_IDGITHUB_APP_INSTALLATION_IDGITHUB_APP_PRIVATE_KEY 混用。PAT 仅在 Worker Secret/provider内存中使用,不能进入D1(包括digest/ciphertext/IV)、R2、dispatch payload、PR、日志、artifact 或 Agent prompt。repo-write broker以单条guarded D1 effect直接建立reference-only active authority,不经过issuing两阶段;20路并发也只能有一条Attempt/lease-generation authority。GitHub REST 继续使用 Authorization: Bearer,Git Smart HTTP 继续使用 x-access-token Basic 形式。
  • 默认 App 权限:metadata read、contents read;仅已批准实现 attempt 获取 contents write / pull requests write 的 installation token。
  • Actions workflow 的 GITHUB_TOKEN 显式声明 permissions;不使用 write-all
  • 当前试点仓库为public,因此Runner边界固定为literal ubuntu-latest GitHub-hosted job;pnpm run verify:workflow-runners对完整workflow inventory fail-closed,拒绝self-hosted、标签数组、matrix/repository variable/expression、未受审hosted标签和job级reusable workflow。不得把本机、持久VM或共享宿主注册到该public repository来绕过provider网络问题。未来如需self-hosted,必须先取得owner对机器、费用和注册权限的独立批准并升级本契约;最低边界是一job一机的clean JIT/--ephemeral disposable VM/container、专用runner group/label、外送保存runner application logs、任务后自动deregister并销毁,不得复用工作站或宿主Secret。独立private execution repository是另一种需要重新设计App installation、OIDC、immutable checkout和证据绑定的方案,不能由repository variable静默切换。
  • required CI 只把计算拆成一个Node lane和四个固定workerd shard;所有lane仍是literal ubuntu-latest、顶层contents: read且setup Action固定到受审commit。最终唯一名为verify的聚合job以always()运行,只在Node与完整matrix都为success时成功,因此分支保护继续只依赖稳定verify上下文,取消、跳过、缺失或失败的任一lane都不能被聚合层伪装为通过。CI外部证据verifier从exact head workflow恢复固定job集合,并核对与扫描真实展开后的六份job/log。
  • 分支保护禁止 Agent push main、批准自己的 PR、修改 required checks 或 workflow 文件(除非任务显式属于平台仓库并二次审批)。
  • 仓库初始化 verifier 没有 create/update 权限:RepositoryBootstrapEvidenceManifestV1 只保存用户决策主体/selection digest、repository/branch安全标量和active rule parameters digest。真实 API 用短期 metadata/contents/rules read token;本地 origin 只通过固定 git remote get-url origin读取并拒绝userinfo、PAT、非GitHub host或其他repository。manifest 不能自证用户确认,必须与仓库外人审记录共同入账。
  • 生产 deployment 使用 GitHub Environment reviewer 与 OIDC 云角色。
  • GitHub base readiness的host-path恢复面只能是manual-only .github/workflows/github-base-readiness.yml。第一个job不关联Environment、不读取Secret且只做DNS/TCP/TLS;第二个job必须等待第一个成功,再进入预先创建的专用phase1-readiness Environment并只读取DELIVERY_LOOP_BASE_READINESS_OPERATIONS_TOKEN,再映射为进程内既有的GITHUB_BASE_READINESS_OPERATIONS_TOKEN。GitHub拒绝创建任何以GITHUB_开头的Actions Secret,因此不能把进程环境变量名直接复用为Secret名。两个job都固定public repo的ubuntu-latest、owner actor、refs/heads/main、exact github.sharun_attempt == 1,权限恰为contents: read,不能获得OIDC、deploy、Task或模型凭证;rerun不会再次GET。Environment必须在首次dispatch前由repo admin创建,required reviewer恰为owner且deployment branch policy只允许受保护分支;该token只能是Environment Secret,repository级Secret inventory必须不存在同名项。仅在workflow里写environment:会让GitHub自动创建无保护Environment,不能作为人审证据。Environment存在、Secret存在、workflow dispatch、preflight成功都不自授权;owner仍须把一次窄authority绑定到exact run ID/head SHA,并单独批准Environment job。Secret缺失时既有CLI在HTTP前exit 2,readiness非200/transport失败时不retry、不rerun、不扩张为Task或其他effect。
  • GitHub OIDC只信官方issuer/JWKS与RS256;audience固定。签名通过后仍逐项匹配D1的repository、job_workflow_ref ?? workflow_ref、GitHub run ID、dispatcher从受信Actions API候选冻结的workflow run head、Attempt status与lease generation/expiry;跨repo/错workflow/错SHA/run/过期lease均拒绝。OIDC sha不得匹配caller提供的值或Plan/checkout base_sha,两种SHA可以不同。
  • OIDC JWT只允许消费一次;JWT、opaque attempt token和独立tool token均只保存digest,响应禁止缓存。两个token必须不同且TTL都不超过lease。analysis grant由server catalog固定为repo/log/trace/K8s read与database diagnostic,不能凭JWT claim或请求body升级write/deploy/destructive scope。
  • exchange 将 starting→running 与一次性 credential pair入账放在同一D1 batch,并返回version/generation;缺任一可信绑定时不签token。Runner不获得TASK service token、R2 credential、GitHub App token或tool-bridge internal/Admin Secret。
  • dispatcher先检查控制面repository allowlist,再使用对应App installation的短期token;token只进入GitHub Authorization header,不进入dispatch inputs、D1 payload、日志或错误。workflow file/ref从受信D1 target派生,Runner请求不能覆盖。reconciliation只接受稳定title/event/branch/path全部匹配且同时具有合法run ID与40位小写head_sha的候选,并把两者原子写入Attempt;缺失/非法head的同身份候选必须停止,不能当成“尚无run”而重复dispatch。
  • GitHub App private key 只来自 Worker Secret binding;GitHub App Manifest conversion返回的PKCS#1 RSA PRIVATE KEY在Worker内以有界PEM/base64/DER解析包装为PKCS#8后交给WebCrypto,原值和转换字节都只在内存中。原生PKCS#8继续接受;未知header、重复/尾随PEM、非法base64、过短或超过20 KiB一律在网络前拒绝。App JWT ≤10分钟,普通dispatch/reconciliation installation token以repository名和Actions write + contents read再收窄并仅内存缓存到刷新窗口。App JWT、private key、installation token明文和API response body都不进入D1/错误。
  • installation-token POST固定10秒AbortSignal.timeoutredirect=manual且每次credential request最多一次;Cloudflare workerd不实现redirect=error,因此manual只用于取得而不跟随3xx,provider把所有非201(包括3xx)fail-closed且不读取其body。JWT生成后先以同一URL/options显式构造Request但不发送;运行时拒绝构造固定返回credential_request_invalid、网络尝试为0且不伪造transport日志。只有构造成功才把这一个已验证的Request对象直接交给fetch,禁止再次传入URL/options触发第二次RequestInit解析;production默认fetch还必须通过globalThis.fetch(...)调用,不能把捕获的Web API函数作为provider成员方法以foreign receiver执行。网络仍只有原单次POST。收到HTTP响应前失败也不自动重发,因为原POST可能已经到达GitHub并创建另一枚token。provider与一次性readiness caller共用只读name/code/cause的五类transport分类,但readiness响应继续只暴露credential_transport_unavailable。生产诊断只能经secureStructuredLogSink输出固定github_app_installation_token_transport_failed + operation + failureKind + requestAttempts=1;没有repository、URL、App/installation ID、HTTP状态、JWT/key/token、raw message/cause/body字段,sink失败不覆盖原credential stage。
  • 单仓库installation外部验收默认零网络:未设置DELIVERY_LOOP_GITHUB_APP_DISPATCH_E2E=1时在manifest/token/network前exit 2。App JWT只读App/installation/repo binding;installation audit token必须在签发时省略repositories/repository_ids,再以metadata/contents/actions read读取完整selected inventory、workflow/Action/job。响应1 MiB且分页fail-closed,workflow decoded上限256 KiB;credential只进Authorization header,raw App/installation/workflow/job响应、workflow正文和token不进入manifest/错误。audit token可能被预先二次narrow且无法从字符串发现,因此API count=1不能取代settings页和credential issuance人工审计。
  • analysis Action外部验收继续复用上述App/dispatch verifier,额外用途隔离地读取Task/Plan/Case 8和Action immutable head上的Runner source-set。manifest不含Task/Plan/Item正文、Evidence ref原值、source/workflow正文、tool参数/result或raw API;只保存分类、SHA、count和digest。Runner聚合digest必须与manifest外release review记录一致,不能从待验manifest复制expected值。Case 8只接受成功read类别和exact triage scopes,任一denied/mutation category或analysis repo-write credential都失败;最终job还必须证明exact HEAD、detached和clean。默认未设置DELIVERY_LOOP_ANALYSIS_ACTION_E2E=1时在manifest/credential/network前exit 2。
  • diagnostic Evidence producer只能使用active attempt token,不能使用Task/operations/tool token,并再次核对analysis + bug + planning + version/generation/lease。caller只能提交locator digest、脱敏root-cause摘要/代码引用和source trace ID;统一Secret scanner在D1前拒绝Worker Secret/current token/credential形状。source必须是同Run/Attempt中成功的logs/search + traces/get且effect=read,tool arguments/result、uid/cid/path原值、raw日志/trace和错误正文没有持久化字段。operations投影刻意排除Evidence summary。
  • bug Agent不直接拥有tool client或token。固定Runner只给Adapter一个冻结、不可枚举authority状态的searchLogs/getTrace/finish capability facade;三方法内部以状态机限制一次logs/search、一次traces/get和一次root cause,path/scope/effect均由Runner与控制面catalog固定。heartbeat轮换与tool call串行读取当前fencing,旧tool token不会因并发轮换被继续使用。Agent request、tool result、root cause、Plan均扫描全部runtime Secret和credential shape;结果超过256 KiB、失败、重复/越序、未知字段、自填diagnostic ref或workspace mutation时,Evidence与Plan保持零写入。
  • logs/trace正文只进入Runner内存及repo外0700目录中的0600临时上下文,prompt明确其为不可信参考资料,finally递归删除;它们不进入D1、artifact、checkpoint、stderr或模型usage。每个bug固定最多四次Codex structured-output调用,使用同一受信model profile但独立quota reservation/usage,统一50分钟Attempt timeout;requirement路径保持单次调用。第3阶段只返回root cause并由可信Adapter解析、runtime Secret扫描和finish冻结;Adapter随后用仅含净化root cause的0600上下文替换原始logs/trace上下文。第4阶段复用普通Plan schema,只从该净化root cause与可信Task policy接收requiresRepositoryChange:writable bug必须提议唯一self-verifying required change;该Item已有repo_write + test:* + verify:* + commit/test且唯一时,Adapter只补齐logs_read effect,已完成诊断只能以Runner注入的Plan级verified Evidence ref绑定。它不能作为后续execution Attempt自产Evidence,也不能新增写权限、命令或修复语义;多候选与其他模糊形状保持fail-closed。所有可执行required change Item的evidenceKinds必须恰为commit/test,未来阶段的PR/check/review/approval/deployment不能由不可信Plan提前声明为关门前置。read-only bug没有repo_write能力且不执行该绑定,最终effect/command/Evidence shape仍由Runner validator强制。provider-facing diagnostic JSON Schema必须是strict closed object:全部properties required、版本用单值enum,不得使用中转站不支持的constpropertyNames、regex lookahead、开放additionalPropertiesuniqueItems。兼容wire中的空字符串/零值只表示未选择字段,Adapter必须在可信边界验证并去除;locator唯一性、顺序、非空选择、code ref相对路径与有效定位及参数shape仍由Runner Zod schema在tool/Evidence/Plan前重验,不能因此重复调用、扩大scope、接受绝对/父级路径或空根因定位。Evidence producer只在Plan/root cause/Secret/workspace全部通过后调用;返回ref与两个digest必须由Runner本地重算核对,Agent无法伪造或替换。
  • 真实telemetry只保证经过净化的source事件,不保证提供repository path,且Tool Bridge的SLS payload可能是单层plaintext string。Runner因此在第3阶段前构建用途单一的source snapshot:候选只能来自已扫描diagnostic结果;长字符串有256 KiB上限,只提取有界code-shaped token,普通词不参与源码匹配,每个高频候选超过50条匹配即整体丢弃。文件只能来自exact checkout的Git tracked、仓库内regular且非symlink UTF-8源码;tracked-path数量/输出预算与Runner inventory policy共用5,000/256 KiB可信常量,单文件/累计字节、候选、匹配、excerpt和最终JSON仍各有独立硬上限并确定性排序。snapshot再次扫描全部runtime Secret,任何inventory/path/read/decode/上限/Secret异常都fail-closed。模型返回的每个codeRef必须命中snapshot exact path,并匹配正行号或excerpt内symbol;snapshot不存在、空引用或仓库中“看起来合理”但未命中的位置不能进入root cause、Evidence或Plan。snapshot只在repo外0600临时上下文和stdin不可信区块中存在,不写D1/R2/artifact/checkpoint/log,也不把diagnostic字符串或源码excerpt持久化。
  • Task/Plan policy context以digest-verified临时文件保留调用前后完整性锚点,并在provider前通过256 KiB上限、credential形状和全部runtime Secret扫描;0600文件严格为{schemaVersion:'1', contextDigest, context},Runner对嵌套context的JSON.stringify字节预先计算marker,Adapter在模型调用前后都重算并要求完全相等。通过后,exact envelope只作为单个JSON对象进入stdin的BEGIN/END_UNTRUSTED_ANALYSIS_CONTEXT_JSON明确不可信数据区块;正文不进入argv、日志、artifact、checkpoint或D1,正文中的分隔符形状只作为转义JSON string。requirement与bug第4阶段Plan output继续严格为{contextDigest, plan},bug第3阶段root-cause output继续严格为{schemaVersion, contextDigest, rootCause},但contextDigest只是provider-wire兼容字段:模型值被Runner忽略且不持久化,不能授权Plan、effect或Evidence。缺兼容字段、格式非法、额外顶层字段、Runner文件缺marker、marker/context不一致或调用期间漂移全部fail-closed。Runner只提取嵌套Plan并与本次内存中的identity/base/context绑定;按owner产品裁决,command_execution和模型精确复制digest都只可作为非授权兼容/诊断事实,不得阻止合法Plan。Runner-owned前后digest绑定不授予effect、不单独证明完整语义理解,也不替代Plan validator、Evidence或human approval。
  • E2E-2 verifier默认零网络;未设置DELIVERY_LOOP_BUG_TRIAGE_E2E=1时在manifest/token/network前exit 2。它完整调用原Analysis Action verifier,不接受测试注入子verifier;再以用途隔离operations token读取diagnostic投影和Case 8。仓库外manifest单份64 KiB、HTTP响应1 MiB/10秒有界,四类token与synthetic canary在JSON parse前扫描;stdout/stderr只输出固定错误码和安全计数。manifest中的review布尔值不能自证locator输入、根因语义或日志平台内容。
  • base_update不能把调用方或Agent自报的Evidence ref升级成诊断authority。只有可写bug、同一Run、revision冻结的prior Plan恰好一个diagnostic ref、该ref绑定prior Plan原analysis Attempt、Evidence仍为diagnostic/passed/verified且source仍含成功只读logs/trace时才允许carry;context和Plan persistence各自重算。Runner不向模型披露ref,不创建新tool/Evidence,只在模型完成新base只读检查后确定性追加;模型输出任一diagnostic ref、lineage缺失/重复/漂移或ref跨Run立即在Plan写入前拒绝。该路径不继承旧approval、credential、Attempt token或写权限。
  • GitHub test deployment使用另一套内存cache/pending与权限profile,effect token严格只有deployments:write;status reconciliation再使用物理分开的deployments:read cache,不得复用Actions、PR、merge observation或contents-write token。D1/outbox/observation只保存deployment引用、GitHub numeric ID、canonical fact digest与白名单状态,不保存token或REST response body。
  • 测试部署外部验收继续沿用上述分离:TestDeploymentEvidenceManifestV1 只保存 test Environment、workflow/OIDC 标量、Action/Deployment ID、URL、status observation digest 与 zero-duplicate 计数;e2e:test-deployment 复用 Watt 的显式 opt-in、64 KiB manifest、0/1/2 退出和有界读取,并使用独立 deployments:read 与 deployment-triggered Action 事实。OIDC 换证审计和生产 Secret 隔离 URL 只能人工核对,不能把 manifest、Runner echo 或 Deployment create 响应当作成功。
  • yunxiao_pipeline测试部署只允许控制面持有Tool Bridge internal credential;GitHub Runner不获得该credential或云效写工具。目标organization/pipeline/repository/source branch/SHA来自受信配置与D1 snapshot,不能由Task正文、Agent输出或Queue message覆盖。Tool Bridge body/result视为不可信外部数据,只读取numeric run ID、白名单状态/时间与exact commit;不记录raw response、pipeline参数、日志或流水线Secret。create API缺少幂等键时,响应丢失后只允许有界只读list+detail reconciliation;只有稳定deployment ID与exact SHA同时匹配才复用,否则第二次写被禁止,不能以“可能失败”为由盲重试造成双部署。
  • GitHub post-deployment acceptance再使用独立内存cache/pending,权限严格为actions:write + contents:read;不能复用通用Agent dispatch cache,也没有deployments、PR或contents-write权限。dispatch只携带acceptance ID、exact deployed SHA、schema和控制面origin,不携带测试凭证、任务正文或Environment URL。
  • test与production部署身份物理分开:workflow path、Environment、OIDC audience和role ref均由strict policy分别固定。本地test路径只接受audience=delivery-loop-test-deploy、subject=repo:<repo>:environment:testenvironment=test;通用Agent audience、ref subject和production environment全部拒绝。OIDC JWT只存digest,attestation不返回云credential。
  • acceptance OIDC与deployment/通用Agent audience继续物理分离,固定为delivery-loop-test-acceptance;控制面逐项绑定test Environment subject、repository、固定workflow ref、deployed SHA和GitHub run ID。Runner result与JWT只存digest/白名单标量,原始token、测试响应和workflow payload不落D1。
  • acceptance 外部验收只使用独立 Actions read token,TestAcceptanceEvidenceManifestV1/e2e:test-acceptance 的 running/passed/failed case 必须分别证明 Action 状态、Runner result、双源 observation 和 Evidence;requested/in-progress、Deployment success、dispatch response 或 Runner echo 均不能关闭 Item。Case 8 不返回 acceptance/Action 正文、OIDC token、workflow payload 或数据库行。
  • rollback OIDC与deployment/acceptance/通用Agent audience继续物理分离,固定为delivery-loop-test-rollback;控制面逐项绑定test Environment subject、固定workflow、失败SHA、GitHub run ID、verified failure source及exact contract observation。rollback role必须是与deploy role不同的test:*。JWT/Runner result只存digest与白名单标量,原始policy、token、命令输出和workflow payload不落D1。
  • 固定test workflow只关联GitHub test Environment,因此GitHub不会向job注入production Environment Secret。Runner还在policy command子进程前移除GitHub deployment token和OIDC request token;真实云侧必须另以trust policy把test:* role限制到测试账户/namespace,这一外部隔离在未实测前不得视为完成。
  • repo_write使用独立、不可跨Attempt缓存的installation token profile:仓库固定为D1 Task/Attempt目标,权限只有contents:write + pull_requests:write。签发前必须命中Task policy、active Plan/Item的repo_write effect、Attempt fencing与exact未过期approval;run/tool scope即使被污染也不能触发签发。
  • Runner在Agent前请求一次repo_write credential,只用于证明当前审批允许本地edit;10分钟Agent窗口结束后、任何patch/commit/push前必须用最新heartbeat fencing重新请求同一credential identity并刷新短authorization窗口。两次请求都不能改变repository、approval、token或exact permissions,也不能创建第二个GitHub token。任一请求transport失败、非2xx或strict response不合法时,不读取或传播response body/status/raw error;只经active Attempt fencing上报固定tool_unavailable / external_reconciliation / resolve_external_dependency,控制面立即以external_dependency阻断Run/Plan/Item并取消Workflow。提交前刷新失败时不执行patch/commit/push;failure report后Runner停止heartbeat、清理临时目录并固定失败,不盲重试或扩大authority。
  • 上述失败若来自exact review_fix,恢复authority只能来自新的未编辑OWNER commit comment;旧approval、原comment、operations caller字段和Agent输出都不能解锁。零credential的固定external-dependency failure与lost pre-effect replacement继续分开标记为failed_dependency|lost_pre_effect。普通review-feedback lost replacement要求唯一credential已revoked|expired;exact implementation-repair replacement还可在credential签发前失败,但必须同时重验prior recovery为failed_dependency、settled repair dispatch、原implement targeted-verification failure、相同head、GitHub terminal failure、resolved stuck fence、settled cancel以及零credential/effect。旧PAT两阶段实现产生的唯一lost-pre-effect replacement若又固定失败,只允许最后一次嵌套恢复:必须绑定完整的verification failure → failed_dependency recovery → fenced lost replacement → lost_pre_effect recovery不可变链、当前settled dispatch、exact unresolved blocker、唯一已过期issuing且无token/digest/ciphertext/expiry/error的credential、零model usage/head/commit/test/verification effect及fresh approval;第三个replacement使用failed_dependency,因此不能再次命中该专用形状。此例外不接受任意zero-credential review Attempt,也不形成无限恢复。自动review fix的unknown_failure/external_reconciliation终态另用automated_fix_failed_pre_effect,只在直接自动fix根lineage、current active Plan/in-progress Item、changes_requested review、verified publication/latest head、唯一terminal credential、零blocker/head/commit/test/verification effect及零replacement同时成立时开放fresh模板。该形态不把可能陈旧的D1 github_status/conclusion当第二终态authority:failed Attempt与撤销token/credential已经阻断晚到Runner写,外部Action observation仍保留为审计事实。审批batch把source kind、source/root review和fresh approval写入immutable lineage,专用reconciler再次重验全部guard后才创建replacement。active或多个credential、review/publication/head漂移、reject/invalidation、active blocker、已有replacement或任何effect一律fail-closed;generic scheduler不能消费未完成recovery marker。
  • 控制面Draft PR producer使用第三个用途隔离profile:单仓库、仅pull_requests:write、只在Worker内存短期缓存。它不能写contents或Actions,且每次effect前仍重新核对prepared snapshot、active Plan/final head和exact未过期repo-write approval;更新的reject即使token仍在缓存也阻止调用。
  • GitHub App短token为保证Worker重启后仍能撤销,D1只存token digest及AES-256-GCM ciphertext/IV,密钥来自独立GITHUB_CREDENTIAL_ENCRYPTION_KEY Secret binding;没有明文token列。authorization TTL取GitHub/approval/lease最小值,scheduled revoker在过期、reject、complete/fail/cancel/lost后调用官方revoke endpoint并清除密文,失败安全重试。PAT不能由该endpoint撤销且不得复制长期Secret到D1,因此只保存reference-only authority和authorization/upstream时间;失效时标记expired并停止返回PAT,真实PAT撤销仍是独立人工/Secret轮换动作。
  • Git mutation只能走无任意argv入口的GitRepositoryWriter:分支固定agent/<task>/<attempt>,push target必须同一derived ref,main/master/base/受保护分支和所有force请求在spawn前拒绝。commit author+committer固定bot,宿主GIT_*清空、hooks/GPG禁用,不能由repo config、Task或Agent覆盖身份。
  • repo_write token不写remote URL或Git argv,只作为单次push子进程环境的HTTP header;进程错误固定化且不回显stderr。即使Agent构造refspec、--force、替代author或过期credential,strict writer API也无对应透传入口。
  • writer在commit前强制扫描内建与commit-bound policy高风险路径,不能由Agent关闭或省略reporter;workflow/CODEOWNERS/delivery policy、.env*/.dev.vars*/常见secrets文件、Wrangler、Docker Compose、Terraform和常见部署目录始终在内建集合。rename/delete/untracked同样覆盖,rename的old/new path任一命中即暂停。
  • 高风险报告没有patch正文容器,只允许base/tree/policy/diff digest、总文件数和path/previousPath/changeType/additions/deletions。固定HTTPS reporter用active attempt Bearer + version/generation上报;响应必须202且回显同一canonical报告,否则commit仍拒绝。Bearer不进body/URL/error。
  • 控制面只有在running repo_write Attempt、executing Run、exact active Plan/Item/base、Task policy和active单仓库write credential全命中时创建gate;同一事务撤销run/tool token、递增generation、取消Attempt、标记GitHub token待外部撤销并建立Workflow pause outbox。安全查询可列路径diff摘要,但不返回raw diff、Git对象内容、token或ciphertext。
  • 测试命令只能来自可信base policy的canonicaltest:*/verify:*;Agent/Task不能提交argv、shell、环境或删减required verify。Plan Item声明选择的targeted refs,Runner自动追加policy全部verify refs,控制面再要求manifest与Item commandRefs集合exact相等,任一层漂移均拒绝。
  • 命令输出与stderr不进入Evidence reporter。上报schema只有position/phase/ref/exit/duration/head,summary/status由服务端派生;固定HTTPS reporter每次取最新轮换Attempt token,Bearer只进header,响应必须no-store且命令序列不能被服务端重排。
  • 每条命令前后复核HEAD;命令改变commit时不产生误绑定Evidence。D1只在active required verification Item上下文接受first-pending结果,targeted未全passed不能写required Evidence;跨Attempt suite/evidence ID猜测、旧version/generation、错误head或调用者自报passed/verified均拒绝。
  • Item关门是独立服务认证边界:Agent run/tool token不能调用verify路由,strict body没有status/verified字段。控制面重新绑定active Run/Plan/required Item/Attempt/head,并要求每条doneWhen映射覆盖声明的Evidence kind/command/external fact;test/verify事实还必须来自completed suite。通常还要求active lease;lease过期的恢复路径必须另有D1可信GitHub completed/success,不能由Runner自报或本地时钟单独放宽。failed/skipped、旧Plan/SHA、跨Attempt Evidence或缺失mapping均不能产生部分decision。
  • migration 0015的D1 trigger阻止required progress绕过decision直接变passed;成功batch同步写decision/mapping、锁定Evidence、完成Attempt、提升generation并撤销token。migration 0063只修正head-linked commit Evidence的关门窄缝:允许控制面执行一次unverified → verified,不允许修改其run/attempt/plan/item/kind/status/SHA,verified后仍由通用trigger完全冻结。已映射verified Evidence关键字段不可变且映射存在时不可删,避免passed后篡改审计依据;查询只公开ID/digest/head/mapping/时间,不公开正文。
  • Queue payload 只有 outbox ID 且不作为 destination/权限真源;consumer 必须回查 D1 destination。Cron的fresh Workflow优先入口也只能从D1选择queued + base_sha resolved + workflow_create + 非open dead-letter并调用同一个fenced processor;它不接受HTTP/Task/Queue自报destination、kind、Run状态或effect,不能复活dead-letter或绕过lease。GitHub runtime 未完整配置时 outbox 保持 pending/retry,不得 fallback 到 Workflow processor 或 ack 丢失。
  • dispatch 载荷只允许 schema/run/attempt/plan/item/task digest/base SHA/control-plane origin/mode 白名单字段。稳定 run-name 只含 attempt ID;唯一fenced redispatch可在immutable recovery/redispatch lineage与exact execution outbox共同证明generation 1时追加固定/redispatch-1,不得接受caller自报generation,也不含任务标题、正文或actor。
  • Phase 1 analysis workflow 只有 contents: read + id-token: write;checkout exact base SHA、persist-credentials: false,所有第三方 Action pin 到 commit SHA。OIDC runtime token 与 attempt token 只保存在 bootstrap 内存中,不写 context/output 文件。always-run只读关口必须独立核对HEAD仍为checkout SHA、symbolic-ref为空和porcelain为空;clean tree单独不足以排除本地commit或branch漂移。
  • GitHub webhook必须先对原始body验证X-Hub-Signature-256,再按X-GitHub-Event解析白名单workflow_runpull_requestpull_request_review;delivery ID + raw digest去重。workflow fact继续全绑定run/repository/workflow/dispatcher冻结的run head/title/attempt,不能用Agent checkout base替代run head;title只接受base stable name,或由D1 recovery/redispatch lineage与exact outbox推导出的generation 1 suffix。旧projector已把同一redispatch fact记为immutable ignored时,新binding profile使用独立observation identity重新核对一次,旧记录不改写且任意suffix仍ignored。PR opened fact必须全绑定publication的repository/base/head SHA/title/body digest/draft/open;changes-requested review还必须令review commit、payload PR head与控制面当前PR branch head三者一致。签名正确但binding不符只ignored,Agent自报URL/number/status没有状态入口。
  • review webhook丢失补偿只使用独立pull_requests:read installation token;REST body与token不落D1/日志/artifact,review body仍先经当前Worker Secret catalog扫描再写私有R2。补偿必须重验open PR、same-repo base/head branch、当前head、reviewer最新状态与既有publication/approval/Plan/Item门禁;分页、100条边界、空body、非法URL/time、stale head或任一binding漂移全部fail-closed,不能借API路径绕过webhook projector或创建额外写effect。
  • lost review recovery不复活旧lease、token、credential或GitHub run,也不覆盖旧Attempt。首层无credential lost可在仍有效approval下按原stable recovery收敛;若approval-recovery replacement已经取得credential后被fence,只有外部Action completed/non-success、恰好一个credential已revoked|expired、prior recovery/root review、resolved exact fence、settled cancel、零active blocker及零failure/head/commit/test/verification effect同时成立,才允许通过新的OWNER approval创建下一Attempt。replacement继续从同一reviewed head重新签发短期credential并执行remote-head/non-force fast-forward检查,故链式恢复不能扩大repo、branch或effect authority。
  • head CAS不把任意recovered_from_attempt_id视为写入授权;implementation repair replacement必须同时命中immutable recovery ledger与同Run/Plan/Item、同head、terminal failed implement root,且不能同时命中direct repair/review/rebase lineage。
  • 首次implement若在Agent前因未分类Runner异常被fence,不得靠checkpoint API、旧approval或D1 repair复活。唯一兼容恢复要求外部Actioncompleted/non-success、resolved exact stuck fence、settled Workflow cancel、current active Plan/in-progress Item、repo_write effect、零open blocker,并逐表证明旧Attempt没有credential、failure、head/branch、checkpoint、suite、Evidence或replacement。此时只开放一次fresh exact commit-comment approval;独立immutable ledger把Item恢复为ready,专用D1 reconciler再以仍有效approval创建唯一implement replacement和execution outbox。replacement不继承旧lease/generation/GitHub run,任一并发或晚到effect都会使guard失败。
  • merge gate verifier 使用 production GitHub adapter 的最小只读 token,依次读取 exact PR、base ref、branch rules、check-runs、statuses 和 reviews;任何响应超限、分页、错误绑定或 digest drift 都 fail-closed。Case 8/manifest 只保存 normalized SHA、计数、digest、固定 rejection reason 和 zero-effect 计数,禁止 raw REST/review body、payload、数据库行、Agent 输出和 token。
  • identity approval verifier 只使用 GitHub read token 读取 exact PR/review actor/head;commit-comment repo-write通道只接受未编辑comment的个人仓库OWNER或组织仓库MEMBER,拒绝COLLABORATOR|CONTRIBUTOR|NONE。GitHub owner/repository路径只按平台语义忽略ASCII大小写,host、commit SHA、comment ID、正文和时间仍精确绑定。accepted 必须有 human + approve:<effect>、roles digest 和 immutable lineage。只有已有 PR/merge author 的 mergeproduction_deploy 等高风险 effect 才要求 approver/author separation;PR 创建前的 repo_write approval 固定投影 separationVerified=false,不能被 Case 8 误判为损坏数据,也不能借此获得 merge/production authority。self/agent/service/unknown/revoked identity 只能形成固定 rejection projection。Feishu source 只保存验签后的 event/tenant/open_id metadata 与 digest,不保存原始事件或 token;IdentityApprovalEvidenceManifestV1/Case 8 不会把 manifest、roles 自报或 approval adapter caller 当作身份真源。
  • approval-lineage pair verifier使用用途隔离的operations、observer和单仓库GitHub PR-read token,只做1 MiB有界GET;解析前扫描三枚token、credential形状与仓库外canary。manifest不含raw callback/review/card value/open_id,Feishu仅保存operator/open_id/chat digest;Case 8的operations-only channel identity用于重算digest,人工目录review才确认open_id/login/principal同人。observer必须同时证明Feishu/GitHub same-event replay收敛、distinct-event nonce与same-event snapshot mutation拒绝;任何response、manifest或live review都不能单独自证approval lineage。步骤见飞书/GitHub审批唯一关联真实验收
  • GitHub commit-comment repo-write入口不信任POST调用者:body只能有正整数comment ID,operations token只允许触发回查。GitHub read token仅进Authorization header;provider响应64 KiB/10秒有界,redirect、非200、非法shape全部固定失败。只有exact repository/base commit上的未编辑OWNER|MEMBER comment、服务端派生的完整Run/version/Plan/version/digest/base模板和24小时内source时间同时成立,才产生一小时approval。外部fact解析后的identity映射仍按GitHub事实派生;若principal roles和channel principal都已完全相同,read-before-write直接返回且不刷新时间或制造两个冗余D1 writer,真实变化仍按原upsert生效。blocked implement恢复只接受上述零effect/fenced/cancel-settled形态;pull_request_open只为pending自动review的terminal-failed、expired/fenced、保留可调度workflow与current publication/head快照开放fresh模板。普通PR-open、Runner-only failure、不可调度Attempt、尚未终态replacement、已有effect/replacement或redispatch仍为409。comment正文只做内存exact比较并以digest入source,不能进入日志、D1、artifact、PR或错误;caller自报login/actor/effect/expiry/Plan/base均无schema入口。
  • GitHub-hosted operator复用受保护phase1-readiness Environment把既有operations Secret交给受信main workflow,不新增或轮换credential。workflow只允许owner、refs/heads/main、exact SHA、attempt 1并继续要求Environment人工gate;readiness、dead-letter read、repo-write comment observation与dead-letter replay四种输入模式互斥。approval模式只把canonical Run ID放URL、正整数comment ID放0600 strict JSON body并发送一次POST;不接受或输出comment正文、actor/effect/expiry/Plan,响应只投影accepted approval/lineage ID与created。该唯一POST可等待最多120秒以容纳Free-plan Cron和D1 writer竞争;这只扩大transport等待窗口,不放宽Worker内部GitHub GET的10秒上限、workflow 10分钟总上限、comment/Plan快照或effect authority。replay模式只接受exact dead-letter ID、expected outbox attempt count和固定reason code,0600 body不含payload/effect/destination并只发送一次POST;响应只投影dead-letter/replay ID、状态与created。branch-only workflow、Task token、Environment配置或人工gate任一单面都不能产生approval或扩大原outbox authority,最终authority仍是控制面对当前D1 snapshot、原outbox与GitHub OWNER comment(approval模式)的重新核对。

3.2 飞书

  • webhook 验证 verification token/signature/encryption,拒绝过期 timestamp 和重复 nonce。
  • FEISHU_EVENT_ENCRYPT_KEYFEISHU_EVENT_VERIFICATION_TOKEN只能来自Worker Secret;缺两者时POST /v1/webhooks/feishu固定503,不能沿用Watt原实现的“无token明文也接受”兼容行为。推荐加密模式同时执行exact-body纯SHA-256签名、300秒request timestamp、AES-256-CBC解密和解密后token常量时间比较;签名不是HMAC,不能把GitHub HMAC helper误用于飞书。
  • challenge在来源校验后短路且不产生D1行。event必须再绑定配置app/tenant;验签失败、过期、错误app/tenant/token和畸形事件都不能产生nonce/receipt、Task、Run或outbox。成功路径只在D1保存event/tenant/app/type、transport/event digest与时间;nonce只保存SHA-256 digest,raw/encrypted/decrypted payload、verification token、encrypt key和异常正文没有列或日志入口。
  • webhook外部验收日志只允许case/outcome + request/response digest + status + start/end/latency + 正向event/type/delivery ID,由统一Secret redaction/scanner后输出;invalid signature无法可信解密event ID,不能在日志中伪造该绑定,负向event ID由受控probe manifest索引并由operations exact零写入查询补强。observability与operations token用途隔离,manifest URL必须与独立配置exact相等后才发送token;飞书后台历史投递无机器可读OpenAPI时必须保留人工review,不能用manifest、D1或Worker日志替代。
  • 每个加密request nonce由独立immutable ledger按tenant + nonce digest唯一。相同event ID用新timestamp/nonce重新投递可以收敛为同一receipt,但每个新nonce仍入账;同nonce更换event/request digest固定409,防止event唯一约束掩盖transport replay。
  • 普通Task/工作项event的verified receipt与ingress outbox同D1 batch发布,Queue只携stable outbox ID。card.action.trigger在验签后明确分流,只保存同一metadata receipt并直接进入action鉴权,不创建Task ingress。relay/consumer不能从消息body取得tenant、event digest、Task或权限;每次回查immutable receipt/outbox。Cloudflare Queue是at-least-once,安全目标是重复delivery吸收到同一D1 identity,而不是在日志里宣称物理exactly-once。consumer只在内存读取平台message.id并保存canonical digest;timestamp/attempts与digest形成immutable observation,和queued状态同batch。相同attempt重放幂等,后续attempt必须连续留痕;原始Queue ID/body、lease和上游错误没有ledger字段。
  • 飞书ingress真实verifier严格只读并分离operations、observability和Cloudflare Workflows read token;manifest中的observability URL必须与独立配置exact一致,Cloudflare account ID只以digest进入manifest。四条HTTP观测、两个D1 lineage和live Workflow是不同authority;Queue dashboard没有可替代D1 attempt ledger的自证能力,仍需人工review。manifest/summary/错误不含raw webhook、nonce、Queue原始message ID/body、Task正文、数据库行或credential。
  • normalized Task sink不是公共入站认证面:它只接受已queue-observed的exact event/tenant,task.eventId必须等于receipt event,source只允许feishu|meego且tenant相同。Task在R2/D1前扫描配置Secret;Task revision identity排除平台delivery metadata但覆盖source/actor/coordination/target/intent/policy,因此不同event同revision可复用Run,而同revision更换业务正文不能绕过去重。
  • Meegle snapshot/profile必须同时绑定receipt tenant、project与work-item type。field key/role key来自预先核实的受控profile,role不能从同名普通field读取;target repository还必须命中profile allowlist。工作项raw字段、描述、owner与repository均是不可信数据,不能携带policy/effect或改变审批要求。fieldsComplete=false或存在nextPageToken时fail closed进入triaging,不能把第一页冒充完整快照。
  • Meegle真实验收器只允许固定1.0.16 CLI、argv数组与shell:false,profile/work-item ID不能进入shell文本;profile、tenant、project和type由环境独立配置并与manifest exact绑定,manifest不能选择本机其他profile。--envelope响应有2MiB流式上限且错误固定化;raw data/stderr、cursor、token和principal不进入summary或manifest。任何truncatedstopped_reason或剩余cursor均拒绝。operations接口用独立短期只读token,只在Worker内部读取R2 ref并返回digest验证布尔与白名单标量;对象存在本身、manifest digest或本地fake不能自证真实映射。
  • triaging正文只写私有content-addressed R2且先过Secret scanner;D1候选表只有source metadata、profile/snapshot digest、固定gap和ingress lineage。operations查询不返回description、field values、owner principal、R2 ref或digest;event/profile/binding/Secret错误都在R2/D1/Task之前拒绝。
  • 卡片按钮的可见性不是授权。renderer直接复用Watt 476e3cdbutton.value={id,signal}骨架,但signal只冻结latest immutable card/presentation/message、Task/Run version、task revision digest、active Plan ID/version/digest/base、command/effect和application nonce;没有principal/roles/policy/expiry/target/R2 ref字段。callback继续先过signature/timestamp/decrypt/token/app/tenant,再要求exact配置chat、当前active message和latest presentation,且signal canonical digest确实存在于该presentation。
  • 服务端以feishu:<tenant> + operator.open_id实时解析identity:anonymous、service、agent、缺human或缺approve:<effect>/operate:<command>/context:add均拒绝;approve还执行Task actor分离,高风险effect继续执行PR author/merge/release分离。retry Item和replay step由D1当前blocker/checkpoint或固定受控step推导,payload不能自选。card-created低风险approval消费时重新JOINcurrent channel mapping/live role;撤权立即失去trusted authority并触发卡片重投影。
  • transport nonce与application nonce是两个ledger:前者保护密文request,后者按tenant+eventtenant+nonce digest各唯一保护业务动作。action receipt/outcome只保存open_id/principal、安全ID、版本/digest、固定command/effect/result/reason;不存raw/encrypted/decrypted event、form正文、token、明文nonce或异常。card action不进入Task normalizer。claim后的动作仍由既有approval/lifecycle/recovery/replay/context store执行;失败outcome不能伪装成功,也不能留下Run/Attempt/approval/task revision部分状态。
  • add-context只允许受控form字段提供正文;正文不参与authority且不进入action D1。服务端回读prior Task R2并核对content digest/metadata,再用已验签event和open_id派生revision/actor,交给既有Secret scanner与immutable R2 producer。new_run|apply_current来自两枚不同的冻结command;用户正文或篡改payload不能切换模式或改变policy/effect/base/target。
  • action evidence endpoint只接受operations Bearer与单一exact tenant/event GET。已验签card event先保存metadata delivery,使pre-claim拒绝可审计;response把open_id/principal/chat转换为canonical digest且不返回roles正文、application/transport nonce、raw callback/form、context/R2 ref。成功必须恰好一个event-bound effect,拒绝必须零effect/零ingress;synthetic credential-pattern canary在JSON parse前扫描observer和operations完整有界响应。observer token与operations token用途隔离,manifest URL必须与独立配置exact匹配后才发送凭证。
  • supplemental-context evidence endpoint只接受operations Bearer与单一exact context ID,并在服务端从隐藏ref有界回读context/new Task R2,strict解析且重算digest/metadata;响应只保留external lineage和Run/Attempt/token/approval安全计数。new_run必须证明旧Attempt version/lease和active token未变;只有apply_current可令旧Attempt cancelled、token全撤销、approval全失效。verifier另用用途隔离的observer与飞书Message read token,在JSON parse前扫描仓库外synthetic canary;步骤见补充上下文 revision 与当前 Run 隔离真实验收
  • 用户映射(飞书 open_id ↔ GitHub identity/团队角色)需要显式维护和审计。
  • 状态卡没有外部写入/自然语言指令面:renderer只接受strict v1/v2 immutable presentation。v2枚举/计数/identity来自D1;Plan Item title、checkpoint和verified Evidence summary先做单行限长与Worker Secret/credential scan,Markdown渲染再次转义。命中Secret使用固定隐藏摘要;Task/PR正文、raw log、artifact/R2 ref、Runner output、数据库行、自由错误和飞书raw响应不能进入presentation/outbox/错误/卡片。
  • Action链接只在GitHub observation version前进后由trusted repository+numeric run ID构造;check/Evidence链接只来自verified Evidence;PR/merge与deployment继续要求各自verified external fact。approved effects必须来自exact current Task/Plan/base的trusted view,排除过期、统一invalidation与更新reject;最早expiry触发无事件刷新,隐藏/旧卡不得继续暗示已经失效的authority。
  • FEISHU_APP_SECRET只来自Worker Secret binding,tenant access token直接复用Watt的isolate TTL cache并只进入Authorization header;D1只存tenant/chat/message ID、presentation digest和固定投递结果。token/token refresh/create/PATCH/GET直接复用Watt的10秒AbortSignal.timeout;token-invalid清缓存,限流与timeout分别只存feishu_rate_limited/feishu_api_timeout并保持原outbox pending,业务拒绝只存固定码。create使用最长50字符稳定UUID,PATCH只更新本应用发送且未撤回的共享卡;14天平台窗口到期后创建新message而不循环重试旧ID。
  • 人工刷新只允许operations identity以GET返回的current presentation/revision/digest发起strict CAS。刷新request与新presentation immutable且旧delivery不改写;API没有message ID、card body、destination、effect或reason字段,caller不能把修复入口变成任意飞书发送器。refresh epoch由服务端生成、参与digest但不渲染;pending request由cron恢复,避免HTTP/session中断留下不可见半状态。
  • retry history只在D1 lease update成功后写入,且只能是固定Feishu错误枚举;insert失败不阻塞或伪造retry,UPDATE/换outbox/换presentation由FK、CHECK、唯一键和immutable trigger拒绝。operations最多投影100条白名单标量;真实verifier同时重读当前refresh lineage和真实Message GET,manifest不能覆盖缺失或多余历史。token只进Watt-derived cache/Authorization header,raw响应、卡片正文和上游错误没有schema/serialization入口。
  • 飞书回读需要机器人仍在目标群,并显式授予消息读取权限;应用身份群消息按官方要求使用im:messageim:message:readonly并附加im:message.group_msg。GET只允许D1已知message ID,必须绑定配置chat、sender_type=app + FEISHU_APP_ID、interactive、未删除及latest canonical card digest。body.content与上游msg只在内存解析,D1 observation不含卡片正文。禁止用群历史的相似卡片补一个未知message ID,避免跨Run误认领。
  • 卡片展示evidence API不复用旧strict operations response,避免新字段破坏已有verifier。它只接受单一exact runId、operations Bearer和GET,最多100张strict v2;每张必须核对presentation/card/run、exact reference-only outbox和immutable lineage后才返回白名单snapshot。actions、application nonce、raw presentation_json、card JSON、正文/log/artifact/R2 ref、DB行和upstream error没有response字段。仓库外synthetic canary必须本身命中credential scanner;verifier在JSON parse前扫描控制面与飞书完整有界响应,明文命中立即固定secret_leak_detected,不打印原文或credential。
  • 真实试点verifier默认关闭,缺显式opt-in以exit 2结束且不发网络请求。PILOT_CONTROL_PLANE_TOKENPILOT_GITHUB_TOKEN只进入当前进程Authorization header;manifest、stdout/stderr、PROGRESS和示例文件都不得保存token。verifier不打印Zod issue、HTTP error、response body或manifest正文,只返回固定错误码/安全计数;GitHub token只需试点仓库Actions read与Deployments read,不能拥有contents write、pull request write或Environment管理权限。
  • pilot manifest是untrusted索引:runtime再次strict parse,repository/ID/SHA用于URL前都受pattern约束,证据URL必须HTTPS且无userinfo/query/fragment。success/failure/rollback必须用分离identity并由live GitHub/D1事实交叉核对;OIDC/reviewer/隔离/恢复URL只能提示人工核查,不能自动升级为部署成功或授权事实。
  • 七天试运行verifier遵循相同显式opt-in/固定错误码边界,并进一步分离SEVEN_DAY_TRIAL_OPERATIONS_TOKENSEVEN_DAY_TRIAL_GITHUB_TOKENSEVEN_DAY_TRIAL_OBSERVABILITY_TOKEN。manifest中的report URL是不可信输入;只有受控环境独立配置的exact HTTPS URL与其完全相等时才发送observability token,防止manifest把凭证转发到攻击者host。GitHub token只需试点单仓库Pull requests read与Deployments read,operations token只读Case 8报告;三者均不得进入manifest、argv、日志、artifact或PROGRESS。

3.3 监控 adapter

  • monitor入口默认关闭;三个required配置全缺时不启用,部分配置、短Secret、非法tenant/repository allowlist或越界窗口全部fail-closed。HMAC Secret只来自Worker binding,签名覆盖exact raw body且用常量时间比较;header、Secret和raw body不进入D1/R2/日志/错误。
  • strict body只允许固定firing alert字段,caller提交fingerprint、policy、effect、Task或approval字段在持久化前400。repository必须命中配置allowlist;source time最多过去24小时/未来5分钟。规范化snapshot在R2前扫描所有已配置Secret与credential形状,finding和响应不返回命中值。
  • suppression fingerprint由控制面从adapter/tenant/profile/rule/resource/repository/environment/severity派生,不采信monitor供应商自报fingerprint;event ID只做delivery幂等。相同event换内容冲突,窗口内不同event只增加candidate occurrence/immutable lineage;窗口exact edge仍合并,过1毫秒才开新candidate。
  • monitor candidate不是Task:表没有policy/effect/approval字段,producer没有Task intake、Run、Workflow或outbox调用路径。即使签名有效也只获得triage记录,不获得repo/log/database读取,更不获得repo write。人工提升必须走独立、可审计的人审与Task创建协议。
  • normalized title/description/resource只写私有R2,operations查询只返回安全adapter/tenant/repository/rule/severity、窗口、计数和时间;不返回正文、resource、fingerprint/profile/snapshot digest或R2 ref。candidate identity字段不可改写,聚合只允许occurrence+1与lastSeen单调前进。
  • monitor真实验收token按Cloudflare settings、observer、operations和Sentry read四种用途隔离,全部只通过环境注入且不进入manifest。verifier只做1 MiB有界HTTPS GET,在JSON parse前扫描全部token、credential形状和仓库外synthetic canary;拒绝分页、重定向、URL userinfo及响应泄漏。Cloudflare Secret binding只核对secret_text类型,不读取或比较Secret值;plain tenant/allowlist/window只在内存exact比较且不输出。exact-event operations响应用布尔表示私有R2回读/重算结果,不泄漏digest或对象ref。

3.4 tool-bridge

  • 控制面 broker SK 只存在 Secret store;Agent 永远拿不到 Admin SK。
  • 每个 attempt 生成短期 tool token:绑定 run/attempt/generation/TTL,按 path + action + effect 授权;当前由控制面PEP验证后再用Worker internal Secret调用上游,避免把Admin SK交给Runner。
  • 缺陷分诊默认仅只读;数据库通过参数化诊断工具暴露,不下发 DSN/Redis 密码。
  • 生产写、删除、任意 shell 属于 destructive,MVP 禁止授予。
  • POST /v1/attempts/:id/tools/authorize只接受tool-token digest并复用active status/generation/lease/revocation fencing;control-plane run token固定拒绝。path必须exact命中受信catalog,action/effect由服务端派生且triage只允许read effect;quota admission成功后才返回不可预测的server trace ID。/tools/observe只接受绑定同Attempt、同path admission的trace ID与metadata,拒绝arguments/result/error正文和identity漂移。/tools/call仅为GitHub Runner兼容lane保留同一PEP规则。
  • repo/write、k8s/apply、database/execute、shell/exec是catalog内已知deny capability。scope缺失或effect非read均留policy_denied metadata trace且不调用上游;即使D1 scope被污染为包含write/destructive action,独立effect gate仍拒绝。caller不能在body自报policy字段。
  • tool trace schema 只有 trace/run/attempt/path/action/effect/duration/result category/time,不提供 arguments、header、URL query、response 或 error-detail 容器。上游非 2xx 正文不读取;API 错误为固定类别,不能把工具或数据库原始错误变成 secret 回显通道。
  • service binding 的内部 token 只来自 Worker Secret binding;调用参数只存在本次内存/转发 body,成功结果以 no-store 返回授权 Runner,不进入 D1、Workflow event、console、artifact 或 PR。
  • Cloudflare Executor Worker持用途隔离的组织Tool Bridge SK;控制面、execution spec/grant、D1、日志、artifact和publisher都不得取得明文。SK只经startProcess.env进入trusted work Runner,Codex child environment显式删除DELIVERY_TOOL_BRIDGE_SKTB_SK。Sandbox internet只允许exact tool-bridge.fantacy.live,不开放任意外网;BaseURL必须等于固定HTTPS origin,tool path、tipsy-chat/prod/14天/20条不可由Agent覆盖。direct client使用redirect=manual、20秒timeout、256 KiB response cap,非2xx不读取正文,并拒绝schema/trace identity漂移、短假阳性trace ID和Secret reflection。
  • GitHub Runner兼容lane仍通过同账户delivery-loop-tool-bridge Worker持SK与internal token;控制面只持internal token且Runner拿不到SK。两条lane复用同一scope/effect/catalog和metadata trace语义,但不得互相fallback。SK scope固定为最小可调用Tipsy命名空间mcp/tipsy/**:read,call,不含其他MCP、write、register或admin。

3.5 人工 Task intake

  • POST /v1/tasks 默认关闭匿名访问;Phase 1 使用控制面 Secret binding 中的 Bearer 服务凭证,后续可替换为组织 OIDC/mTLS,不接受 body 内自报身份代替认证。
  • .github/workflows/guarded-task-intake.yml是当前唯一fresh试点manual operator,只允许owner、protected main、run_attempt=1且串行执行。零Secret preflight从GITHUB_EVENT_PATH读取Task并校验;effect job必须经过phase1-readiness Environment,Task正文仍只从event file读取,workflow/step env、argv、run-name和输出中都不得出现${{ inputs.task_json }}或派生正文。Task bearer只用于控制面Task GET/唯一POST,内建GitHub token显式限制为contents:read + actions:read并只用于集中executor repository的完整stable-title inventory;二者原文必须不同。目标业务repository/base/environment与test-deploy policy必须逐字段命中operator内置受审allowlist,不能由Task把inventory切换到业务repository。operator固定10秒/每页1 MiB/per_page=50/最多20页边界、拒绝redirect、parse前扫描两枚token;分页不跟随GitHub可能切换为numeric-repository path的Link,而是用每页稳定total_count和本地固定URL递增page并要求最终seen一致。只有Task 404且analysis Action为0才允许一次POST;任何不确定结果都不自动rerun、repair或创建第二Task。
  • intake前的GET /v1/operations/github-base/readiness使用独立OPERATIONS_TOKEN且只接受exact repository/baseBranch query;Task token、Runner token、GitHub token均无权调用。探针复用当前Worker真实GitHub App resolver,只执行App JWT→repository-scoped contents-read installation token→exact ref GET,不读取或写入D1/R2,不创建Task/Run/outbox/Workflow/Action。配置与reference继续使用configuration_unavailable|reference_unavailable|reference_invalid;GitHub App provider公开credential_signing_unavailable|credential_unauthenticated|credential_forbidden|credential_installation_not_found|credential_policy_rejected|credential_request_invalid|credential_transport_unavailable|credential_upstream_unavailable|credential_response_invalid九个当前固定凭证阶段,并只保留credential_auth_rejected作为历史兼容值;未知provider异常才使用兼容兜底credential_unavailable。收到HTTP响应前的transport失败、401、403、404、422与5xx分别转换为上述固定枚举,不公开raw status/body;App JWT、private key、installation token、upstream body和raw error均不得回显或记录。GitHub要求所有REST请求带有效User-Agent,因此Worker的token签发/撤销、base ref/compare及Actions query/dispatch统一显式发送固定非敏感值delivery-loop-control-plane,不依赖Node/undici等运行时默认头,也不把Task/repository/credential拼入该值。控制面GitHub客户端的默认fetch统一用闭包调用globalThis.fetch,避免client实例成为Web API foreign receiver;测试注入fetch不被包装或替换。readiness成功不是Task POST、dispatch或部署authority,失败也不授权重试已消费的Task请求或任何repair/restart/rollback。
  • readiness的仓库内caller必须显式opt-in并按实例最多一次GET;非敏感配置缺失在读取token前exit 2,任一配置缺失都在network前exit 2。它固定exact query、10秒timeout、redirect拒绝、1 MiB响应上限、no-store与JSON content type,unexpected HTTP status不读取body;200/503正文都在parse前以operations token和credential形状扫描。transport错误只读取allowlisted name/code/cause并输出固定timeout/DNS/TCP/TLS/generic类别,raw error、host address、token和响应正文不进入stdout/stderr、D1、artifact或账本。caller诊断、DNS/TCP/TLS无HTTP preflight及不同host对照都不授予第二次readiness或任何effect。
  • production credential_transport_unavailable的具体failureKind只能通过独立owner authority下的GitHubAppTransportDiagnosticEvidenceManifestV2只读验收。verifier固定绑定repository owner、main上的.github/workflows/github-base-readiness.ymlworkflow_dispatch + attempt 1、exact失败job window、当时最后生效的100% Worker deployment、唯一strict diagnostic和同一Worker invocation;窗口起点至终点出现任一新deployment即拒绝。公开503、mock sink、manifest字段、example或旧v1 trace假设都不能替代production log/invocation事实。
  • GitHub Actions read、Cloudflare deployment read和Cloudflare observability query三枚token必须原文互异且只进各自Authorization header;account ID只经环境进入请求路径,manifest和成功summary只保存digest或省略。telemetry固定dry=true、exact job timeframe、一次events与一次invocations查询;所有响应1 MiB/10秒有界并在parse前扫描三枚token、credential-shaped canary和凭证形状。GitHub signed log redirect不转发Authorization。CLI不输出raw manifest/log/invocation/error、account ID或带query URL;exit 0也不授权credential/Secret/installation修改、Worker发布、readiness rerun、Task/Action/repair/restart/recreate/rollback。
  • transport diagnostic collector读取仓库外64 KiB strict request但不把它当authority;一次且仅一次发送不带invocation ID filter的events query,仍固定service/event/component/operation/requestAttempts、受验collection ID queryId、Unix毫秒exact window、顶层limit=2dry=true。它要求三枚read token互异并用三者扫描响应,只有observability token进入请求header;403/timeout/无唯一strict log均fail-closed且不重试。provider 200后的0条、多条、envelope、source与time不匹配只允许转为cloudflare_log_absent|cloudflare_log_ambiguous|cloudflare_log_envelope_mismatch|cloudflare_log_source_mismatch|cloudflare_log_time_mismatch五个固定类别,不输出count/raw字段或响应。成功输出仅含安全identity、16位invocation ID、时间、allowlist failureKind和log digest,并固定formalVerification=still_required;不得生成human review或替代formal verifier。若同一authority覆盖两阶段,必须显式计入collector的一次events和verifier自己的另一次events/一次invocations,不能用“collection+verification”隐藏重复读取上界。
  • Workers Observability read credential provisioning是独立Cloudflare credential写,不得从transport collection authority、deployment-read token或代码合并推导。显式CLI只接受仓库外0600、最长30分钟且canonical digest绑定的authority;bootstrap token必须来自Cloudflare Create additional tokens模板并由具备Super Administrator的owner提供。工具固定先查Keychain空槽,再以per_page=50&include_expired=true完整inventory和exact name/account-scope动态解析唯一Workers Observability Read permission group;create body只能含目标account一条allow policy。Cloudflare真实4xx在约2小时、24~25小时、7天TTL及50/64字符target上保持相同,删除optional not_before后的live create仍为4xx且安全provider code仅为通用400,故不能再把失败归因于TTL、名称或该字段。官方create runbook要求TTL wire format为UTC整秒;新authority只接受YYYY-MM-DDTHH:mm:ssZ的target expiry,仍须在authority窗口结束后至少存活7天、且从authorizedAt起总TTL不超过7天30分钟。新secret只允许出现在create result.value一次并只经stdin交给固定Security Framework helper,helper以SecItemAdd拒绝覆盖;随后新token各执行一次verify与dry=true极窄telemetry probe。每个API/Keychain stage最多一次,create POST一旦尝试后的任何不确定状态统一created_unverified且不自动delete/overwrite/retry/rotation/rollback。token-create可以附加且只能附加transport_unavailable|auth_rejected|request_rejected|rate_limited|upstream_unavailable|response_invalid固定failureKind。非2xx body只允许在1 MiB/10秒边界内读取一次,parse前扫描bootstrap/account/canary/credential shape;只有标准错误envelope里的唯一非负安全整数可输出为cloudflareErrorCode,message、raw status/body/header、request字段、多码/非法码或命中Secret的body全部丢弃。failureKind或数字code都不能当作未创建或retry authority;完整边界见Cloudflare Workers Observability credential provisioning
  • provisioning create POST进入created_unverified后,不得重用已消费authority或直接发第二次create。独立post-create reconciliation authority必须绑定source provisioning authorization/digest/authorizedAt、exact account digest、token name、nullable not_before expectation与expiry,且effect恰为完整token inventory GET 1、其余permission/keychain/verify/telemetry/create/delete/retry全0。只在单页完整inventory中允许present|absent;同名多枚、lifecycle/status漂移、分页、Secret响应或raw错误均fail-closed。present不恢复一次性secret,absent不自授权replacement;后续保留、撤销或替换仍需新决策。完整边界见Cloudflare Workers Observability credential post-create reconciliation
  • reconciliation只证明exact target present/active且固定Keychain槽存在时,若原provisioning stdout已丢失,必须用独立最长30分钟的已有Workers Observability credential再验证 authority补足实时事实。该入口固定Keychain read 1、account-token verify GET 1、dry=true telemetry POST 1,inventory/permission/create/Keychain write/delete/rotation/retry全0;verify返回的token ID只在内存中重算并匹配authority digest。固定security find-generic-password -w子进程的stdout有2,000-byte上限且不向上游传播,credential不进入env/argv。两次Cloudflare请求复用provisioning的10秒、1 MiB、redirect/pagination拒绝、parse前Secret scan与strict envelope/parser;任何identity/status/probe漂移立即停止。失败只允许transport_unavailable|auth_rejected|request_rejected|rate_limited|upstream_unavailable|response_invalid或独立secret_leak_detected安全分类,不回显raw status/body/message且不授权retry。exit 0仍不执行历史collection、readiness或其他effect,只允许后续签发独立immutable collection authority。
  • Workers Observability telemetry query必须以固定Cloudflare OpenAPI事实为准:ad-hoc query仍要有queryIdtimeframe.from/to是Unix毫秒,events/invocations row的limit是顶层字段,filters等查询内容才位于parameters。provisioning/reverification以authority ID作为queryId,collector以collection ID,formal verifier以evidence ID与view的受验组合;三者都只在内存中转换时间。event的截断事实必须取自provider响应$workers.truncated,不存在的$metadata.truncated必须fail-closed而不得伪造false。$metadata.type在provider schema中是非枚举字符串;Round 269生产event固定为cf-worker,且没有traceId,关联身份必须严格来自相同的$metadata.requestId/$metadata.rayId/$workers.requestId。旧v1的cf-worker-log + 32位traceId、ISO timeframe/缺queryId/$metadata.truncated与Round 260的parameters.limit中间假设均不能覆盖provider contract。shape修正仍不授权retry已消费authority,必须受保护交付后使用fresh authority。
  • Idempotency-Key 不作为授权凭证,D1 只保存其 digest;认证 header、key 原文和非法 Task 正文均不得进入错误响应或日志。
  • Task 完成 schema 校验后、计算 identity 或写 D1/R2 前,扫描 Worker 当前配置 Secret 与 credential 形状;命中时固定拒绝,不在 finding/响应中返回匹配值,也不产生 Task/Run/outbox/R2 对象。
  • 原始规范化 TaskEnvelope 只写受控 R2;Workflow-create outbox 和 API 响应只含 Task/Run 引用,不含需求正文或凭证。
  • Phase 1 的 Task/Plan GET 查询使用同一服务认证且只公开 D1 白名单投影。禁止返回 Task description/原始 acceptance criteria、checkpoint summary/nextStep/payload ref、Evidence summary/artifact ref、lease token digest;外部 URL 移除 query/fragment,避免签名参数或 token 进入响应。
  • 外部 x-correlation-id 仅接受 UUID;不符合格式时生成新 UUID,禁止把任意 header 原样带入错误响应。

3.6 高风险审批身份入口

  • POST /v1/runs/:runId/approvals使用独立APPROVAL_ADAPTER_TOKEN,不复用Task intake、Agent、GitHub Actions或tool-bridge token。这个凭证只授予已验签GitHub/飞书adapter提交最小身份事实的能力,不授予adapter自报人的principal、role、Plan digest或base SHA。
  • request strict且最大8 KiB,只接受provider/tenant/event ID/external subject/event digest/time与Run version/Plan version/effect/decision/expiry。actor、author、task revision、Plan ID/digest、base、roles均从D1派生;extra field在持久化前拒绝。source表只保存digest和白名单标量,不保存GitHub/飞书原payload、卡片正文或token。
  • IdentityMapper直接复用Watt的双表解析:channel_identities隔离GitHub repository和飞书tenant,identity_mappings每次实时返回roles。未映射为anonymous;只有human + approve:<effect>且不是agent:*/service:*可产生高风险decision。PR作者从只读GitHub observation获得login后再映射;GitHub与飞书落到同一principal即视为同一人并拒绝自批。
  • merge/production authority不等于approvals表存在一行。消费者必须通过trusted_effect_approvals重验approver/author当前渠道映射、live role与分离关系;role撤销或映射改变无需改写历史记录即可fail-closed。source、accepted binding和identity rejection均immutable且同event只能有一个outcome。
  • external decision与权限判断分层:approval_lineages只做append-only审计,在approval写入的同一batch冻结已验签provider事件/卡片receipt、principal/roles、Task/revision、Plan/digest、base/effect/decision及两个时间;唯一约束和shape trigger阻止一个event关联多个approval或伪造snapshot。它不缓存未来权限,effect仍须经过trusted_effect_approvals重验live mapping/role/separation/expiry/invalidation。
  • P0 quota override走同一独立adapter身份入口但使用单独approve:quota_override role;P0 priority本身不授权扩容。source必须绑定Run所属飞书tenant或GitHub repository、exact Run version、唯一资源集合、reason digest与最长4小时expiry,批准人必须是非Task requester的human,不能是agent/service。multiplier固定2且不可由body指定;self/未映射/缺role/跨tenant或repository/stale decision均拒绝并保留安全outcome,不能借紧急优先级获得无限预算。

4. Secret 生命周期

  1. Secret 只存 GitHub Environment/云 Secret manager/控制面 Secret binding。

  2. dispatch、飞书卡片、TaskEnvelope、prompt、checkpoint、PR 和 artifact 不含 Secret。

  3. Cloudflare Workflow input、step result、waitForEvent payload 和 instance metadata 不含 Secret、完整 PRD、原始日志或数据库行。

  4. Runner 通过OIDC一次交换用途隔离的run/tool短期凭证;凭证不写磁盘、不加入子进程全局环境,按命令最小注入。两个明文只存在Runner内存,upstream internal/Admin Secret永不离开Worker。

  5. 日志/响应输出前做 schema-aware redaction:敏感 header/字段整体替换,嵌套 JSON 递归处理,URL userinfo/query value 替换并移除 fragment,命令环境变量按 key/value 脱敏;所有Worker credential从唯一configuredSecrets catalog取得,控制面日志只允许一个结构化console sink且在redaction后再次scan,Runner入口只写固定event/outcome的一行JSON;用 canary Secret 自动测试泄漏。

  6. Task、checkpoint、artifact、PR 等持久化/发布 producer 在写入前运行统一 scanner;finding 只保存安全的 path + kind,不能再次携带匹配值。checkpoint scanner 还注册当前 opaque attempt token,必须在任何 D1/R2 写入前拒绝;生产源码与 workflow/migration/schema 另跑静态 credential scan。

  7. attempt 取消、超时、失败或完成立即撤销共享 credential grant;run/tool 两个 token 同时不可用,broker记录撤销结果。

  8. attempt write lease 的明文 token 只返回一次给 CAS 胜出的 Runner;D1 仅保存 SHA-256 digest。heartbeat/写入同时校验 version、lease generation、digest 与 expiry,过期 lease 被新 generation 接管后旧 token 即使重新联网也不可写。

  9. Runner heartbeat每次成功都原子轮换run/tool两个opaque token及digest;两个旧token都不存在宽限期。同batch的immutable heartbeat receipt只含identity/version/time/lease标量,表结构没有token或token digest字段;查询最多返回1000条并拒绝超限。complete请求不接受githubStatus/githubConclusion等自报外部事实,只能提交受控Plan ref/digest,且共享grant在result/outbox原子入账时撤销。

  10. cancel 与 running heartbeat timeout 同事务递增 generation、清 lease并撤销该 Attempt 全部 active token;reference-only revocation audit 不保存 token。watchdog每分钟运行,running 90秒判定同时绑定Attempt status/version/generation与Run state/version,token TTL仍必须先满足expiresAt <= leaseExpiresAt,不能依赖扫描器延后失效。唯一completion-pending保护要求implement/review_fix已有受信GitHub completed/success、同head completed suite、passed commit与passed test Evidence,并在候选选择及最终mutation CAS重复核对;它只阻止把已成立的成功事实降级为lost,不恢复token或接受Action自报。缺任一内部事实仍按timeout fencing。queued/review/deploy超时只执行requeue、人工升级或外部事实reconciliation,不把时间流逝伪造成审批拒绝或部署失败。

  11. run_stuck_incidentsrun_stuck_detected/resolved日志只允许incident/run/attempt ID、状态/version、阈值、固定action/resolution和时间。Task/PR正文、query/URL、payload/ref、token、外部响应与raw错误均无字段;日志sink失败不影响D1 durable alert,20路scan以stable identity/CAS收敛。

  12. checkpoint 写入需要独立 checkpoint:write scope,并绑定 active plan/version/item、Attempt version/generation/lease 与 head SHA;完整 payload 进入私有 R2,D1 只保留包括脱敏 summary/nextStep 在内的安全恢复投影,不保存 provider session ref、completed criteria 或 Evidence ref 数组;查询响应只公开 plan/item/head/digest 元数据,不公开 summary/nextStep/R2 ref。恢复读取重新计算 canonical digest,旧 plan 或篡改 payload 不进入新 Attempt。

  13. GitHub repo_write token只在no-store响应与Runner内存中以明文存在。为durable revoke保存的ciphertext必须以credential identity作AES-GCM additional data;revoked/expired后立即清空,日志、错误、audit、checkpoint、artifact和PR永不记录token或ciphertext。

  14. 高风险path gate只持久化Git tree/content绑定digest和安全name/status/numstat;原始patch、文件正文(包括.env*值)不得进入D1、Workflow、outbox、HTTP响应或artifact。审批必须针对exact diff digest,不能把已有repo_write effect approval当作高风险路径批准。

  15. verification Evidence只保存canonical command ref、exit code、durationMs、head SHA与固定summary,不保存stdout/stderr、测试日志正文或Agent结论。新Evidence一律unverified;exit 0只是执行事实,只有独立服务端doneWhen decision才能把required Item置passed。

  16. Draft PR正文只由控制面从digest核对后的Task结构字段、active Plan、verified decision/Evidence和immutable bot head派生;不发布Task description、Evidence summary/output、原始日志/数据库行或Agent自由文本结论。自然语言统一转义Markdown/HTML/@mention;来源URL含userinfo时不发布,否则移除query/fragment并编码Markdown括号。输入与最终正文均执行Secret scan,命中或超过65,536 UTF-8 bytes时不写D1;GitHub processor在真正list/create effect前还必须按当前完整Worker Secret catalog重扫title/body,命中只结算固定pull_request_secret_detected且零GitHub调用。prepared正文与验收/Evidence/未完成项snapshot不可UPDATE,且不能被当作GitHub PR外部事实。

  17. PR publication/outbox不复制正文,只引用prepared draft;REST create响应只保存候选number和无userinfo/query/fragment的HTTPS URL。webhook/API observation只保存payload/fact digest与白名单标量,raw payload/response/body/token不落D1;只有exact external projector生成固定summary Evidence。错误响应不含GitHub response body、正文、App key或token。

  18. Review feedback在验签/schema/head fence后仍按不可信数据处理:先以全部Worker配置Secret和credential形状扫描,命中时D1/R2/Attempt零写入;完整body只进私有R2,D1只保存ref/digest和安全lineage。Runner回读必须复验R2 metadata/schema/canonical body digest,context以no-store只交付active exact Attempt;dispatch、outbox、日志、Evidence和PR正文都不复制review body。

  19. 模型profile ID由Worker可信配置经固定workflow注入;D1 profile保存model、token上界和整数micro-USD价格,Task/PRD、Agent输出和tool结果没有价格或limit字段。reservation/usage时间统一由控制面接收时生成,Runner不能回填旧UTC日期或未过期override时刻;API extra occurredAt严格拒绝。

  20. Codex --json stdout按行流式消费且不保留。只持久化官方turn.completed.usage的input/cached/output/reasoning四个计费数;锁定的Codex 0.145.0额外发送cache_write_input_tokens,只允许非负整数并在进程内丢弃,其他未知usage字段仍fail-closed。thread ID、Agent message、reasoning、command/file/tool/web/search/plan事件、原始stdout和模型response均立即丢弃。D1只写per-call usage标量/source digest;查询不公开prompt、response、tool参数或raw错误。

  21. GitHub repository Secrets OPENAI_API_KEYOPENAI_BASE_URL只在固定workflow的Agent step或无Task的手动provider preflight分别映射为CODEX_API_KEYOPENAI_BASE_URL;把base URL放入Secret是更严格的存储边界,不把它变成凭证通道,其中仍不得包含key、userinfo、query或fragment。validated URL只进入共享custom provider的base_url override;profile固定requires_openai_auth=true并从进程环境读取CODEX_API_KEY,不得配置env_key、静态bearer token或header中的key。profile同时固定Responses与supports_websockets=false,避免中转被内置OpenAI provider的WebSocket能力改变transport。两枚Secret都不进入dispatch input、控制面、checkpoint、artifact、PR或日志;preflight安全结果只留RUNNER_TEMP且不上传,Agent子shell继续由environment policy排除*KEY*/*SECRET*/*TOKEN*/*PASSWORD*

  22. 第三方模型中转是独立数据处理信任边界:即使URL通过公网HTTPS和host校验,中转方仍可能看到Task、代码、日志摘要、prompt及模型输出。接入前必须由owner确认其Responses API兼容性、exact model支持、数据保留与访问政策;中转响应仍按不可信模型输出处理,不能提升Plan effect、命令或credential authority。

  23. provider preflight只允许把已按敏感环境值脱敏且最多8 KiB的CLI stderr映射为12个固定失败枚举;分类器不返回原文。provider_stream_interrupted只匹配Codex官方stream disconnected before completion或同一行明确带Responses/SSE stream语义的提前close/end/interruption,必须先于普通network分类;裸connection closed/reset不能被提升成stream,未知或恶意文本只返回provider_process_failed。raw stderr、第三方响应、URL、credential及其摘要不得写入Action log、artifact、manifest、D1或PROGRESS;分类枚举仅用于决定是否需要owner输入或受控修复,不构成provider成功证据。

  24. provider network preflight只读取OPENAI_BASE_URL,不能读取API key、启动Codex、向provider发送HTTP或上传artifact。它与三个adapter共用同一URL parser;DNS结果还必须至少包含一个公网地址,私网、loopback、link-local、documentation、multicast和reserved地址不得进入socket。TCP直接连接受控DNS结果以避免二次解析/rebinding,TLS仍以原hostname做SNI及系统CA/hostname校验。Action日志只允许固定code和三个布尔值,不允许hostname、IP、URL、证书、底层错误或digest;该诊断workflow只有contents:read且没有input/Environment/OIDC/write。

  25. provider Secret等价诊断只允许用一次性32-byte随机proof key,分别对OPENAI_API_KEYOPENAI_BASE_URL的exact UTF-8字节计算field-domain-separated HMAC;proof key与两份期望proof都只能以短期repository Secret进入固定只读workflow,期望/实际proof、credential、URL及其长度不得进入日志、artifact或持久状态。比较使用常量时间,每项只输出固定match/mismatch/invalid枚举,不调用provider、Codex、控制面或模型。外部run结算后立即删除三枚proof Secret;两项match只排除GitHub Secret字节漂移,不能证明provider可用、Responses stream完整或hibernate成功。

  26. control-plane真实hibernate窗口包含一次production D1 migration和两次production Worker发布,三者都需要明确且分离的生产授权;readiness只读检查或一次授权不得自动扩展到后续动作。多账号Wrangler命令显式绑定受审account ID,Sol/high migration必须先于引用它的before Worker,发布固定--strict并冻结main SHA、bundle digest、100% deployment/version和安全binding投影;远端漂移即停止。before版本只作为人工rollback anchor,rollback仍是新的production写权限,不能由失败、文档命令或Agent自批。只为上线readiness路由的窄before session也必须绑定exact source、bundle bytes/digest、当前deployment/version和固定message:clean source双build一致后才允许一次--no-bundle --strict,新deployment必须ID不同、时间单调且100% traffic;bundle路径漂移、publish后观测失败或随后readiness transport/HTTP失败都不获得第二次deploy/GET、Task、repair、Secret rotation或rollback authority。由于固定analysis Runner在Plan提交后立即callback,after只能获得绑定exact before/source/bundle/Run/Attempt的conditional authority:两次最多5秒陈旧的live guard必须同时证明唯一未完成Attempt、唯一active Action、零result signal、active wait和零wait内deployment,任一漂移在Wrangler前fail-closed。guard参数和本地测试本身不产生production authority。live CLI还要求30分钟内的仓库外0600 authorization/Task、canonical authority digest及五枚互不相同的用途凭证;digest只防文件漂移,owner外部批准与本次deploy credential注入才是authority。文件在parse前有界读取并扫描Secret,HTTP token只进对应header,deploy token只进单次Wrangler环境。冻结bundle只在内存和仓库外0600临时文件存在,以--no-bundle --strict上传精确bytes;每条Wrangler命令固定临时空--env-file和隔离HOME/XDG,不能加载ignored dotenv或本机OAuth。adapter实例最多一次Task POST和一次deploy,Wrangler raw输出丢弃。after post-check必须证明100%新version、wait内恰好一个deployment且创建时间早于wait结束;失败不得自动rollback、重建Task/Action或重发after。纯函数guard、CLI默认exit 2、healthz或dry-run都不能冒充live collector、dispatch或Workflow恢复成功。

5. Prompt Injection 防护

  • 系统策略与用户任务分离;外部内容使用带来源、时间和 digest 的引用块。
  • Agent 生成的 ExecutionPlan 是不可信提议:控制面校验依赖、命令引用、effect、base SHA 和 Evidence 要求后才可进入审批或执行。
  • Plan Item领取是控制面D1/CAS操作,不是Agent工具。scheduler只晋升依赖全部passed的Item,claim前按exact Run/Plan/progress version再次核对;有界候选limit在Item shape、依赖、Task policy与当前approval有效性过滤后应用,旧Run不能靠无可领取Item或失效authority饿死新Run。Free-plan Cron的早期D1-only ready claim仍执行相同SQL authority/CAS/稳定identity,只改变调度优先级,不激活awaiting Run、不读取不可信正文、不签发credential或直接dispatch外部Action。claim body strict且没有status/skip字段,稳定claim identity和数据库唯一约束防止并发创建多个Attempt。
  • Runner complete/failure schema拒绝planItemStatus等额外字段,Agent没有D1凭证,Attempt结束也不会自动把Item标为passed。required及全部investigation/verification Item的skip由D1 trigger硬拒绝;passed只由服务认证Evidence verifier在exact decision/mapping存在时写入,Agent自报不能解锁依赖。
  • Agent 读取到“忽略规则、上传 Secret、关闭测试”等内容时只能报告,不得执行。
  • tool-bridge 返回的 effect 与本地 action allowlist 是外部强制策略,不接受模型自报 effect。
  • 当前 PEP proxy 不信任 tool-bridge/模型回传的 effect,而以版本控制内 catalog 为调用前上限;Watt help 的 effect 只可用于发现/一致性核对,不能提升权限。
  • 默认禁止修改 .github/workflows/**、CODEOWNERS、分支保护、部署脚本和 Secret 配置;任务确需修改时,Git staged-tree gate在commit前自动把Run置awaiting_approval并列出安全diff摘要。repo_write approval、Agent文本或工作树内被改写的delivery.yaml都不能旁路这次独立审批。
  • 不允许运行来自任务正文、评论、日志、代码注释或Agent output的任意命令。调用者只能提交完整匹配setup:<id>test:<id>verify:<id>的引用;ref suffix、caller argv/stdin/env和未知ref在进程创建前拒绝。
  • delivery.yaml只从dispatch已绑定的exact 40位base SHA读取;工作树、PR分支或Task提供的同名文件不能覆盖本轮policy。命令以结构化argv和timeoutSeconds进入共享execFile/spawn runtime,固定cwd为目标仓库且shell: false
  • verification runner不接受“测试已通过”的模型文本,只执行Plan绑定的targeted refs并自动补全policy全部required verify。D1 suite ledger拒绝required-before-targeted、跳position、失败后继续和同Evidence改写;因此模型不能靠伪造顺序或省略全量验证推进。
  • policy输入最大64 KiB并按strict schema解析;YAML alias/merge、重复key、未知字段、NUL、路径穿越、非法绝对路径和不完整deployment contract全部fail-closed。解析对象递归冻结并计算canonical digest;受保护路径至少包含policy本身、workflow和CODEOWNERS。
  • analysis Codex CLI 强制 read-only sandbox、approval never、ephemeral session,并禁止读取目标 repo AGENTS.md 作为高优先级指令;外部 task/context/code 只作为stdin中明确分隔的不可信JSON数据。Runner动态生成的0600输出schema强制顶层context proof envelope,嵌套Plan不含identity/digest/status;可信 Runner核对proof并注入identity后再由policy validator裁决。
  • writable Task的模型外Plan validator不允许Agent把本轮已完成的仓库调查留成required investigation,或让required self-verifying change依赖investigation。该门禁只读取trusted requiresRepositoryChange与Plan拓扑,不把investigation自动标为passed、不制造Evidence或扩大repo_write;read-only调查和不参与required执行图的optional investigation仍保留原边界。
  • attempt context API 虽返回原始反馈/PRD,但仅对 active token + exact Attempt/lease/scope开放,并在读取时重新核对 D1/R2/canonical digest;响应 no-store。Plan API strict schema 拒绝 Agent 自报 identity/status/digest,effect/command ref 由 server policy 上限裁决。
  • analysis replan context的revisionSource只来自Attempt直接绑定的plan_revisions,或其immutable plan_revision_analysis_retries当前retry lineage,或新Task Run绑定的supplemental_context_revisions。retry不会改写初始Attempt快照;只有当前failed analysis已有trusted failure、未产生Plan、无active blocker且未耗尽通用失败预算时才能创建一个稳定后继,已有proposal、旧retry或调用方自报lineage均fail-closed。review正文、supplemental正文和新Task snapshot均重新核对D1 ref、R2 metadata/schema与canonical digest;base update重新计算规范化fact digest。普通首次analysis可以没有source;已绑定revision的source缺失、双source或篡改一律fail-closed,Runner strict schema不允许控制面响应夹带未知能力字段。
  • Prompt injection的拒绝不能只依赖模型:Task criterion必须由 required Item覆盖;change必须以self-verifying required Item绑定repo_write + test:* + trusted verify:* + commit/test Evidence,或有依赖它的required verification绑定trusted command和对应Evidence。optional/detached verification、自然语言 shell、越权 effect全部在模型外拒绝,合法 Plan也只进入 awaiting_approval
  • “需要改仓库”也不能依赖模型自觉或正文关键词:控制面仅以可信typed requirement|bug + allowRepositoryWrite派生requiresRepositoryChange,Runner和D1持久化前的validator都拒绝纯investigation及缺repo_write/test:*/verify:*/commit+test的提议。当前试点command refs与受信base的delivery.yaml由漂移测试绑定;它们不从Task/Agent输入取得。该effect只进入Plan审批面,analysis OIDC/grant/sandbox仍无repo write,真人批准前不会签发GitHub写token。
  • 测试部署同样不能由Agent文本自提权:只有D1/R2重算一致的Task同时满足allowRepositoryWrite + allowTestDeploy + environment=test才派生requiresTestDeployment。Runner从Task再派生并与context逐字段比对,控制面保存Plan时从D1再次派生;任一漂移、缺deployment Item或Item不是required delivery + only test_deploy + no command + deployment Evidence/fact + direct change dependency都在effect前拒绝。该Plan声明不向analysis/implement Runner下发云效或部署凭证,部署仍要求独立latest exact approval与控制面scheduler。
  • Agent Plan在Runner出网前扫描全部OIDC/attempt token历史与敏感环境值,在控制面D1写入前再次扫描当前token、Worker Secret和credential形状。任一边界命中均固定拒绝且不回显;任务、日志、tool result或代码注释复制出的Secret不能进入Plan、D1、complete或Workflow event。
  • Plan revision source与Plan proposal分离:review/飞书/Meegle/GitHub adapter先验签、绑定旧Plan/base并写reference-only immutable source fact,调用方提交的ref/digest/base不能自行成为事实。revision启动立即撤销旧Attempt token/credential并显式invalidate旧Plan approval;所有审批消费者除exact plan/version/digest/base/effect外还必须排除统一invalidated_approvals视图(Plan revision、base history conflict、base rebase conflict三个ledger)。新Plan仍经模型外schema/DAG/command/effect validator且重新人审,不能继承旧approval或靠改D1旧Plan正文提升权限。request_replan reporter只对transport、409、5xx或无法验证的响应最多发送3次完全相同的fenced POST,401/403和其他拒绝不重试;每次请求仍在同一个serialized authorization临界区内,不能重新交换token、调用模型、写Git或改变body。服务端对已提交后响应丢失的恢复只接受原expiry内exact revoked token和原version/generation并只读返回既有projection,不能恢复token/lease、创建第二source/revision/outbox或调用其他endpoint。
  • Attempt completion的sequence只在单个Attempt内单调;workflow_signals(run,event)(run,Attempt,sequence)双重唯一约束,允许同一Run的initial analysis与后续re-analysis分别合法提交sequence 1,但禁止跨Attempt冒用event或在同Attempt改绑sequence。prepared Plan revision恢复只接受D1中exact current revision、latest analysis Attempt、validated replacement、Attempt result projection和durable signal的完整一致绑定;它不读取正文、不重放模型、不恢复旧approval,也不把GitHub Action状态提升为authority。
  • GitHub review replan入口只接受active Attempt token与expectedVersion + leaseGeneration;签名review producer预先冻结expected Run version,endpoint从D1 lineage派生source ref/digest/base并把source insert与旧执行fencing放进同一batch。Agent不能提交Plan正文、source/ref/base/effect或选择source kind;stale review head、Run/Plan、lease和verification-repair lineage都在source fact之前拒绝。
  • GitHub base observation没有公网/caller mutation API。scheduled adapter使用独立、单仓库、只有contents:read的installation token,并要求ref head与compare relationship两条GitHub事实共同成立;单一SHA、caller提交base、behind/diverged、compare merge-base漂移或Run/Plan版本变化都不能创建source fact。non-fast-forward只写immutable白名单fact并原子blocked/fence旧执行,raw REST body和token不落D1/log,错误只返回固定类别。
  • 自动rebase不是任意Git能力:只有base-only Plan revision、旧Item verified head、新Plan fresh approval、未发布source branch与ready/dependency gate同时成立才创建Attempt;任何PR publication记录都在GitHub effect前排除。Runner只接收D1绑定的SHA/Attempt派生branch,要求clean tree、old→new纯祖先关系、source线性bot commits,固定禁hook/autostash/GPG;Codex不参与该路径。
  • rebase本体没有push/force argv;成功callback只能使用approval-bound单仓库credential把新的Attempt派生branchnon-force push,远端同名branch前进由Git拒绝。head CAS成功后才允许新suite,旧Evidence不可继承。冲突只有在abort成功、source未变和工作树clean后才可调用fixed conflict endpoint;该endpoint不接受文件名、patch、message或caller状态,并同时撤销新approval、写reference-only Attempt revocation audit。为处理终态提交后响应丢失,已撤销token只可在原expiry内以原version/generation读取同一blocked投影,不可调用其他endpoint或恢复权限;半完成rebase、错误token、Agent文本、Git错误或旧Evidence都不能成为安全恢复事实。
  • merge observation与merge mutation用途隔离:只读token仅含contents/checks/statuses/pull_requests:read,不能dispatch、push、改PR或merge。adapter将branch rules、checks/statuses和reviews缩成strict事实;raw body、review正文和token不落D1/log。required policy缺失、分页/响应不完整、unknown mergeability与任何binding漂移都fail-closed。
  • ready-to-merge decision同时绑定Run version、active Plan/digest/base、verified publication/current bot head、全部required Item、immutable GitHub observation及latest exact merge approval;PR作者login经github:<repository>映射,审批subject经其GitHub/飞书channel映射,只有当前仍有human/effect role且principal分离的identity-bound approval可用。失效/过期/reject/未解析/自批approval不能回退旧批准。最终SQL再次核对全部gate。decision本身没有GitHub effect或outbox,避免把“资格满足”误当“已经合并”;若未来拍板自动merge,producer仍必须另用独立write token、idempotency与外部projector。
  • 当前MVP不申请merge写token,也不调用GitHub merge API;真人/受保护平台完成merge后,HMAC webhook为主事实,API补偿复用现有contents/checks/statuses/pull_requests:read merge-observation token。projector只接受exact ready decision后的closed + merged=true,绑定repo/PR/publication/head/base/Plan并保存merge SHA;raw webhook、REST response和token不入D1/log,错误不传播响应正文。
  • merge fact只能先驱动ready_to_merge → merging。no-deploy和test target可继续succeeded,但test只因merge gate已经证明其deployment/acceptance required Item全部verified passed;production必须停在deploying等待merge-SHA-bound平台事实。该裁决来自Task target/allow flags与active Plan effects/required progress的交集,不能由webhook、PR标签、Agent或调用方自报;不一致policy fail-closed。
  • production approval只在exact merge事实之后成立。approval adapter body没有revision/merge/environment字段;控制面从runs + tasks + active execution_plans + github_merges派生并冻结task_revision + merge_id + merge_sha + productiontrusted_effect_approvals的production分支必须join immutable release binding、merge ledger、两侧identity mapping与live human + approve:production_deploy role;无merge、旧Run/Plan、裸approval、自批、role撤销、过期/reject/失效均在D1 intent或GitHub effect前拒绝。
  • production deployment使用独立outbox destination和deployment-only token cache,不能复用test token实例、Actions dispatch或repo-write credential。GitHub payload只含deployment ID,ref固定为merge SHA;create/reconcile结果不是成功。固定workflow绑定GitHub production Environment、最小permissions和独立OIDC audience/subject/production:* role,policy子进程看不到GitHub/OIDC及test/production控制值。真实required reviewers和云role trust只能由外部配置/审计证明;本地workflow和fake JWT不得自证。
  • production platform status与Runner report隔离:webhook必须先验raw HMAC,API补偿必须使用单独deployments:read缓存并先核对Deployment identity后读取latest status;两者只落digest和白名单fact。URL统一移除userinfo/query/fragment,GitHub响应正文/token/Action输出无状态写入口。success还要求exact production OIDC,failure/error不能被Runner echo覆盖;所有终态以Run/version/Plan/merge/Attempt CAS提交,乱序、双源并发、错误SHA/ID/environment和failure后success均fail-closed。
  • ProductionDeploymentEvidenceManifestV1pnpm run e2e:production-deployment 继续沿用 Watt 固定 commit 的 explicit opt-in、仓库外 64 KiB manifest、1 MiB 有界 HTTP、分页拒绝和固定 0/1/2 退出;manifest 只索引安全标量,不能覆盖 live Case 8/GitHub projection。负向 case 必须保留“Action success、platform failure/error”冲突,防止 echo 被误当作成功。
  • automatic test rollback在任何Actions写权限前先用独立contents:read token读取exact失败SHA的delivery.yaml。缺失、解析失败、未声明trigger、同deploy role、未verified source或非test Task只允许immutable负向observation,禁止创建Attempt/outbox。contract digest与source Evidence一起冻结;Task/Agent/failure payload不能提交argv、trigger、role或policy内容。
  • rollback dispatch使用独立于Agent/acceptance的actions:write + contents:read token cache和github_test_rollback destination,API补偿再使用独立actions:read cache。固定workflow只有contents:read + id-token:write并绑定GitHub test Environment;子进程看不到GitHub/OIDC/控制面身份值。HMAC webhook与Actions只读API补偿共用exact run/workflow/title/branch/SHA projector,Runner pass或GitHub success任一单独都不构成成功;raw payload/REST/token不落D1,查询只公开source引用、digests、role与终态。
  • production policy schema不接受rollback字段,production failure不进入test scheduler。任何production自动回滚必须新增独立真人/Environment审批、production OIDC role、outbox与演练Evidence;不得把test contract、既有production deploy approval或失败事件本身解释为回滚权限。
  • test rollback外部verifier全程只读,控制面Case 8 token与单仓库Actions read token用途隔离;origin必须是无userinfo/query/fragment的HTTPS根,64 KiB仓库外manifest、1 MiB响应和10秒请求为硬上限。每个外部body在JSON parse前扫描两枚token、credential-shaped synthetic canary及通用credential形状;CLI只输出固定错误码/安全计数。Case 8只公开contract/rollback/OIDC/observation白名单标量,不公开OIDC JWT/token digest、raw policy/argv、Runner output或raw webhook/REST。负向零Action必须实时查询exact workflow/SHA/time-window inventory,不能采信manifest自报;云URL与production治理URL必须真人打开review,不能自动升级authority。完整门禁见Test rollback 真实外部证据验收
  • supplemental context内部入口使用strict discriminated schema;caller只能提交完整新Task snapshot、正文与是否apply-current。Task target、intent kind和policy必须与prior revision一致,不能借补充材料扩大repo/deploy权限;source ref/digest/base/effect/Plan body没有输入字段。正文和新Task先经统一Secret scanner,再用Watt复用的R2 conditional create-if-absent写内容寻址对象。默认路径不得触碰旧Run;显式路径还必须exact绑定旧Task revision、Run version、Plan version/digest/base,stale请求在source fact前拒绝。
  • Codex 子进程环境沿用默认 KEY/SECRET/TOKEN 排除并追加 PASSWORD glob;CLI executor 返回 stderr 前先按敏感环境值与 credential 形状脱敏,上层错误只公开固定类别/exit code。deadline触发事实必须在发送SIGTERM前冻结;即使子进程随后以0退出也统一返回timedOut=true + exitCode=124,analysis/preflight固定映射provider_timeout,其他命令消费者也不能将其记为成功。NDJSON 和原始 context 不进入 API error、普通Runner日志、PR或Evidence。execution JSONL仅可由Runner有界collector先按全部历史runtime credential扫描,再经active fencing送专用artifact API;控制面以全部Worker Secret/current token二次扫描并在R2前AES-256-GCM加密。不得使用 --yolo 绕过 sandbox/approval。
  • Codex session start/resume 都使用 --ephemeral + --ignore-user-config + read-only + approval never;不使用 --last,不把 provider session 当长期凭证或状态真源。resume checkpoint 文件必须在 repo 外、0600、大小受限,并在启动前核对 schema/canonical digest/plan/item/head。
  • session provider最终输出受固定AgentSessionResultV1 JSON Schema约束且没有自由文本字段。真实CLI E2E默认exit 2,只有显式DELIVERY_LOOP_CODEX_ADAPTER_E2E=1才创建临时只读repo并调用模型;它不读取当前业务repo正文、不打印模型output/stderr/context/path或credential,只输出digest-bound安全摘要。codex login status只证明本机保存过credential,不证明provider仍接受;实际调用的invalid_api_key必须固定归类为前置缺失且不得勾真实DoD。
  • AgentAdapterEvidenceManifestV1 是真实 adapter 结果的安全索引:processExitCode=0、session=completedAgentSessionResultV1 digest、checkpoint sequence≥2、checkpoint/workspace head exact 相等、Git clean 且 workspace ephemeral 才能通过。manifest verifier 不输出输入对象或 schema 错误正文;canary、模型输出、context、临时路径、stderr 和 token 没有字段入口。pnpm run e2e:agent-adapter 无 opt-in 时必须在认证/模型调用前 exit 2。
  • interrupt reason 不传入 provider argv/stdin/stderr;只有创建 session 的 adapter 可以中断或导出。TERM 后使用有界 grace,必要时 KILL,重复 interrupt 不重复 signal;export 返回副本且只包含 Runner 已记录的结构化 checkpoint。
  • Runner把digest-verified context放在repo内随机命名的隐藏.delivery-loop-analysis-context-*私有目录(目录0700、文件0600)作为调用前后完整性锚点;不得用--add-dir弱化analysis边界。有界且Secret扫描后的exact envelope通过stdin不可信JSON区块进入只读Codex sandbox。Agent output与诊断中间文件继续放在repo外RUNNER_TEMP私有目录且文件mode 0600;diagnostic正文也只在扫描后进入第2/3阶段stdin的独立不可信JSON区块。Agent成功或失败都先删除workspace context,Plan上报前必须确认Git status与启动快照完全一致,finally幂等删除两类临时目录。API非成功响应正文不进入bootstrap错误。
  • fresh initial requirement Plan的有界纠正不创建第二Attempt,也不扩大sandbox或grant。只有无revision source、无diagnostic mediation的第一次通用Plan语义校验失败能触发第二次model call;第二轮复用相同digest-bound context/model profile,只接收去重排序的固定validation issue code。旧Plan、issue path/message、raw error、模型输出和Task外文本不得反馈、记录或持久化。两次调用分别reserve并settle usage,第二次失败即终止;bug diagnostic和Plan revision固定不进入此分支,避免重复外部读取或把纠正当retry authority。writable Plan还必须通过Runner-owned exact-path门禁:git ls-files -zinventory绑定exact HEAD/base delivery policy,过滤built-in/custom protected path、unsafe/credential-shaped path、symlink、非regular和仓库外realpath;Item只能以完整token命中inventory,substring、untracked或protected名字不产生authority。该已过滤文件名数组会作为独立有界JSON数据块发给模型以ground首次与纠正输出,路径字符串明确是不可信data且不能变更policy;数组不发控制面、不持久化、不写日志,最终authority仍是Runner validator而不是模型复制结果。
  • Runner failure report 是不可信输入:body 只允许固定 code/site/path/human-input 枚举与 Attempt fencing,拒绝 message、stack、raw error、caller fingerprint 和 caller failure class。D1 表重复同一枚举 CHECK,且物理上不提供原始错误容器。analysis callback最多重发一次完全相同的event;已撤销token的特殊路径只在token仍未过期、Attempt已failed且version/generation恰为原fencing+1、既有failure逐字段一致时返回同一安全投影。它不接受新写、不恢复token/lease,也不能用于execution或其他endpoint。
  • analysis Agent失败的细分只存在于同一Action的安全结构化日志:Adapter把进程、usage、structured output、context proof或Plan validation映射到固定kind,并把context/single pass/diagnostic各阶段映射到固定stage;没有可信业务failure的Runner内部终态只映射固定runner_internal_failure/runner_boundary,同时以固定failureCode=unknown_failure + failureSite=external_reconciliation + attemptedPaths=[external_reconciliation] + neededHumanInput=manual_investigation进入failure callback。非零进程必须再复用preflight的安全classifier产生固定provider code。Codex JSONL stdout只允许识别turn.failed/error并在内存中把message立即投影为schema/400或共享provider allowlist;projector只保存布尔与固定code,不保留event/message。若JSONL没有具体code,才读取command runtime已按环境Secret与credential shape脱敏、最多8 KiB的stderr作为后备并立即丢弃。Runner只传递这些枚举,logger要求合法组合且只能用于analysis_attempt_result + failed;raw stdout/stderr、exit code、prompt、Task、tool result、模型output、schema issue、stack和异常正文均无字段入口。该细分不得写入failure report、D1/R2/Evidence/PR,也不构成retry或repair authority。
  • provider preflight复用同一typed Adapter error时,失败日志只能是固定JSON:Adapter分支含failureKind/failureStage,且仅nonzero含allowlistedproviderFailureCode;非Adapter分支只有固定failureCode。不得拼接Error message、Zod issue path/unknown key、output片段、临时路径或原始event;这些摘要只用于定位受控复验阶段,不授予Task retry、repair或任何effect。
  • 多阶段analysis的model admission只发生在紧邻的模型子进程前;Runner在下一次reservation前结算上一轮官方usage,避免用尚未发生的future calls占满run quota。429只投影固定policy failure与model_reservation阶段,响应正文没有日志/事件字段入口;terminal Attempt的未结算reservation由scheduled reconciler安全release,不通过手工D1改写或零usage结算释放。
  • failure fingerprint、retry scope、失败类别、路径 label 与人工输入 prompt 均由控制面生成。verification repair还必须绑定同Attempt generation/head的failed suite/command/Evidence;fact digest只含phase/canonical ref/exit code。没有该事实的Agent自报不能创建repair。首次repair若在任何head/checkpoint/Evidence/verification前固定失败,后继repair也只能复用其attempt_repairs指向的原immutable suite/Evidence,并同时要求source head未漂移、原dispatch settled、repo credential已失效、active Plan/Item无变化、同failure尚未被消费,以及latest non-invalidated repo_write decision仍是未过期approve;候选扫描与原子Attempt创建必须重复同一approval fence。approval缺失、过期或被更新decision取代时不得创建Attempt、outbox或切换Item来消耗重试预算;任一guard失败都不能dispatch。Task/Run查询和飞书卡片只消费安全ID/digest投影。
  • 失败卡片外部验收不把飞书正文或manifest当authority。operations只从strict stored presentation重算rendered digest;verifier重新读取当前Task blocker与settled latest/delivered卡片,再对真实Message GET重算digest并要求唯一Blocker段等于固定reason/count/path label/human prompt。blocker查询使用strict白名单schema,出现message/stack/raw error等额外字段即失败;token只进入各自origin的Authorization header,raw控制面/飞书响应不进入错误、summary或证据文件。
  • implement/review_fix共享execution retry预算。首次implement只能来自控制面对ready self-verifying change Item的原子claim,且与唯一execution outbox同batch,repair/review/base-rebase lineage必须为0;terminal verification failure原子撤销当前token并提升generation,未达阈值时只创建一个从失败head起步的新review_fix Attempt和fenced dispatch,不继承旧token、write credential或branch,且三类repair/review/base source必须恰好一个。repo_write始终需要exact Plan effect/approval。连续同fingerprint第2次或总Attempt第3次同时阻断Run/Plan/Item、取消其他Attempt并创建Workflow cancel intent。
  • RepairLoopEvidenceManifestV1 只保存 failure fingerprint digest、Attempt/Action ID、SHA、Evidence ID、blocker 枚举和计数;verifier 读取 /plan 与 Case 8 audit 后再核对 Actions job/commit/ref/compare,拒绝额外 dispatch、Action、commit、分页或 head drift。manifest、错误码、日志和响应不含测试输出、Agent正文、failure message、token 或 raw GitHub response。
  • failed Evidence一旦进入verification failure fact,其run/attempt/plan/item/status/command/exit/duration/head及suite/command binding不可改删。review feedback使用独立immutable lineage,不能伪造verification failure或重置failure预算。延迟execution dispatch要求两种source恰好一个,Run/Plan/Item失效后必须terminal settle且零GitHub调用;外部调用后fencing丢失的Action也无法交换active token。execution context重新绑定active Plan/Item、Task/R2 digest、repo_write policy/effect和exact source;head API只接受受信branch与当前parent,并以immutable ledger+commit Evidence前进一次。
  • execution Runner不信任“不要操作Git”的prompt:Agent后必须复核branch/HEAD仍绑定checkout head,bot commit必须以该head为唯一parent。context/output仍是repo外0600常规文件;context先经Runner runtime Secret扫描,再由Adapter以canonical object、256 KiB与credential shape复核后作为明确不可信JSON数据块送入stdin,模型结束后重读必须未漂移。正文不进入argv、日志、artifact、checkpoint或D1新字段;第三方模型边界仍会看到Task/Plan正文,不能误称本地文件路径为数据隔离。普通metered implement/verification repair首轮是无--output-schema的edit turn:模型final message没有authority,Runner只在completed file-change计数非零时派生apply_fix并进入Git门禁;command计数只作诊断,不能覆盖真实file change或后续Git验证。verification repair的可信聚焦信息只有Runner从冻结base受信delivery policy解析出的failed command ref/argv;Task正文、Agent输出、失败摘要和repository instruction均不能改写它。argv只进入模型stdin指令,不进入dispatch/D1/日志,且不扩大Runner本来就会执行的命令集合。唯一例外是首轮固定零工具,或首轮虽返回apply_fix但Runner证明exact checkout/clean且没有有效tracked diff时的第二次read-only structured patch proposal;production proposal v2只能对Runner snapshot中的已有文件提出baseDigest + oldText/newText有界exact edit,不能直接写workspace或新建文件。Runner一次性预检全部路径、旧digest、regular非symlink文件、runtime Secret、唯一oldText、结果UTF-8/收缩、数量与字节边界,先在内存准备全部next content再落盘;stale digest、missing/ambiguous text、重复/逃逸路径、symlink、delete/rename/binary、受保护路径或partial/dirty activity均不得进入commit。proposal agent-message正文不写raw transcript artifact、D1、日志、checkpoint或PR;output文件在repo外0600且Attempt结束清理。普通branch从task/attempt派生;review branch只能来自控制面lineage,准备时ls-remote核对远端仍是reviewed head,push固定同ref且永不force,随后并发推进会安全失败。heartbeat、head和Evidence/failure传输共享串行fencing,repo token只进固定Git环境。Agent阶段异常保留固定kind;patch落盘、commit、push和head report再各自增加一个固定kind,Action日志只写受审枚举。只有repository_commit_failed可再携带固定precondition|stage_changes|protected_path_scan|protected_path_report|create_commit|verify_commit|result_binding|unknown阶段;这些阶段由trusted writer/Runner产生,不能由Task、Agent或failure reporter自报,非commit组合会在sink前拒绝。command runtime的observer拒绝只留下stdoutInvalid=true;raw error、exit code、stderr、transcript、Task、Git路径/diff和上游响应均无输出字段。该stage不进入D1/R2/Evidence/Plan、不改变failure report,也不构成retry/repair authority。已通过Secret扫描的JSONL只允许额外生成一次固定event/item type计数;command、路径、diff、output、message、usage和unknown字段均在内存丢弃,活动计数不进D1/R2/Evidence且日志失败不影响Attempt。protected-path报告成功后的暂停不被宽泛commit catch改写为terminal failure,failure reporter失败也不能伪造D1成功入账。只有受信verification nonzero结果可创建首个verification repair;其pre-verification retry authority来自控制面原始事实链而非第二个Agent failure。固定workflow/bootstrap的本地穿透不等于真实GitHub Action证据,禁止表述为外部修复完成。
  • patch fallback不是宽泛Agent retry:只接受Adapter内部固定no_tool_activity,或已返回apply_fix但trusted Runner证明completed file-change没有形成任何真实tracked diff;两类都必须由Runner在首轮后重新执行exact HEAD与完整porcelain clean检查。started未completed、command-only/其他typed failure、shell真实改文件、review feedback decision或脏树全部禁止fallback。fallback还必须在首轮前已成功生成非空安全repositorySnapshot;Task/Plan没有显式tracked路径时允许首轮正常edit,但canRecover=false,不得为了二次proposal扩大扫描范围或猜测路径。fallback最多一次,第二轮没有继承首轮自由文本或“建议”,只复用同一受批Task/Plan/context并固定为read-only structured proposal。每个真实模型调用必须先有独立quota reservation;turn.completed.input_tokens按该轮全部Responses/tool往返累计,不能拿context window或首个request大小当上界。当前immutable tool-loop profile把单次input ceiling固定为2,000,000,仍由run/tenant/repository/user总额度限制;Task、Agent和Runner请求不能放宽它。只有取得对应官方usage才能独立settle,不能把两轮usage相加或把失败首轮记成零费用。Adapter在usage产生前失败时不调用settlement,原固定failure继续上报且reservation保持reserved直至既有TTL过期。一旦官方usage已经产生,账本完整性优先于该轮decision:Runner只允许同一stable usage事实的一次幂等补偿;持续失败必须固定为quota_unavailable/external_reconciliation并在Git写前停止,不能泄露原错误、降级成unknown、伪造零费用或开启第二模型调用。首轮raw JSONL和第二轮固定省略proposal正文后的结构事件进入同一Secret-scanned、加密、30天artifact和固定计数日志;proposal正文只从临时0600 output进入内存与随后真实Git工作树。第二轮JSONL中重复正文的物理行只允许在2 MiB上限内由可信envelope前缀转换为固定省略事件,64 KiB parser永不接收正文;其他oversized形状fail-closed。
  • 第二轮也不得把“模型会主动读文件”当成安全或正确性前提。Runner以NUL分隔和256 KiB stdout上限枚举tracked paths,只把受批Item/Task验收文本明确点名的tracked文件加入repositorySnapshot,并在发送模型前要求tracked、非protected、regular非symlink、仓库内realpath、UTF-8、最多8项、单文件不超过128 KiB、总计不超过256 KiB。扩大tracked-path buffer只修复大仓库枚举,不能扩大内容、候选或effect权限。该snapshot是可选恢复材料:零候选、数量歧义、内容超限、结构不安全或仓库内credential-shaped测试样本都只关闭fallback,不能把本可由首轮workspace-write Agent完成的合法Plan变成模型前失败;候选bytes命中当前Runner已注册runtime Secret时则使用独立runtime_secret_detected分类终止Attempt,不能降级。snapshot content仍是不可信模型数据,不能改变policy/effect/paths;其中digest由Runner从exact bytes计算,production proposal v2只返回已有snapshot path、同一digest和有界exact oldText/newText。Writer再次从磁盘计算digest,并要求每个oldText在按序应用前序edit后的current content中恰好出现一次;missing、ambiguous、stale或结果缩短到当前一半以下都在任何文件落盘前拒绝。该门禁不作用于首轮workspace-write,因此不会把合法的大规模改写变成系统级禁止。
  • Git credential不能因同属GitHub而跨协议复用:installation token对REST是Bearer,对Git smart-HTTP必须是x-access-token Basic password。Runner在内存编码后只通过固定Git环境注入;origin保持无credential,argv、stdout/stderr安全failure、transcript、artifact和D1均不得包含明文或Basic编码。push失败仍只暴露固定repository_push_failed
  • 首次implement的null head不能被误判为缺少代码lineage:仅当mode=implementhead_sha IS NULL且请求parent逐字等于冻结base_sha时,head API可把base作为旧parent;review_fix的null head固定拒绝。commit Evidence、head ledger与Attempt CAS必须在同一D1 batch使用相同父判据,错误base、branch、generation、Plan/Item或protected gate均不得因COALESCE回退而通过。
  • request_replan能力只由受信context中的exact GitHub review lineage开启。该路径保留exclusive-create的repo外0600 strict output schema,只有此时向模型暴露apply_fix|request_replan并在解析层二次拒绝越权值;非模型测试adapter也保留strict schema以验证接口,但不能伪造真实工具活动。成功replan在任何commit/push/verification前取消旧Attempt并撤销token,模型没有GitHub或Plan写权限。
  • PR diff 运行 secret scan、依赖/脚本变更检查和高风险路径 CODEOWNERS review。

6. 供应链与 Action 隔离

  • 第三方 Actions pin 到不可变 commit SHA;版本升级走依赖更新 PR。
  • pull_request_target 不检出不可信 PR 代码;来自 fork 的代码不在拥有 write Secret 的 job 中执行。
  • Runner 不复用含工作区/凭证的持久缓存;依赖缓存只按 lockfile digest 读取。
  • 目标仓库执行命令在容器或最小权限 runner 中运行;生产网络不可从普通实现 job 直达。
  • artifact 带 digest、保留期和敏感等级;原始 Agent session/transcript只能以AES-256-GCM ciphertext进入专用私有RAW_AGENT_OBJECTS并显式登记固定30天policy。当前仅execution Codex ephemeral adapter生产raw_transcript:stable UUID、exact execution scope、active Plan/Item、Attempt version/generation/lease/token共同fence;upload intent先落D1,plaintext只在受保护HTTP请求内有界传输且R2/D1 registry永不保存。collector在接受每行前完成JSON/object、runtime Secret和512 KiB校验;observer失败只产生固定transcript_invalid|usage_invalid。artifact持久化仍在commit前执行,但其次级错误不得把已存在的typed Agent failure改写成unknown;Agent成功而required transcript不可用时则fail-closed为transcript_invalid。analysis/session尚无raw producer,不能把checkpoint/Evidence误标为raw。
  • Secret safety 外部验收也必须 fail-closed:SecretSafetyEvidenceManifestV1 的 canary 只通过显式 opt-in 进入 verifier 内存,manifest 只保存 canary digest。Action jobs/logs 读取复用既有 Actions parser,拒绝 rel=next 分页,单 job/Run 有界,日志 302/307/308 只接受无 userinfo 的 HTTPS location;错误码、stdout/stderr、Case 8 audit 和 manifest 均不得包含 canary、token、raw response。safe Draft PR 由 GitHub API 重算 body digest/head/base,blocked publication 必须有 pending publication、settled pull_request_secret_detected outbox 且 GitHub 同 head/base 查询无 PR;两类都不能用 fake fixture、schema example 或默认 exit 2 冒充真实外部事实。
  • Phase 4双case verifier默认零网络:未设置DELIVERY_LOOP_DRAFT_PR_CASES_E2E=1时在manifest/credential读取前exit 2。控制面token只读Task/Plan/Case 8,GitHub token只读单仓库Actions/compare/PR;二者不得拥有repo write、PR write、merge或deployment权限。仓库外credential-shaped canary只在内存扫描每份最大1 MiB的控制面/GitHub响应;下一页、响应中的token/canary/credential、raw正文或上游错误全部fail-closed。manifest只含ID/SHA/digest和安全review URL,不能自证reviewer、PRD语义或bug根因;人工semantic/root-cause/diff review是独立authority。
  • Phase 0 CI verifier 同样默认零网络:未设置 DELIVERY_LOOP_CI_E2E=1 时在 manifest/token/canary 读取前 exit 2。GitHub token 只进入单仓库 Actions/Contents read 请求;CI/validate workflow的第三方setup Action只接受受审commit SHA,不接受可变tag。合法Task校验只打印固定结果,非法校验只打印固定错误;run title、workflow 内容、job log 和 Task canary 不进入 manifest或错误。JSON 1 MiB、job log 8 MiB,分页或非 HTTPS 日志重定向 fail-closed;validate-task failure 只有在前置 steps 全成功且命名 validation step 失败时才算 schema 拒绝,不能拿安装失败冒充安全验证。
  • Workflow hibernate verifier也默认零网络:未设置DELIVERY_LOOP_WORKFLOW_HIBERNATE_E2E=1时在manifest/token/account读取前exit 2。Cloudflare token只读目标account的Workflow instance与Worker deployments,GitHub token只读试点repo Actions,控制面Run与operations token用途隔离;四类token只进入Authorization header。响应上限1 MiB并拒绝下一页,Cloudflare envelope、deployment/version/step/attempt与GitHub run/inventory全部strict归一化后才计算digest;instance/step output、error/stack、raw响应和token既不落manifest/D1也不进入错误。Dashboard链接只允许dash.cloudflare.com的无userinfo/query/fragment HTTPS URL。
  • 平台limits验收使用独立account-policy/billing只读GitHub token;组织模式使用组织管理员读权限,个人模式的enhanced billing额外需要用户Plan: read(classic为user scope),不得为了404自动扩scope。token不能触发workflow或修改账号/repository设置。verifier先核对live User|Organization身份,再按类型读取org policy或repository policy;个人billing item中出现organizationName、缺repositoryName或显式其他owner均fail-closed。并发/时长probe workflow顶层权限为空、不checkout、不读取Secret,输入只允许非敏感correlation ID与matrix整数JSON;真实运行仍需owner先批准约六小时Runner和并发分钟预算。V2主manifest只保存account type/login、policy/usage digest与金额/数量标量,三份既有App/Workflow/replay manifest在仓库外重新核对;raw billing、用户明细、Action日志、Cloudflare output/error、token/JWT和任务正文没有schema字段。Cloudflare Paid plan与GitHub支持调整后的并发仍要求管理面人工review,verifier exit 0不能把manifest URL自证成授权事实。

6.1 Workflow 回放与副作用

  • 所有外部写入使用稳定 idempotency key;Cloudflare step 重试、受控 restart 和 Queue 重放均不能重复创建 Action、PR、merge 或 deployment。
  • 普通 Workflow 恢复只复用成功步骤;受控 replay 重新执行目标步骤前先按外部 API reconciliation。
  • replay 涉及 repo_writetest_deploymergeproduction_deploy 时,旧审批只有在 task revision、plan version/digest、base SHA、effect 和有效期全部匹配时才可复用;其中merge/production还必须在调度快照和restart effect前两次通过trusted_effect_approvals的live身份/角色/分离重验,裸approval不得恢复副作用。
  • 任一approval进入invalidated_approvals(来自Plan revision或base conflict ledger)后,即使原expires_at仍在未来也不可用于credential、PR、review、replay或deploy;invalidation行不删除/改写原审批事实。Plan revision或base conflict开始时旧effect intent先settle,避免已claim但尚未调用的外部写穿越版本边界。
  • replay API 只接受 expectedRunVersion + allowlisted system verification step 或当前 active plan的 verification Item;step type/count/name由服务端固定。任意 dispatch/wait step、非 verification Item、旧 version、cancelled Run和客户端自报 effect均拒绝;reason 只持久化 digest。
  • scheduler 对目标及后续 Item收集 effect;每个 mutating effect独立绑定 exact approval。已有 dispatch intent必须 settled,已有 PR/check/deployment Evidence必须 passed + verified;approval/outbox/Evidence snapshot 在 restart 前重新核对,过期 approval terminal settle且不调用 Workflow。
  • replay API 只创建 fenced outbox,不直接调用平台。restart 仅面向 terminal Workflow instance;目标之前成功步骤复用缓存,目标之后任何 repo/PR/deploy producer仍必须用稳定 idempotency key与外部 API reconciliation。restart_observed_at 只证明平台接受 restart,不能替代 step execution、PR或deployment Evidence。
  • Workflow callback 采用 pending → delivering → settled;先 settle 后投递会导致结果永久丢失,禁止使用。相同 run/event 或 run/sequence 只有完整 type/Attempt/payload/digest/time 全一致才是幂等重放,改写任一字段均拒绝。
  • callback outbox 取得 delivering lease 后仍须从 D1 重新绑定 Run、Attempt result projection 与 referenced Plan。只有 active planning/running exact binding 可 sendEvent;cancelled/blocked Run、cancelled/lost Attempt、stale/invalid binding 以安全 terminal code settled 且绝不调用旧 Workflow。
  • sendEvent 的不确定结果不能盲目重复副作用:重放先核对 Run/Attempt/active Plan,已应用则 already_applied settled;未应用才允许重投,最终业务推进仍由 Workflow 稳定 step 与 D1 CAS fencing。
  • D1 状态与 Workflow create/send/dispatch 通过 transactional outbox 最终一致;禁止在部分失败时无条件删除业务记录。
  • 全局restore generation是高于单Run fencing的灾备边界。restoring期间普通HTTP 503、Queue只retry、Cron只允许write credential revocation;已撤销Attempt context探针仍进入原鉴权路径并必须返回401。恢复完成不能依赖Workflow history,必须由D1 lineage、R2 content/metadata digest、foreign keys及零active credential共同证明。
  • 主outbox Queue的暂时失败最多平台重试3次后进入专用DLQ。DLQ consumer必须先写D1 dead-letter ledger再ack;open dead letter在relay、router和processor claim三层冻结。Queue body仍只有outbox ID,DLQ表不保存payload ref内容、Task/PR正文、外部response或token。
  • dead-letter重放只接受用途隔离的OPERATIONS_TOKEN;Task/Runner/approval token均无权调用。strict body只有expected outbox attempt count与固定reason,不接受kind/destination/payload/effect/actor。重放不复制或改写原outbox authority,只重新arm原ID;destination processor仍须重验Run/Plan/approval并先reconcile外部Action/PR/deployment。每dead letter唯一replay ledger记录固定service:operationsactor。
  • malformed DLQ message和已不存在outbox是不可恢复毒丸,安全ack;D1捕获失败继续retry,DLQ consumer自身100次耗尽后转入不消费的quarantine queue而非永久删除。重复capture/replay/Queue message通过source identity、one-open索引、immutable replay、outbox lease与settled状态收敛。当前系统没有自动merge outbox,operations API也不能指定merge,因此DLQ重放不能扩大到merge权限。
  • cancel/timeout 对尚未执行的 dispatch intent 使用 settled + run_cancelled/attempt_lost 明确表示“无需再执行”,并另建 fenced workflow_cancel;不能删除审计行,也不能让已 claim 的旧 Runner凭旧 generation 写入。
  • GitHub webhook delivery 只存 digest、绑定标量和 applied/ignored 状态,不存原始 payload。外部事实用 GitHub updated_at 单调前进,并与 Runner fencing version 分栏,防止乱序事件回退或 webhook 观察打断 heartbeat。
  • Runner heartbeat真实验收只读D1安全receipt/result projection与Case 8安全observation,并复用Analysis Action verifier实时读取GitHub API。manifest只含安全digest/标量;credential只进Authorization header,响应1 MiB有界,错误固定code且不传播raw body。signed webhook、live API和D1任一不一致都fail-closed。
  • deployment_status同样只存payload/canonical fact digest与白名单projection;Environment URL必须是无userinfo/query/fragment的HTTPS地址。test success在exact deployment/repo/SHA/task/test environment与OIDC attestation全部匹配后才生成独立Item Evidence;production success还原子完成post-merge Attempt/Plan并执行deploying→succeeded,production failure/error执行deploying→failed。未attest success保持可恢复的received状态,任何Runner输出都不能替代平台事实。
  • acceptance workflow_run同样只存payload/canonical fact digest与白名单projection;webhook HMAC和API补偿复用同一repo/run/workflow/title/branch/SHA/run-attempt/updated-at projector。Runner自报pass不能关门;completed success缺Runner结果保持received可重试,结果/结论冲突fail-closed为failed,任何failure都不得把Run写成succeeded。查询不公开OIDC/result digest或原始payload。
  • rollback workflow_run遵循相同双源projector纪律,但Evidence与Attempt独立于原失败Item。completed success缺Runner结果保持received可重试;Runner/GitHub冲突形成failed rollback,终态晚到事实只记ignored。即使rollback成功,原deployment/acceptance failure和Run状态仍保持可见,不能用补偿结果伪装需求已交付。
  • scheduled GitHub API reconciliation 使用同一事实 projector;只存 canonical fact digest,不存 REST response。API 事实不能绕过 webhook所需的run/repo/workflow/base/title/run attempt或deployment所需的ID/repo/SHA/task/environment/payload binding,失败保持既有投影且下一轮可重试。飞书message reconciliation同样只存card/fact digest与白名单identity,并且只能结算原presentation/outbox,不能新建消息或提升effect权限。
  • Free-plan Cron的Draft/publication恢复入口不接受HTTP输入或新authority,只扫描D1中已经verifying、active Plan/版本/digest/base仍一致、required Item全passed且latest completed bot head存在的候选,每轮最多1条。尚无prepared snapshot时,它仍通过PullRequestDraftStore重读R2 Task digest/metadata、verified Evidence和完整Secret scanner;已经prepared而尚无publication时,它直接复用D1 immutable正文及digest,不再次读取R2或渲染不可信正文,再由PullRequestPublicationStore重验Task write policy、latest head、protected gate和exact未过期repo-write approval。把两级入口移到外部scan之前只改变可恢复调度顺序,不允许跳过approval、构造caller正文、重复PR或把CPU超限伪装成成功。
  • Free-plan Cron在recovery serving fence后优先调用原execution scheduler激活/领取最多1条工作,并只relay最多1条github_actions目的地的durable outbox ID。随后在任何历史at-risk Action、base或R2读取前,只核对最多1条仍绑定current verifying Run/version的created_unverified Draft PR、调度其唯一head-bound自动review并定向relay最多1条review Action。两个优先级都不接受HTTP/Task正文/Agent输出,不新增authority;scheduler、publication projector、review scheduler与Queue consumer仍分别重验原D1 policy/CAS、exact repo/base/head/body digest、active Plan/Item和outbox/Attempt lease fencing。重复消息、陈旧publication、旧Run version或已存在same-head review不能借排序变化创建第二Action、PR或review。
  • fresh publication入口无候选或完成后,Cron才运行at-risk projector;projector不再让最老heartbeat无条件占据有界窗口,而是在完全相同的eligible集合内先选current executing|verifyingimplement|review_fix,再选planning、review/deploy及历史恢复,层内仍按heartbeat/Attempt稳定排序。该变化只排序只读GitHub GET,不增加候选、不相信Action正文、不改变installation token scope、fact parser、projection CAS、lease或failure/recovery authority。其写入受信GitHub completed/success后,再通过既有PlanItemEvidenceVerifier完成最多1条D1-only Attempt/Item关门并调用base observer或R2-backed Draft finalization。自动review仍必须由exact verified publication/head产生;Evidence关门继续只消费同head completed suite及passed commit/test Evidence并重验Run/Plan/Item/progress/Attempt version与lease generation,GitHub status单独存在、缺head/suite/Evidence、stale CAS或Agent自报都不能推进。
  • Cloudflare Workflow status不是业务授权事实。adapter只允许官方status枚举并丢弃error.name/message、output、stack及异常文本;D1只存status fact digest、Run state/version和固定repair action。Cron不能直接create/restart/terminate,必须先写immutable observation和reference-only outbox;processor再核对Run version及active/inactive关系。旧observation、状态漂移、已active restart、已terminal terminate和controlled replay竞争均幂等收敛,不能借“恢复Workflow”重放GitHub/飞书/deploy effect或绕过approval。
  • terminal verification replay不把completed Plan普遍视为active authority:仅succeeded Run + exact completed Plan + current passed verification Item能执行无外部effect的稳定verification step;completed Plan的analysis system step、failed/cancelled Run、pending Item或历史verification decision全部拒绝。Case 8 replay投影生成时重算每个outbox/Evidence snapshot digest,防止验收读取被修改后的来源却仍展示旧digest。
  • 真实controlled replay verifier使用用途隔离的operations、Task/query和GitHub只读token;manifest没有URL/token/reason正文。它精确比较全部dispatch reconciliation与GitHub Action title inventory、单head PR和stable deployment ID inventory,额外对象、分页、过期/invalidated approval、raw/超限响应均固定code失败。工具没有POST、restart或GitHub write路径,不能借验收扩大replay authority。
  • 长期Workflow只在Plan激活后等待固定run-terminal事件,任何事件到达后仍从D1重新确认blocked/failed/succeeded/cancelled;外部调用者不能靠event payload把Run改成终态。正常业务终态由既有D1 projector产生,scheduled reconciler随后terminate。365天timeout/restart只恢复控制流,不恢复Agent隐藏状态、token、lease或审批。
  • replay/retry不会重置quota。Attempt trigger按四scope累计所有真实Attempt;同stable Attempt ID的数据库幂等重放不增加计数,replacement也计入真实usage。唯一bounded例外是pending自动review的首个失败replacement:scheduler必须在同一D1 batch按current root/head/Plan/approval全量重验并先写immutable、root/replacement唯一quota slot,trigger才只忽略run-scope上限一次;tenant/repository/user配额、普通Attempt、第二replacement和孤立/不匹配slot全部拒绝,batch失败不留marker。并发reservation、tool admission和model reservation在每个外部effect前重新从D1核对;released并发reservation重试会原子re-arm,settled/expired model reservation拒绝再次调用。P0 override只有在当前接收时间仍未过期时生效,不能被Runner自报时间复活。
  • Runner recovery API 必须认证并校验 expectedRunVersion + active plan version/item;旧 version、非 blocked Run、非 lost active Attempt、未 settled 的 Workflow cancel、未通过的依赖或已 passed/skipped 的目标都拒绝。恢复请求不能用服务认证替代后续飞书身份与 repo-write effect 审批。
  • replacement 只有在旧 token/lease generation 撤销且旧 Workflow 已 fenced 后创建;它不继承旧 token、lease、GitHub run ID/状态或任何临时凭证。晚到 heartbeat/result/callback 仍由旧 generation、Attempt identity 与 Run/Item CAS 拒绝。
  • root initial analysis recovery同样不复活旧token、lease、credential或GitHub run,也不重发旧dispatch。只在无Plan/revision/automated review/blocker且可信failure预算允许时创建唯一replacement;Task/Run/repository/base/workflow ref由D1旧Attempt与Run派生,Agent和dispatch payload不能选择。latest-lineage context fence使旧root即使被外部误标running也不能读取Task或提交Plan;replacement proposal/callback仍受opaque token、lease generation、strict schema、effect policy和Secret扫描约束。prepared activation只读取D1中validated Plan/result/signal exact binding,不把GitHub conclusion或旧Workflow状态当authority。
  • repository inventory v2仍是有界安全放宽:最多5,000 tracked path与256 KiB NUL-separated输出,只有exact git ls-files -z请求可覆盖通用Git命令64 KiB默认上限,绝对上限仍为256 KiB。既有exact HEAD/base、clean index、trusted delivery policy、protected/credential-shaped/unsafe/symlink/nonregular/realpath过滤全部保留。旧容量blocked Run只有在failure code/site/human input、重复计数、blocker scope/fingerprint和零Plan lineage全部由D1精确证明时才可一次恢复;immutable recovery marker与replacement/blocker resolution/Run transition/outbox同批原子写入,quota拒绝不得留下部分状态。
  • Adapter把同一inventory序列化进不可信prompt数据块时使用独立512 KiB JSON上限,不能因JSON编码开销退回旧64 KiB,也不能超过5,000项、包含unsafe/credential-shaped path或扩大effect/command/approval。compatibility recovery只接受由immutable v2 capacity marker直接创建的latest failed Attempt,且D1必须证明模型reservation/usage和tool trace均为0;任何可能已经产生模型/tool副作用的failure都fail-closed,不得由“看起来相似”的agent_output分类恢复。
  • recovery scheduler 只创建 pending Attempt,不自动创建 write dispatch outbox。任何 repo write 仍必须匹配原 task/plan/base/effect 的有效审批并经过普通 dispatcher;“恢复”不是权限升级或审批旁路。
  • checkpoint commit 只作为经过 schema/digest/active-plan 绑定验证后的 Git 恢复输入。Runner 要求 clean worktree,Git 子进程只接受固定命令和已验证的 40 位 SHA,不执行 checkpoint/任务正文提供的 ref、shell 或参数;验证 detached HEAD 后才启动 semantic resume。
  • 真实恢复证据verifier严格只读:控制面query/operations与GitHub token用途隔离并从环境注入,manifest不得携带token、URL、正文或raw响应;origin只允许无userinfo/query/fragment的HTTPS,response有512 KiB流式上限、10秒timeout、分页拒绝,并在JSON parse前扫描全部配置token和仓库外credential-shaped canary。Case 8必须canonical重算,lost Attempt当前generation必须比kill前恰好提升一代,全部旧grant均有revokedAt,唯一workflow_cancel与完整effect inventory settled且replay为空。Git关系不能靠caller声称“SHA已推进”,必须从受信branch ref与GitHub compare证明result指向、checkpoint merge-base和恰好一个result commit。summary不包含token、canary、raw API、日志、checkpoint正文或数据库行;工具不执行cancel/retry/dispatch,因此不能借“验收”扩大操作权限。
  • GitHub PR 外部验收继续保持三方事实隔离:Case 8 只公开 pullRequestObservations 的 source ID、publication、repository/number、fact digest、processing state 与时间;verifier 再从 GitHub PR API 核对 open/draft、URL/number、base/head repository/ref/SHA 和 body digest。Agent 自报 URL、create response、manifest 或单一 webhook 都不能推进 Run。scheduled PR API projector必须先于同一轮base observation完成,禁止二者并发竞争Run version并永久消费稳定observation identity;它还必须在批次limit前要求Run为current verifying snapshot,并在外部GET前重复校验publication冻结version,旧Plan、blocked/replanning Run或version-drift publication既不能调用GitHub也不能饿死新候选。这个顺序不允许旧Plan或旧PR覆盖随后核对到的base漂移。e2e:github-pr 直接复用 Watt 固定 476e3cd 的显式 opt-in、仓库外 64 KiB manifest、固定 0/1/2 退出和 1 MiB 有界读取,但 PR 业务绑定是本项目新增。raw PR body、webhook/API payload、REST response、GitHub/control-plane token 没有 D1/R2/log/audit 序列化入口;失败只返回固定 code。
  • Review feedback 的权限边界独立于 PR publication:只有 signed changes_requested 的 review commit_id、PR payload head 与控制面当前 bot head exact 相等才允许 applied;stale review 只保存 digest/ID/固定 stale_head,不能创建 R2 feedback、review_fix Attempt、dispatch 或 Plan revision。Case 8 只投影 reviewObservations 和 feedback/replacement lineage 白名单字段;e2e:github-review 必须重算Case 8 report digest并复读/plan,证明replacement没有跨repository/Plan/version/Item,且新commit、targeted→required test Evidence和Item decision全绑定result SHA。GitHub侧分别核对workflow head、reviewed checkout SHA和result SHA,唯一Action job及固定execution steps、PR/ref/单commitcompare和exact完整check inventory;manifest没列出的pending/failed check仍fail-closed。控制面/GitHub token用途隔离且只读,仓库外credential-shaped canary必须命中scanner;所有GET使用10秒timeout、1 MiB上限、redirect/pagination拒绝并在JSON parse前扫描完整响应。review正文、raw payload/REST response、R2 ref、token、canary和Action输出不进入D1、日志、manifest或summary。
  • 自动review是独立的只读Agent边界,不是GitHub reviewer身份,也不能批准repo write、merge或production effect。只有verified publication的exact current head、active Plan/Item和既有未过期repo-write approval允许创建read-only analysis Attempt;该approval只允许后续blocking finding触发已有branch上的review_fix,不赋予review Agent写权限。Codex强制ephemeral/read-only/approval-never并屏蔽目标仓库AGENTS.md提权,前后workspace snapshot漂移即失败。
  • 自动review结果仍是不可信模型输出:provider-wire strict schema把finding全部字段列入required,可选定位只允许path/line=null;Adapter在单一边界删除这两个null后仍用内部strict schema和稳定context digest校验,额外字段、linepath及unsafe path继续拒绝。digest排除合法heartbeat会改变的Attempt version,避免长于30秒的review被可变计数自行否定;它仍绑定Attempt/Run、lease generation、exact PR head、Task和Plan,且每个API请求继续以opaque token、当前version和lease generation做CAS,因此排除version不允许旧lease、replacement或跨head结果重放。失败恢复也不相信Action自报:只有GitHub API核对的completed/non-success、expired lease、pending immutable review、same latest bot head、active Plan/passed Item、verified publication、零blocker及唯一fresh approval同时成立,才撤销根token并创建至多一个read-only replacement;root/replacement之外的Attempt不能读取context或提交结果。唯一replacement若再次失败,只能在同样guards下复用同一Attempt一次:immutable redispatch ledger、generation提升、旧token撤销和旧Action observation清空必须与新outbox原子收敛,独立dispatch title防止命中旧Action;第二次失败无恢复authority。模型reservation绑定新lease generation,不能复用旧settled usage。exchange后的只读context允许对409/5xx/transport做最多3次同token重读以跨过D1读后写窗口;401/403和所有mutation不重试,最终失败只上报固定分类且不记录响应正文。verdict必须由blocker|major finding机械决定。结果在R2/D1前扫描全部runtime Secret和credential形状;全文作为review/context对象只写私有TASK_OBJECTS的内容寻址对象并进入既有备份边界,不得明文污染仅允许加密transcript的RAW_AGENT_OBJECTS。D1、dispatch、outbox、日志、Evidence、PR正文和Action安全结果只允许ref/digest/计数/枚举。provider失败只保留allowlist分类,raw JSONL/stderr/message丢弃;typed process_nonzero_exit必须携带固定provider code,防止日志层二次失败掩盖原错误。修复Runner回读时重新核对R2 metadata/schema/result及feedback digest,minor finding不进入write prompt。Runner只把纯数字GitHub review ID或producer共享schema生成的automated_review_<52 lowercase hex>作为合法source identity;伪造内部ID、大小写/长度漂移及同时出现多个repair/review/base source均在任何credential、model或Git effect前fail-closed。若自动review fix判断必须改变Plan,它只能提交无正文的expectedVersion + leaseGeneration;服务端从exact automated review/fix/publication/head派生内容寻址source digest,20路收敛为一份revision并撤销旧Attempt/approval。re-analysis再次从私有R2重算result/body/metadata,caller不能选择source ref、finding、base、effect或Plan。第三轮重大问题必须blocked并撤销控制流,不能由Agent文本或重放创建第四轮。
  • 当前head一旦存在自动review lineage,merge gate必须看到其terminal approved;pending、changes requested或blocked都按review不足拒绝,passed SQL在Run/Plan/publication/head同一快照上再次核对。Cron顺序保证fresh PR先创建自动review再观察merge/base,避免只靠Agent结论或调度时序放行。
  • Plan revision 必须先有受信 source fact,不能由 Agent/HTTP caller 选择 source ref、base SHA、effect、Plan body 或 approval 绑定。review/base/context 三类 source 都在 D1 中保存 canonical digest 和 prior Plan snapshot;review source内部再区分真人GitHub signed feedback与自动review immutable result,二者不得同时绑定同一Attempt。activation 前旧 Plan/approval 只可被 invalidated,new Plan 必须 version + 1 且重新获得 exact human/provider approval。Case 8 planRevisions 对自动source只公开review Attempt/PR/head/result/body digest等安全投影;GitHub ref/真人Review/compare由只读 API 复核,自动结果由D1/R2双重重算,Feishu/Meegle 签名、tenant/identity 与审批后台仍需人工核对。Task/PRD/context/review 正文、R2 ref/content、raw source payload/API response、token、nonce 和 Action 输出无序列化入口。

“PR projector先于at-risk与base”按同一Run version实施:priority projector只选择verifying + current run_version + created_unverified + github_pr_number,并在Store内再次核对repository/base/head/title/body digest、active Plan和Run CAS。base reconciler同时在batch候选和按Run ID直查两层排除publication.run_version = runs.version AND status <> verified;历史stale publication没有当前CAS authority,不能阻断新base。PR读取与base读取仍使用各自用途隔离的单仓库最小权限token,排序变化不允许交叉复用credential。

7. 人审闸门

Effect 默认策略
读 repo / 测试日志 已接受任务可自动
读生产日志/trace 最小字段、按 run 授权、审计
读数据库 只读诊断工具;敏感列脱敏
写目标分支/开 Draft PR 任务显式允许 repo write
测试环境部署 独立批准或仓库白名单策略
merge required checks + review + 最新 base 校验
生产部署 GitHub Environment/外部审批,Agent 不可自批
删除、生产 DB/K8s write MVP 禁止;未来必须双人审批和专用工具

批准必须绑定 taskRevision + planVersion + planDigest + baseSha + effect + actor + nonce + expiresAt。merge/production的actor不能来自request body,而由已验签provider/tenant/subject经实时身份映射解析;PR作者或agent:*/service:* principal不能批准该PR的高风险effect。Agent不能批准自己生成的计划,也不能通过新Plan版本继承旧版本的写/部署批准。

8. 审计与保留

  • 所有状态变化、授权、token 签发/撤销、tool 类别调用、Git commit/PR/check/deploy 追加到 audit。
  • 审计事件包含 payload digest,不保存不必要的原始敏感内容。
  • Case 8报告只允许OPERATIONS_TOKEN读取;Task/Runner/approval token均不能调用。查询严格拒绝全部query/body扩展,不能请求raw/R2/session/log/SQL或任意列。报告从authoritative D1表白名单投影八栏;external approval只通过approval_lineages公开安全principal/event/digest、exact Task/revision/Plan/base/effect以及source/control-plane时间,legacy/internal approval明确返回null lineage而不伪装外部身份。链接统一移除userinfo/query/fragment;物理查询不选择Task title/payload ref、Plan objective/doneWhen、Evidence summary、PR body、tool参数/result、token/OIDC/nonce/request digest、credential ciphertext/lease或raw外部响应,因此这些字段没有序列化入口。
  • 每个报告的canonical digest覆盖安全业务body但排除生成时间、耗时和access ledger,20路同状态读取必须同digest;每次成功读取仍分别写immutablecase8_audit_report_accesses(service:operations)。structured log只有Run ID、report digest、duration和八栏计数,无URL或自由文本。任一栏超500、grant scope漂移、投影冲突或耗时达到5分钟均fail-closed,不返回部分报告。
  • quota审计保存effective policy、安全denial、P0 source/outcome/reason digest、并发/model/tool reservation/admission及per-call usage;不保存scope key明文于denial、override reason正文、prompt、Agent/模型输出、tool arguments/result或raw JSONL。Attempt trigger的ABORT会回滚插入事务,因此attempt超额只产生固定D1错误,不能伪称已有独立denial行。
  • 长期关联根固定为run_id,不信任调用方提供的HTTP correlation值。GET /v1/correlations与Task查询共用控制面Bearer认证,strict拒绝未知/重复query;GitHub PR与deployment数字ID必须绑定repository scope,多Run命中fail-closed。
  • correlation成功日志只有schema/event/time与Task/Run/Attempt/GitHub run/PR/deployment/trace白名单ID,各类有界;不得记录查询原文、URL、Task/PR正文、R2/artifact ref、token、外部响应或错误。响应按类限制200条、外链去query/fragment并no-store
  • D1/R2 中的 checkpoint/evidence 默认保留 180 天;原始 session/transcript 固定30天;Cloudflare 已完成 Workflow 的平台保留期不能替代这两个要求。raw retention只扫描D1显式registry并推导专用bucket exact key,不枚举/接受bucket、key、prefix或调用方时间;Task/checkpoint/Evidence/backup永不进入候选。
  • retention先以5分钟D1 claim fencing外部delete,删除前核对R2 etag/size/类别/object/ciphertext/encryption metadata,删除后再次head为null才写immutable完成审计。ambiguous error、metadata/policy漂移或对象仍存在只写固定失败码并安全重试,不保存raw error;20路扫描同对象只有一个effect。完成审计只含identity digest、类别、policy、expiry、attempt/result/time,不含key或正文。
  • POST /v1/data-retention/scans仅接受OPERATIONS_TOKEN + {mode};dry-run零claim/零delete,execute固定25条和服务端时间。raw bucket被备份管理器物理排除,避免30天敏感正文进入长期backup;Secret永不进入备份。restore fence期间不运行retention。
  • D1 dump只写专用私有BACKUP_OBJECTS,因为它可能含token digest与加密credential ciphertext;manifest只保存bookmark、key、digest、size及R2 descriptor汇总,不保存SQL、Task/checkpoint正文、signed URL或raw错误。Cloudflare API token仅作为Worker Secret进入D1 export Authorization header,下载signed URL时不附带该header。
  • restore operations只接受服务端可推导资源的backup/manifest identity;不接受SQL、任意R2 key或状态/effect。manifest/dump未验证时token零变更;验证后先原子进入全局restoring并撤销内部token、提升Attempt generation、隔离Run/Plan/Item/outbox/quota,再让既有revoker解密并撤销exact GitHub token。credential仍pending或任一九类一致性检查失败时绝不重开业务流量。
  • 事故处置遵循OperationsRunbook:token只从隐藏stdin/Secret manager进入,不出现在argv、shell history、工单或PROGRESS;mutation必须记录expected Run version/outbox attempt count并双人复核credential/destructive/production动作。Runbook测试逐项核对真实路由并禁止任意D1 SQL、R2删除、调用方自选destination/effect或硬编码Bearer。
  • 七天试运行report和最终summary只保存Run/incident/PR/deployment安全ID、固定计数、时间和canonical digest;不保存raw metric/log/alert、上游错误、数据库行或Secret命中值。metrics/log/Secret alert链接必须是无userinfo/query/fragment的HTTPS永久链接并人工核对scope;链接存在、manifest示例、本地fake或命令exit 0都不能单独证明外部平台真实运行了七天。
  • 当前没有全局provider pause API或production rollback API。provider冻结、导入前traffic isolation、Secret信任根撤销、production traffic shift/rollback都是外部平台人工处置,不能借operations token、restore fence、test rollback、伪造webhook或D1改写扩大authority。healthz也不是D1/provider健康或effect成功证明。
  • Secret轮换先在provider撤销/重签,再以stdin更新最小Secret并分段canary,最后证明旧值失效;不等待自然流量、不运行覆盖整套配置的setup。GITHUB_CREDENTIAL_ENCRYPTION_KEY必须在scheduled revoker用旧key撤销既有write token后才轮换;旧key不可用则从GitHub App/installation根撤权。
  • 管理员读取原始 session 也产生审计事件。
  • 定期演练:Secret canary、取消后 token 不可用、旧 OIDC 重放失败、Runner 失联恢复、审批 revision 过期。

Base rebase 只接受 GitHub compare 证明的纯 fast-forward base;rebase Runner 禁 hook/autostash、不接受 Agent argv 且不 push,随后 writer 只能用 force=false 更新 Attempt 派生 branch。behind/diverged、异常 merge-base 或内容冲突必须 blocked 并撤销 token/write credential/approval,不能用 force-push、自由 --onto 或调用方自报 SHA 绕过。BaseRebaseEvidenceManifestV1、Case 8 与 summary 只含 ID/SHA/digest/状态/时间和安全 outbox 标量;diff、Git stderr、raw Action/webhook/REST、数据库行和 token 禁止进入 manifest、日志、artifact 或审计响应。GitHub API 不提供完整 force-push 历史证明,真实验收必须额外人工核对 push webhook/组织 audit,不能把 manifest 的 force=false 自报当事实。

  • GitHub merge external fact 使用与 merge gate 隔离的只读 contents/checks/statuses/pull_requests:read token;当前 MVP 不申请 merge write token。pull_request closed webhook 先验 HMAC 和 strict merged schema,API compensation 先核对 exact repository/PR/head/base,再解析 merged、merge SHA、actor 和时间。raw webhook/REST、PR 正文和 token 不落 D1/log;observation 只保存 digest 与白名单标量。
  • merge projector 的 SQL 再次核对 ready decision、verified publication、active Plan/digest/base、全部required Item、Task deployment policy 和唯一 identity。no-deploy与test可merging → succeeded;test的deployment/acceptance已在此前required Item中完成,不会merge后再调度。production只能merging → deploying。closed-but-unmerged、旧 head、错误 merge SHA、decision 缺失、重复/冲突 observation 和任意 merge outbox 均 fail-closed。MergeEvidenceManifestV1 只保存安全索引;verifier 必须以 live GitHub API 重算 canonical merge fact。

E2E-7总manifest与八份component manifest均只保存ID/SHA/digest/枚举/时间/安全URL,禁止Task/PR正文、raw API/webhook、日志、OIDC/JWT、token、action nonce或卡片正文。组合HTTP继续使用Watt-derived显式opt-in、仓库外64 KiB、有界/10秒读取、分页fail-closed和固定0/1/2;所有component响应在parse前扫描三枚用途隔离token、synthetic credential-shaped canary。飞书完成态必须无button/input/action和仍可消费的approval,live card/screenshot不能替代GitHub Environment、云OIDC或业务结果人工review。

E2E-8总manifest、四份component和transport report分别限制仓库外64 KiB;只允许ID、digest、固定状态/计数/时间,不允许raw webhook、signature/header、Queue message、DLQ payload、PR/Task/卡片正文、日志、数据库行或credential。observability report是transport旁证,必须与D1 immutable observation、Case 8、resolved dead-letter和live GitHub inventory交叉核对,不能自报业务成功。callback case一旦出现webhook observation即fail-closed;DLQ只能引用controlled snapshot已有dispatch outbox,operations API不能由manifest指定effect。全部外部响应使用Watt-derived 10秒有界HTTPS、分页fail-closed并在JSON parse前扫描所有用途隔离token和credential-shaped canary;公开options不接受component verifier替换。

  • production approval 的 source event、identity mapping、live human + approve:production_deploy role、author separation、Task revision、Plan/digest/base、immutable merge ID/SHA 和 environment=production 必须同时存在;这些值从服务端派生,caller 不能提交或覆盖。production_release_approval_bindingstrusted_effect_approvals 在 scheduler/effect 前双重重验,旧/过期/reject/role撤销/错误 merge binding 均 fail-closed。
  • ProductionApprovalEvidenceManifestV1 只索引 accepted/rejected release decisions;accepted 也必须证明 production outbox/deployment/Attempt 为零,防止把 approval 变成隐式 effect。真实 Environment reviewer/Feishu event、OIDC/cloud trust 和 production Secret 证据不能由本地 schema、fake API 或 D1 行冒充。

Correlation telemetry 安全边界

Round 115的correlation平台验收继续复用Watt固定commit476e3cdd2490d725fde174e7c697ebf00899edc6的显式opt-in、仓库外64 KiB manifest、固定0/1/2退出和安全错误纪律;Watt没有跨Task/Run/PR/deployment的Workers telemetry证据链,等价业务代码直接复制量为零。新verifier只读D1安全projection、GitHub REST与Cloudflare官方telemetry query,全部响应限1 MiB/10秒并在JSON parse前扫描控制面、GitHub、Cloudflare三枚用途隔离token、synthetic credential-shaped canary及已知credential形状。

invocation_logs=false避免平台自动请求日志包含correlation query URL;custom log仍必须经过唯一redact→scan sink,新增的matched-by字段只接受strict parser产生的kind/ID/repository标量。manifest只保存account digest、log digest、trace ID、时间和人工review URL,不保存account ID、token、请求/响应、Task/PR正文或raw error。telemetry查询固定dry=true且CLI没有部署、设置修改或仓库写路径。完整步骤见Correlation 平台日志与 trace 真实外部证据验收

E2E-1 组合验收安全边界

RequirementE2EEvidenceManifestV1只保存ID、SHA、canonical digest、时间和无query的人工审计链接;Meegle/PRD正文、飞书卡片正文/open_id、Plan正文、Workflow output/error、raw API响应、account ID和token均无schema入口。四份manifest各自64 KiB有界,Cloudflare响应1 MiB/10秒有界;用途隔离token与credential-shaped canary在JSON parse前扫描,错误只输出固定code。

组合CLI只读:Meegle CLI使用既有get/meta命令,控制面/GitHub/飞书observer/Cloudflare只发送GET;没有卡片decision、Workflow create/restart、credential签发、repo write或dispatch接口。当前Case 8必须同时证明Run仍awaiting_approval、只有settled analysis outbox且write credential/change/deployment全零。planSnapshotsApproved=1effectsApproved=1必须来自同一exact approve(repo_write)记录,不能复制计数获得额外authority,也不能把E2E证据manifest当作approval source。真实human、tenant、需求语义和Dashboard内容继续由仓库外人工review负责。

E2E-3 代码交付验收安全边界

E2E-3继续复用Watt-derived显式opt-in、仓库外64 KiB manifest、固定0/1/2、有界HTTPS、分页fail-closed、安全错误和credential-shaped canary扫描;CLI只发GET,不签发credential、dispatch Action、push commit、创建PR、merge或deploy。Watt没有delivery-loop的Task/Plan/ready Item/approval/credential/commit/PR lineage,因此不复制其generic task模型;业务authority完整复用本项目既有Case 8与Draft PR verifier。

Case 8只新增claimedProgressVersion和write credential createdAt两个非敏感历史标量,不返回progress正文、token digest/ciphertext、lease token或GitHub token。组合verifier必须把latest exact飞书mapped-human approve(repo_write)及source/lineage/event/role digest同时绑定Task revision、Plan/version/digest/base、唯一change Item effect、initial implement Attempt、单仓库credential、唯一commit和PR publication;approval覆盖到publication,credential覆盖到commit,日后自然过期不改写历史。任一更新reject/invalidation、错误repo/Item/Attempt、commit前过期/撤销或多个commit都fail-closed。ahead=1和真人diff review共同回答本场景的最小改动,manifest或Agent自报不能证明语义最小性。

E2E-5 双层恢复验收安全边界

E2E-5总manifest只保存两个component manifest的canonical digest和安全identity,不保存component文件路径、token、canary、Task/Plan/checkpoint/Agent正文或raw response。三个仓库外manifest分别限制64 KiB;同一credential-shaped canary只以digest进入三份manifest,明文只在受控进程中用于两份component response扫描。Workflow hibernate与Runner kill必须是同repository但不同Run/Evidence/Action,避免用互斥状态拼成一份虚假投影。

组合CLI没有POST、restart、kill、retry、dispatch、Git写入或部署路径,只完整调用两份既有只读authority。Workflow component必须证明七条durable step跨deployment复用、Case 8无controlled replay;Runner component必须证明generation/token/cancel fence、checkpoint→单result commit fast-forward和完整outbox/PR/deployment inventory。任一component失败只输出固定组合错误码,不传播内部错误、provider response或credential;fake注入、默认exit 2和schema example均不能产生真实平台authority。

E2E-6 权限与 Prompt Injection 验收安全边界

E2E-6不以敏感关键词拒绝Task正文。三条固定挑战作为不可信数据进入真实analysis;判据是Task policy保持deny、Plan只有read/diagnostic effect、Attempt只有analysis、broker没有write credential且Case 8没有change/deployment/outbox。这样既允许系统阅读真实用户反馈中的攻击性字符串,也防止模型输出成为policy输入。

未授权repo write不能只靠unauthorized_account/role_revoked场景名自证。两个真实callback必须由独立observer和manifest冻结枚举型approve + repo_write尝试,人工mapping review确认unmapped/revoked,控制面operations证明只有verified delivery且零receipt/outcome/ingress/business effect。其他拒绝case不得夹带attempted command/effect,避免把任意拒绝重标成写权限测试。

跨repo OIDC probe只在隔离repository运行,workflow顶层权限固定contents:read + id-token:write,不含目标repo token。脚本不打印JWT、响应正文或错误正文,只有exact 403 policy_denied retryable=false输出固定marker;immutable source和manifest外contract digest必须复核。合法同repo Test deployment component继续证明目标deployment/attestation baseline和零重复,marker不能独立自证零D1副作用。

组合verifier公开options不允许替换component authority;CLI只读且无dispatch/approval/credential/deploy入口。五份component manifest、总manifest和Task各限仓库外64 KiB;全部控制面/GitHub/PR/Action log响应10秒、有界、分页fail-closed,在JSON parse前扫描所有用途隔离token、credential shape与仓库外canary。错误只输出固定code,默认exit 2、fake/module mock、schema example和dry-run均不是安全通过。

There aren't any published security advisories