Files
qinglong/docs/adr/ADR-0438-content-free-private-release-evidence-receipt-chain.md
T

84 lines
7.0 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-0438:内容无关的私有发布证据收据链
- 状态:Accepted
- 日期:2026-08-18
- 关联 RFCQL-RFC-0001 D-03、D-14、D-333、D-335、D-336、D-346
- 关联 ADRADR-0245、ADR-0264、ADR-0425、ADR-0427、ADR-0428、ADR-0430、ADR-0436、ADR-0437
- SupersedesADR-0427 的 release-set v1 聚合边界,以及 ADR-0428 的 release-set v1 OCI media type
## 上下文
Cluster/All 发布已经要求两个 commit-scoped、24 小时内的私有门成功:Worker management 重新审计五份来源报告,CloudNativePG
disaster recovery 重新审计对象存储 backup/WAL/latest restore/PITR、证书轮换和三项静态供应链锁。publisher 通过 `needs` 只能看到 job
成功或失败,最终公开 release-set 却只记录候选策略中的“这些证据必须存在”,没有绑定本次 workflow attempt 实际审核的报告摘要。
因此 durable catalog 可以证明镜像、source 和 deployment family,却不能证明某个 Cluster release-set 对应哪一组私有发布证据。直接上传
原始报告会泄漏生产环境事实并扩大保留面;只依赖 GitHub job 状态又会在 workflow artifact 过期后丢失可验证的发布闭包。
## 决策
1. 两个私有 evidence job 在既有 release gate 成功后,各自产生一份
`qinglong/private-release-evidence-receipt@v1`。收据精确绑定 release version、40-hex source revision、source tag、`cluster|all`
scope、evidence kind、report SHA-256、观测/审核时间和 24 小时窗口,并具有自身 canonical SHA-256。
2. Worker 收据只投影 source-aware 聚合报告摘要。CloudNativePG 收据额外投影 backup、Barman Cloud 与 cert-manager 三项静态审计结果摘要;
静态 selection lock 继续保持 `releaseReady=false`,因为它自身不携带时效证据。实际某次发布是否 ready 由收据与 release-set 闭包决定,
不能永久翻转一个静态文件来冒充持续有效的现场证据。
3. 收据不得包含原始报告、路径、credential、token、连接信息、私钥、Kubernetes 对象或命令 transcript。它显式声明
`sourceReportsUploaded=false``privateReportContentPublished=false`,并诚实记录公开消费者无法在缺少私有报告时重放外部结果。
4. 私有 job 只上传收据文件,保留 1 天;原报告仍只存在于 commit-scoped ephemeral runner mount,禁止 cache 或 artifact 上传。artifact 名必须
同时绑定 `run_id/run_attempt/evidenceKind`,下载时也必须使用同一模式。
5. release-set 升级为 `qinglong/release-set@v2``local` scope 必须恰好零份收据;`cluster|all` 必须按固定顺序恰好包含
`worker-management``cloudnativepg-disaster-recovery` 两份同 release identity 收据。缺失、重复、额外 kind、source/scope、freshness、
static audit 或任一 digest 漂移均在 tag promotion 和 catalog publication 前失败关闭。
6. release-set v2 把完整 content-free 收据嵌入自身并纳入 `releaseSetDigest`,随后由 file provenance、OCI catalog immutable digest、Cosign 与
GitHub provenance 共同保护。原始 1 天 receipt artifact 只是跨 job 交接,长期 authority 是公开 catalog 中的 release-set v2。
7. OCI artifact/file media type 升为 `application/vnd.qinglong.release-set.v2+json`。不能用 v1 media type 承载新增字段,也不接受 v1
release-set 进入新部署锁或 catalog consumer。
8. 不新增 workspace package、production dependency、数据库、migration、listener、timer、controller、Pod 或设备侧工具。所有新工作只发生在
Cluster/All 的短生命周期 release runnerLocal 发布不等待私有 evidence jobEdge/Standalone 只消费工作站生成的 selection 与 immutable
image。
## 失败与恢复
- 私有报告不新鲜或 source 不匹配:私有 job 失败,不生成收据;重新取得同 source 的现场证据后重跑受保护 tag。
- 收据 artifact 缺失、来自其他 attempt 或目录中出现额外文件:release-set 聚合失败;不能以 job success 或手工 digest 替代。
- 收据已生成但 publish matrix 失败:不 promotion;同一 tag 重跑必须重新审核仍在时效窗口内的证据并产生新收据。
- catalog 消费者可验证收据结构、自摘要和 release-set 闭包,但不能声称重放了私有现场结果;需要审计原始事实时进入受控私有 evidence 环境。
- v1 release-set:3.0 尚未正式发布,不提供隐式兼容;从同一 source 重新执行 release workflow 生成 v2。
## 部署与资源影响
- Local scope 的 release-set v2 收据数组为空,不启动两个私有 runner,不增加路由设备下载、CPU、内存或稳态连接。
- Cluster/All 的公开 release-set 增加两份小型 content-free JSON,节点无需安装证据工具或访问私有报告;可信工作站随 catalog 一并审核。
- 原始证据不离开私有 runner,公开内容仅能做 equality/source/freshness binding,不能反推出 credential 或生产对象内容。
## 被拒绝的替代方案
### 只依赖 GitHub `needs.<job>.result`
拒绝。它是瞬时调度事实,不能进入 release-set digest,也无法在 workflow 记录过期后由部署者独立核对。
### 上传全部私有证据到 release-set job
拒绝。公共 publisher 不需要原始生产事实;扩大跨 runner 传输和保留面违反最小披露边界。
### 把静态 Barman/cert-manager lock 永久改为 release-ready
拒绝。静态供应链选择没有 24 小时 freshness、backup/PITR 或 rotation 事实。ready 是 source-scoped release 结论,不是永久 lock 属性。
### 只在 image record 中加入一个布尔值
拒绝。布尔值无法绑定证据内容,也会把 deployment-family 级事实复制到每个镜像 publisherrelease-set 才是跨镜像与私有证据的唯一终态 authority。
## 验证
- receipt contract 覆盖 Worker/DR exact projection、source/scope/freshness/report/static-lock/self-digest 漂移、私有字段注入、closed CLI、stable
private read、mode `0600` no-replace 和内容无关输出;
- release-set contract 覆盖 Local 零收据、Cluster/All exact-two、缺失/额外/漂移收据、v2 standalone inspection 与 digest 闭包;
- workflow 静态门冻结同 attempt artifact、私有报告不上传、两份收据 create/audit、release-set 下载与 aggregate/audit handoff,以及 v2 OCI media type
- 定向契约 134/134,完整 backend 为 1,360 pass/2 条件 skip/0 fail18-package clean build/test 退出 012 项架构/部署审计和 14 档
Local artifact 全部 compatibleworkspace 保持 18 packages 且没有 single-source/shallow-source package
- PostgreSQL 18.6/arm64 HA 重跑 142/142 gates、timeline `1→2`,独立 evidence audit compatible,报告 SHA-256 为
`1e7c31cc6c7aa3e1e0398eb51696b6054850d5fc25910a08d6faffc9a75f1c6f`container/network/volume 残留为 0
- 完整结果同步记录于 QL-RFC-0001 D-346;首份真实公开收据和 catalog 仍须由受保护 `v3` release tag 产生。