feat(ql3): publish complete release sets

This commit is contained in:
whyour
2026-08-16 10:06:34 +08:00
parent bad8399cc3
commit 41549524d4
16 changed files with 1302 additions and 39 deletions
+1
View File
@@ -11,6 +11,7 @@
最新增量证据(2026-08-16):
- D-335/ADR-0427(已接受;公开发布结果待实际 tag):发布矩阵不再让每个镜像验证成功后独立写 version/source tag。每个 publisher 只产生不可变 digest,在远端 manifest、Cosign、四类 GitHub attestation 与适用的 Local rollout 全部验证后生成绑定同一 candidate/scope/source/owner/repository/platform/digest 的 canonical image record;唯一 release-set 终态 job 只在完整 publish matrix 成功后下载 exact `run_id/run_attempt` record,重新生成 candidate,并要求 Local 一镜像、Cluster 四镜像或 All 五镜像集合无遗漏、无重复、顺序一致。独立审计通过后才统一 promotion,写前回读全部 source digest/既有 tag、冲突失败、缺失才 copy、写后再验 digest;明确不宣称 GHCR 跨仓库原子性,以 `verify_exact_digest_then_continue` 支持同源幂等恢复。最终 `qinglong/release-set@v1` 同时冻结 deployment family、五类可选镜像、image-record digest 和 `@sha256:` 引用,获得 GitHub file provenance 并作为 90 天 deployment digest-lock artifact 发布。Edge/Standalone 只消费 `local` setCluster 只消费四角色 set`all` 不把两族运行时耦合;不新增 package、生产依赖、Pod、controller、listener、timer、watcher、数据库、migration、SQL、Pool 或低配设备常驻开销。定向 contract/workflow 回归 73/73,联动发布/Console distribution 回归 77/77backend 1,264 pass/2 条件 skip/0 fail18-package clean build/test 退出 0package boundary 保持 18 packages、`singleSourcePackages=[]``shallowSourcePackages=[]`dependency、Edge import、Cluster/Worker deployment、image release 与 Local image 审计均 compatible。14 档 Local artifact 全部 compatible,默认 Edge/Standalone 精确保持 2,589,890/2,589,968 bytes、315 files、56 modulesapplication+AI 为 4,493,043/4,493,175 bytesMCP 为 7,315,930/7,316,038 bytesCluster Admin pack 保持 250 files、271,238-byte tarball、1,690,196-byte unpacked。本 Gate 无数据库/HA 拓扑变化,复用 D-331/D-333 PostgreSQL 18.6 arm64 142/142、timeline `1→2` 基线;公开 tag 尚未执行,因此不宣称真实 GHCR promotion 或线上 attestation 已成功。
- D-334/ADR-0426(已接受):根级 canonical `ql3-release.json` 现在是唯一 QingLong 3 release identity authority,精确冻结 3.x SemVer、Node 24.18.0/engine、18-package 边界和 legacy 2.x 排除事实;发布候选、四组容器、Cluster/Worker/Console 部署、Local/Cluster image audit、CloudNativePG、物理 Edge 与外部恢复审计均改为读取同一 authoritycandidate contract 额外绑定 identity schema 与 SHA-256。共享 CI 新增 `audit:release-version:ql3`,失败关闭 18 个 workspace、四组 build/runtime manifest+lock、Dockerfile Node/version label 与 242 个部署文本文件中的 32 个 image reference/36 个版本 occurrence。维护者升级版本必须走 closed `audit|plan|apply`plan 只接受严格递增 exact v3 SemVer并生成 no-replace `0600`、逐文件 path/mode/replacement/before-after bytes+digest 和自身 digestapply 先全量预检 65 文件/83 处替换,再用同目录确定性临时文件、fsync+rename 逐文件收敛,允许 source/target 混合状态原 plan 幂等恢复并生成 digest-bound report,绝不修改 legacy 根 2.x、自动 commit/tag/push 或宣称跨文件单事务。实现不新增 workspace package、生产依赖、数据库、migration、SQL、Pool、Pod、listener、timer、watcher 或任何低配/集群常驻开销。定向回归 177/177backend 1,254 pass/2 条件 skip/0 fail18-package clean build/test 退出 0package boundary 保持 18 packages、`singleSourcePackages=[]``shallowSourcePackages=[]`dependency、Edge import、Cluster deployment、image release 与 Local image 审计均 compatible。14 档 Local artifact 全部 compatible,默认 Edge/Standalone 精确保持 2,589,890/2,589,968 bytes、315 files、56 modulesapplication+AI 为 4,493,043/4,493,175 bytesMCP 为 7,315,930/7,316,038 bytesCluster Admin pack 保持 250 files、271,238-byte tarball、1,690,196-byte unpacked。本 Gate 无数据库/HA 拓扑变化,复用 D-331/D-333 PostgreSQL 18.6 arm64 142/142、timeline `1→2` 基线;完整回归未发现数据库或部署拓扑漂移。
- D-333/ADR-0425(已接受;公开发布结果待实际 tag):3.0 发布入口不再把所有部署者绑成一个不可分割矩阵。唯一 `.github/workflows/ql3-image-release.yml` 增加 closed `local|cluster|all` deployment-family scope;根级 source-derived release-candidate contract 从 exact `v3` SemVer/tag/40-hex revision、18 个边界审计通过且非 single/shallow 的 workspace、Node 24.18.0 engine、容器 runtime manifest/Dockerfile version、双架构和部署 profile 推导唯一 OS/publish matrix,并以 canonical SHA-256 失败关闭版本或源码漂移。`local` 只发布 AI-excluded Local image、只要求 Edge/Standalone digest rollout,不再等待 Worker management/CloudNativePG 私有 HA evidence`cluster` 才要求两个 ephemeral private evidence gate,并闭合此前遗漏的 `qinglong3-worker`,与 control/control-ai/admin 一同进入 native amd64/arm64 build-once、Trivy OS scan、CycloneDX、OCI merge、Cosign 与 GitHub attestation 链;`all` 同时保留两族门禁。legacy 根 `2.21.0-14` 被显式标记为不参与 3.0 release identity,而不是伪改旧产品版本。Worker 现在有 27-component24 external/3 internal)、28-node 的 production SBOMBSD-3-Clause 纳入受审 allowlistWorker config 固定 `65532:65532``worker` profile、`edge,node` capacity labels 和 3.0 versioncontrol/admin 也补齐同一 version label。candidate contract 作为第四类 digest-bound GitHub predicate 发布并远端回读,Cluster Admin verifier/外部 ceremony/offline audit 同步升级为四类 attestation/八步 transcript。实现不新增 workspace package、生产依赖、数据库、migration、SQL、Pool、listener、timer、watcher 或低配设备常驻资源。定向 105/105、backend 1,246 pass/2 条件 skip/0 fail、18-package clean build/test 均通过;package boundary 确认为 18 packages、`singleSourcePackages=[]``shallowSourcePackages=[]`dependency、Edge import、Cluster/Worker deployment、image release、OS vulnerability policy、Console/distribution 审计均 compatible,四个 runtime dependency root 的离线缓存审计为 0 vulnerability。14 档 Local artifact 全部 compatible,默认 Edge/Standalone 精确保持 2,589,890/2,589,968 bytes、315 files、56 modulesapplication+AI 为 4,493,043/4,493,175 bytesMCP 为 7,315,930/7,316,038 bytesCluster Admin npm pack 仍为 250 files、271,238-byte tarball、1,690,196-byte unpacked。由于本 Gate 不改变 schema、migration、SQL、role、Pool 或连接/HA 拓扑,不重复执行 PostgreSQL 门,继续复用 D-331 的 PostgreSQL 18.6 arm64 physical HA 142/142、timeline `1→2` 基线。公开 tag/digest 尚不存在,因此不宣称真实 GHCR/Cosign/attestation 发布成功,在线依赖漏洞新鲜度与五镜像远端门由实际 release workflow 重新取得。
- D-332/ADR-0424(实现门完成、外部验收待公开 release):从 exact reviewed `v3.*` source tag 执行的 Cluster Admin release workstation ceremony 已实现为根级 runner + 独立 offline auditor,不新增 workspace package、生产依赖、产品命令、镜像内容或常驻组件。runner 只接受 owner-bound `ghcr.io/<owner>/qinglong3-cluster-admin@sha256:<digest>`、40-hex source revision、完整 tag ref、canonical absolute `cosign|gh|docker`、current-owner `0600` 短期 GitHub token file 与 no-replace 私有 report;三个工具按绝对路径直接执行且前后复验 inode/size/SHA-256,不经 shell/ambient PATHtoken 只注入 4 个 `gh attestation verify` 子进程。ceremony 精确验证 keyless workflow identity、provenance、CycloneDX、OS-vulnerability evidence 与 D-333 source-derived release-candidate contract,拉取并 inspect 同一 RepoDigest,再在 non-root/read-only/network-none/drop-ALL/no-new-privileges/128 MiB/0.25 CPU/32 PIDs 下运行 release image 内置 `evidence-verify` 检查固定非敏感 vector。成功报告只含 public release identity、tool/argv/stdout/stderr digest、字节数、isolation/limitation 与自身 canonical SHA-256,不含原始 transcript、token、路径或 workstation identityoffline auditor 只证明 canonical structure、digest 和 expected identity binding,明确 `externalResults=not_replayed``reportAttestation=none``actionAuthority=none`。定向正负门覆盖 token 隔离、mutable/source drift、tool/file authority drift、no-replace、结构重签和 report swappingbackend 1,233 pass/2 条件 skip、Cluster Admin 387 pass/3 条件 skip、18-package clean build/test 退出 0。workspace 保持 18 package、无 single/shallow packagenpm pack 保持 250 files、271,238-byte tarball、1,690,196-byte unpackedpackage/dependency/Edge import/Cluster deployment/image release/OS vulnerability/Console/distribution 审计均 compatible。14 档 Local artifact 全部 compatible,默认 Edge/Standalone 精确保持 2,589,890/2,589,968 bytes、315 files、56 modulesapplication+AI 与 MCP 也不变。本门无 schema/migration/SQL/role/Pool/连接拓扑变化,复用紧邻 D-331 的 PostgreSQL 18.6 arm64 142/142、timeline `1→2` 基线。由于当前没有公开 3.0 release digest,且工作站没有真实 `gh/cosign`ADR-0424 必须保持 Proposedstub 或本地 image 不能冒充最终外部 ceremony,公开 digest 可用后才记录真实 report/tool digest 并转 Accepted。
@@ -0,0 +1,85 @@
# ADR-0427:完整跨镜像发布集与部署 Digest Lock
- 状态:Accepted
- 日期:2026-08-16
- 关联 RFCQL-RFC-0001 D-03、D-14、D-333、D-334、D-335
## 上下文
D-333 已把发布候选拆成 `local|cluster|all` 三个 deployment-family scope,并让每个镜像在原生
amd64/arm64 build、OS 漏洞扫描、OCI 合并、Cosign 与四类 GitHub attestation 后独立回读验证。
但矩阵 publisher 过去会在各自验证完成后立即写 version/source tag。五个仓库之间没有事务,后续镜像失败时,
部署者可能看到只覆盖部分候选的同版本标签,也没有一个能同时冻结 scope、source revision 和所有镜像 digest 的
部署输入。
## 决策
1. 每个 publisher 只发布不可变 digest,不再写 version/source tag。完成远端 manifest、Cosign、四类 GitHub
attestation 和适用的 Local profile rollout 验证后,生成一个 canonical、no-replace、mode `0600`
`qinglong/release-set-image-record@v1`
2. image record 必须绑定同一个 source-derived release candidate digest、scope、version、source ref/revision、
lowercase repository owner、repository、双架构、immutable reference 和自身 SHA-256。矩阵 job 只保留同一
`run_id/run_attempt` 的短期 record artifact。
3. 唯一 `release-set` job 必须等待整个 publish matrix 成功,重新从 exact tag source 创建并审计 candidate,下载
同一次 workflow attempt 的全部 record,并要求 record 集与 candidate image 集精确闭合、无遗漏、无重复、顺序
与 candidate 一致。
4. 聚合结果为 `qinglong/release-set@v1`,按 `local``cluster` deployment family 列出 exact digest reference、
version/source tag、platform 和 image-record digest。`local` scope 只包含 Local image`cluster` scope 包含
control、control-ai、worker、admin`all` 同时闭合两族。
5. 只有 release set 独立重算审计成功后才允许统一 promotion。promoter 先回读所有 source digest 和已有 tag
tag 若已指向其他 digest 则失败;缺失 tag 才执行 digest-to-tag copy;每次写入后必须再次解析为 release-set
digest。
6. 不宣称 GHCR 跨 repository tag write 具有原子性。恢复模型明确为
`verify_exact_digest_then_continue`:失败重跑先验证已存在 tag,只有相同 digest 才继续补齐其余 tag。
workflow concurrency 只串行化同一 release ref,外部写入仍由 conflict preflight 失败关闭。
7. 完整 release-set JSON 使用 GitHub file provenance attestation,并作为 90 天、no-overwrite 的 deployment
digest-lock artifact 发布。生产部署必须从该文件取 `@sha256:` referenceversion/source tag 只用于发现和
人类导航,不能成为 rollout authority。
## 部署与资源影响
- Edge/Standalone 路由设备只下载并解析 `local` release set,不需要 Cluster 镜像、Kubernetes、数据库或发布
工具;运行时 artifact、模块数和常驻资源预算不变。
- Cluster 节点使用 `cluster` release set,同时锁定四个角色镜像;release-set job 只存在于发布 CI,不新增
Pod、controller、listener、timer、watcher、Pool、schema、migration 或 SQL。
- `all` 是维护者同时发布两族的便利 scope,不把 Local 部署依赖于 Cluster 私有证据,也不要求单个设备拉取
五个镜像。
## 被拒绝的替代方案
### 每个矩阵 job 验证后立即打标签
拒绝。单镜像证据正确不等于 deployment family 完整;部分成功会暴露同版本的混合状态。
### 假设多个 GHCR repository 的 tag promotion 原子
拒绝。registry 没有本 workflow 可用的跨仓库事务。显式、可重入的 digest preflight 比虚构原子性更可靠。
### 让部署继续只引用 version tag
拒绝。tag 可变且无法表达同一 source candidate 下的跨镜像闭包。生产 rollout 必须使用 release set 中的
immutable digest。
### 为 release-set 增加常驻发布协调服务
拒绝。该问题属于低频发布控制面,GitHub Actions 的有界终态 job 足够;常驻服务会给低配用户和集群都增加
不必要的新故障域。
## 验证
- contract 覆盖 Local/Cluster/All 聚合、缺失/重复/跨候选 record、owner/digest/report drift、symlink、额外文件、
closed CLI、no-replace 与独立 audit
- workflow 静态门要求 per-image publisher 不再 promotion、record 位于全部验证之后、same-run attempt 下载、
publish matrix 全成功、独立 aggregate/audit、checksum-pinned copier、先全量 preflight 后 promotion、最终 file
attestation 和 90 天 artifact
- release-set contract/workflow 定向门 73/73,连同 Admin Console distribution 交叉审计为 77/77backend
1,264 pass/2 条件 skip/0 fail18-package clean build/test 退出 0package boundary 仍为 18 packages、无
single-source/shallow packagedependency、Edge import、Cluster/Worker deployment、image release 与 Local image
审计均 compatible
- 14 档 Local artifact 全部 compatible,默认 Edge/Standalone 为 2,589,890/2,589,968 bytes、315 files、
56 modulesapplication+AI 为 4,493,043/4,493,175 bytesMCP 为 7,315,930/7,316,038 bytesCluster Admin
pack 保持 250 files、271,238-byte tarball、1,690,196-byte unpacked
- 本 Gate 不修改 schema、migration、SQL、role、Pool、连接或 HA 拓扑,因此复用 D-331/D-333 PostgreSQL 18.6
arm64 142/142、timeline `1→2` 基线,不把未重跑的数据库门冒充本阶段新证据;
- 本 ADR 接受的是源码、契约和 workflow 门。公开 tag 尚未运行时,不宣称真实 GHCR promotion、Cosign 或 GitHub
attestation 已成功;它们必须由实际 release run 取得。
+4
View File
@@ -427,6 +427,10 @@
| [ADR-0421](./ADR-0421-explicit-cluster-run-task-workflow-observation-console.md) | 显式 Cluster Run、Task 与 Workflow 观察台 | Accepted |
| [ADR-0422](./ADR-0422-browser-local-redacted-cluster-evidence-bundle.md) | 浏览器本地生成的脱敏 Cluster Evidence Bundle | Accepted |
| [ADR-0423](./ADR-0423-independent-offline-cluster-evidence-verifier.md) | 独立、离线且无 Authority 的 Cluster Evidence Verifier | Accepted |
| [ADR-0424](./ADR-0424-external-cluster-admin-release-workstation-ceremony.md) | Cluster Admin 外部发布工作站 Ceremony | Proposed |
| [ADR-0425](./ADR-0425-deployment-family-release-candidate-contract.md) | Deployment-family Release Candidate Contract | Accepted |
| [ADR-0426](./ADR-0426-source-derived-release-version-transition.md) | Source-derived QingLong 3.0 Release Version Transition | Accepted |
| [ADR-0427](./ADR-0427-complete-cross-image-release-set.md) | 完整跨镜像发布集与部署 Digest Lock | Accepted |
## 规则
@@ -0,0 +1,39 @@
# QingLong 3.0 release-set 部署准入
生产部署的镜像 authority 是成功 `ql3-image-release.yml` 运行产生的
`ql3-release-set-<version>-<scope>` artifact,不是可变 version/source tag。下载后先验证该 JSON 的 GitHub file
provenance,确认 repository、source tag、source revision 与目标发布一致,再从 `images[].reference` 读取完整
`ghcr.io/<owner>/<repository>@sha256:<digest>`
## 选择 scope
| 部署类型 | release scope | 必须出现的镜像 |
| --- | --- | --- |
| 低配路由器、Edge、Standalone | `local` | `local` |
| Kubernetes/Cluster | `cluster` | `control``control-ai``worker``admin` |
| 同时发布两族 | `all` | 上述五个镜像 |
Local 用户不需要下载 Cluster 镜像,也不依赖 CloudNativePG 或 Worker 私有发布证据。Cluster 运维者不能拿 Local
image 的证明替代任一角色镜像;尤其 Worker 与短生命周期 Admin 必须有各自 digest。
## 准入检查
1. 只接受来自成功、未重跑替换的同一 release workflow attempt 的 artifact,并验证 release-set 文件
provenance。
2. `schema` 必须为 `qinglong/release-set@v1``release.version``release.sourceRef`
`release.sourceRevision``release.scope` 必须与变更单一致。
3. 镜像集合必须与上表精确相等;每个 `reference` 必须是 digest reference,且 owner/repository 与部署目标一致。
4. Kubernetes overlay 用 `newName` 加 digest 或等价的 immutable image reference;不得把生产 placeholder 改成
`newTag`。Local compose/rollout 同样固定 `@sha256:`
5. rollout 前再次向 registry 解析 version/source tag。它们可以用于发现,但只有解析到 release set 的同一
digest 才算一致;部署仍以 digest 为准。
## 发布失败与恢复
GHCR 不提供跨 repository tag 事务,release set 明确记录 `crossRepositoryAtomicity=false`。如果 promotion 中途
失败,不删除已经正确的 tag,也不重新构建镜像。使用原 source tag/revision 重跑 release workflow:它会先验证
每个 source digest 和既有 tag;既有 tag 指向同一 digest 时继续,指向其他 digest 时立即失败。只有最终
release-set artifact 和 provenance 都生成后,才能宣布该 deployment family 可部署。
workflow artifact 当前保留 90 天,因此长期归档属于 release owner 的外部职责。进入稳定 GA 前,应把经验证的
release-set 同步到不可变、保留期满足组织策略的发布档案;同步过程不得改写 JSON。