Files
qinglong/docs/adr/ADR-0253-private-worker-management-evidence-image-release-gate.md
T

80 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-0253:私密 Worker 管理证据的镜像发布门
- 状态:Acceptedworkflow、freshness gate、静态审计与负向测试已实现;生产 JIT runner 成功记录待取得)
- 日期:2026-08-01
- 关联 RFCQL-RFC-0001 D-235、D-236
- 关联 ADRADR-0128、ADR-0196、ADR-0252
- 后续修订:ADR-0425 已把本 ADR 的私有 Worker evidence gate 收窄到 `cluster|all` 发布族;`local` 发布不得等待该证据,Cluster 的 source/freshness/private-runner 约束继续有效。
## 背景
D-235 已能用 final report 与四份 source 独立重判 Worker management 的 external ceremony、durable audit、leaf
revocation 和 client CA rollover,但镜像发布 workflow 尚未消费该结论。直接接入存在四类风险:
- 把 source 上传为 GitHub artifact/cache 会复制受限生产证据并扩大 retention 与读取主体;
- 只上传低敏 final 后检查 `passed=true` 会丢失 D-235 的 source-aware 重判能力;
- tag push 自动发布会绕过生产证据准备、双人复核和受保护 environment
- 在 GitHub-hosted builder 上读取 source,会把生产证据与 registry/OIDC 写 authority 放进同一安全域。
## 决策
1. `.github/workflows/ql3-image-release.yml` 只接受显式 `workflow_dispatch`。dispatch 必须选择 exact protected
`v3` tag,输入 version 必须与 tag 名完全一致;普通 branch、自动 tag push、PR 和 schedule 均不能发布。
2. 发布前增加唯一 `worker-management-release-evidence` job。它固定运行在带
`ql3-release-evidence-ephemeral` 标签的 Linux self-hosted JIT runner,并受
`ql3-production-release-evidence` environment reviewer 保护。标签只是调度条件;真正的隔离必须由 runner
provisioner 保证每个 job 一次注册、一次执行、随后销毁。
3. 私密文件由 runner provisioner 以当前 runner UID、canonical `0700` 目录和 `0600` regular file 预挂载到
`/run/qinglong3-release-evidence/$GITHUB_SHA`。文件名固定为 final、ceremony、durable、PKI v2 和 CA rollover
五个名称;workflow 不接受用户提供的路径、目录扫描、glob、URL 或 artifact download。
4. gate 重新执行 D-235 source-aware auditor,并额外要求 final `observedAt` 不超过 24 小时、不得比 runner clock
超前 5 分钟。成功摘要只包含 fixture、commit、version、final SHA-256 和最大年龄,不输出 source 内容。
5. workflow 顶层和 evidence job 只有 `contents:read`。GHCR、OIDC、attestation 与 artifact-metadata 写权限只授予
`publish` job,且 `publish` 必须无条件 `needs: worker-management-release-evidence`。证据 job 失败、超时、未获
environment approval 或 runner 缺失时,三个 image matrix 均不得启动。
6. 整个 release workflow 禁止 `actions/upload-artifact``actions/cache`。证据挂载不进入 workspace、job output、
workflow artifact、BuildKit context、SBOM、provenance 或 OCI attestation。runner 销毁/卸载由外部 provisioner
执行;workflow 不删除作为审计事实来源的外部归档。
7. environment reviewer 必须确认 tag protection、tag commit、workflow 与 gate script 均来自已审发布提交。
自托管 runner 不参与镜像 build、签名或 attestation;实际 publisher 继续使用 GitHub-hosted runner,既有
`--deny-self-hosted-runners` provenance 验证保持不变。
8. 本能力是 repository-level 短期发布逻辑,不新增 workspace package、第三方依赖、数据库 migration、Profile
artifact、daemon、controller、watcher、timer、listener、Pool 或设备常驻资源。
## 失败与恢复
- 没有匹配 JIT runner 或 environment 未批准:发布保持 pending/失败,不回退到 GitHub-hosted evidence audit
- 任一文件缺失、owner/mode/symlink/大小不合法:gate 在 publish 获得写 token 前失败;
- source 被替换、final claimed gate 被修改或 schema 不兼容:重新采集/聚合,禁止手工修补 final;
- evidence 超过 24 小时:重新执行生产 ceremony 与必要的证据协议,生成新的 no-replace final
- runner clock 超前/落后:修复可信时间源后重跑,不扩大 future skew
- tag/version 不一致:以正确受保护 tag 重新 dispatch,不允许 branch fallback
- runner 执行后未被 provisioner 销毁:视为基础设施事故,停止后续 dispatch,隔离 runner 并轮换其注册凭据。
## 被拒绝的替代方案
### 上传五个 JSON 为私有 GitHub artifact
拒绝。repo 私有性不等于最小 custody;artifact 会新增复制、下载主体、retention 和误传风险。
### 只把 final report 放进 repository secret
拒绝。final 不能替代四份 source,且 GitHub secret 的大小/轮换模型不适合有界文件归档。
### 在 publisher job 内直接审计
拒绝。它会让同一个 job 同时持有生产 source、GHCR write、OIDC signing 和 attestation authority。
### 保留 tag push 并异步查询另一 workflow 的成功状态
拒绝。跨 workflow run/commit/tag 的竞态和重放关系更复杂;同一 dispatch 内的强 `needs` 提供更直接的失败关闭。
## 验证
- D-235 + D-236 定向 11/11source-aware happy path、stale/future、source replacement、exact identity arguments
- image release 静态/变异契约 26/26,覆盖自动 tag push、缺失 dependency、persistent runner、artifact upload、
非 commit-scoped mount、evidence write authority 与 movable action
- `audit:image-release:ql3` 返回 `sourceAware=true``privateEphemeralRunner=true`
`maximumAgeSeconds=86400``artifactUpload=false`
- workspace 仍为 19 个 QL3 package,未新增第三方依赖或 Profile 稳态资源。