feat(ql3): govern release version transitions

This commit is contained in:
whyour
2026-08-16 09:32:27 +08:00
parent 7130d77a76
commit bad8399cc3
24 changed files with 1462 additions and 128 deletions
+1
View File
@@ -11,6 +11,7 @@
最新增量证据(2026-08-16):
- 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。
- D-331/ADR-0423(已接受):`@qinglong/cluster-admin` 在既有 `copilot-console/` 职责目录增加独立 TypeScript evidence verifier,并以第 11 个静态产品命令 `ql3-cluster-admin evidence-verify --bundle=/absolute/evidence.json` 交付。它只通过 no-follow/stable descriptor 读取一个最大 512 KiB 的 canonical absolute UTF-8 JSON,拒绝 BOM、CRLF、minified、duplicate-key、symlink、relative path 与读取中漂移;独立固定检查 exact bundle/request shape、13 operations、16-entry/8 MiB/64-item/depth/key ceiling、安全字段白名单和顺序 typed alias,再重算不含 `contentDigest` 的 canonical SHA-256。结果明确只证明 `bundleDigest=verified`;没有原始 fact 时逐条 digest 为 `not_recomputed_without_raw_facts`server signature/attestation/durable audit 均未验证且 action authority 为 none。实现不读 stdin/environment/context,不联网、不写文件、不新增 package、依赖、route、listener、数据库、Kubernetes workload 或 Edge/Standalone closure。定向门 18/18Cluster Admin 387 pass/3 条件 skip18-package clean build/test 退出 0backend 1,225 pass/2 条件 skip/0 fail。真实 arm64 Admin image `qinglong3-cluster-admin:d331-local` 为 344,567,527 bytes,在 non-root/read-only/network-none/no-capability/no-new-privileges/0.25 CPU/128 MiB/32 PIDs 下验证 11 个命令、有效 bundle、tamper rejection 与零 verifier file write。npm pack dry-run 为 250 files、271,238-byte tarball、1,690,196-byte unpacked;结构/依赖/部署/发布/Console 审计零 findingworkspace 保持 18 package、无 single/shallow packageCluster Admin 122 个源码中 121 个位于领域目录。14 档 Local artifact 全部 compatible,默认 Edge/Standalone 仍为 2,589,890/2,589,968 bytes。因本门没有 schema/migration/SQL/role/Pool/连接拓扑变化,不重复冒充执行 HA,复用紧邻 D-330 PostgreSQL 18.6 arm64 142/142、timeline `1→2` 基线。下一门应完成公开 release digest 的外部工作站 ceremony,不得给 verifier 增加上传、签名或行动能力。
@@ -0,0 +1,107 @@
# ADR-0426:以单一源码身份治理 3.0 版本,并提供可恢复的版本迁移
- 状态:Accepted
- 日期:2026-08-16
- 关联 RFCQL-RFC-0001 D-01、D-03、D-14、D-42、D-61、D-186、D-333、D-334
- 关联 ADRADR-0196、ADR-0253、ADR-0254、ADR-0255、ADR-0425
## 背景
QingLong 3.0 的当前版本同时存在于 18 个 workspace manifest、四组容器 build/runtime manifest 与 lock、
四个 Dockerfile label,以及 Kubernetes/Console 部署材料。D-333 已能在候选发布时发现 version/tag 漂移,
但没有定义哪个文件是版本 authority,也没有提供从一个版本安全迁移到下一个版本的正式路径。人工批量替换
会漏改部署面、误改 legacy 2.x 根 package,或在进程中断后留下无法判断的新旧混合状态。
版本治理本身不应进入 Edge、Standalone 或 Cluster 常驻运行时,也不能为了统一版本引入新的 workspace package。
## 决策
### 1. `ql3-release.json` 是唯一 3.x release identity authority
根级 canonical JSON 固定 product、exact 3.x SemVer、Node 版本/engine、workspace package 数量以及 legacy 根排除事实。
读取者只接受 bounded、canonical、non-symlink regular file、精确字段顺序和值;SemVer 必须同时通过 3.x 约束和
标准 SemVer 校验。legacy 根 `package.json` 的 2.x version 明确不参与 QingLong 3 release identity。
发布候选、容器/部署审计和物理 Edge 证据不再各自保存一份 3.0 常量,而是读取同一 authority。D-333 candidate
contract 还会携带 identity schema 与 canonical SHA-256,使发布证明能发现 authority 被事后替换。
### 2. CI 对完整版本表面执行失败关闭审计
`audit:release-version:ql3` 必须验证:
- 18 个 workspace version 与 Node engine
- 四组容器 build/runtime manifest、lock、Dockerfile Node base 和 OCI version label
- Kubernetes Cluster/Worker 与 Console 部署材料中的 QingLong 3 image/source tag
- legacy 根仍为不同的 2.x version,且没有被纳入迁移集合。
审计只读取源码文件,具有 4 MiB 单文件、512 个受管文件和 canonical path/symlink 上限,不启动 listener、timer、
数据库或容器。共享 CI 与 image-release 静态审计均必须证明该 gate 存在,不能只依赖实际发布时才发现漂移。
### 3. 版本升级使用 review-first 的 `plan → apply` 两阶段协议
`ql3-version-transition.cjs` 只接受三个封闭模式:
1. `--mode=audit`:审计当前 identity
2. `--mode=plan --from=<current> --to=<newer> --output=<absolute>`:生成 no-replace `0600` plan
3. `--mode=apply --plan=<absolute> --report=<absolute>`:应用已审阅 plan 并生成 no-replace `0600` report。
目标必须是严格单调递增的 exact QingLong 3 SemVer;降级、相等版本、build metadata 和非 canonical SemVer 均拒绝。
plan 精确列出每个 path、mode、替换次数、before/after bytes 与 SHA-256,并对 unsigned canonical 内容形成自身 digest。
当前 `3.0.0-alpha.0 → 3.0.0-alpha.1` 计划覆盖 65 个文件、83 处替换,根 2.x package 不在集合中。
### 4. apply 必须先全量预检,再允许逐文件收敛
apply 在第一次写入前验证 plan 自身、legacy 版本、完整文件集合,以及每个受管文件的 mode 和 before/after digest。
任何第三种状态都使整次操作在无源码 mutation 时失败。通过预检后,每个 source 状态文件先写同目录确定性临时文件、
`fsync`,再 atomic rename;已经处于 target 状态的文件被计入 recovery,而不是报错。因而进程在部分 rename 后中断时,
原 plan 可原样重放直至全部 target,成功后再运行完整 identity audit。report 区分 changed/already-current,并以 canonical
SHA-256 绑定 plan 和结果。
该协议提供进程中断后的幂等恢复,不宣称跨 65 个文件的单事务原子性,也不替代 Git review/commit。机器断电时的目录项
持久性由文件系统和 Git 工作区恢复承担;apply 不自动 commit、tag、push 或触发 release。
## 资源与权限边界
- 不新增 workspace package、生产 dependency、schema、migration、SQL、role、Pool、Pod 或容器;
- 所有版本命令是维护者显式启动的短生命周期 Node 进程,Edge/Standalone/Cluster 运行时零常驻开销;
- plan/report 必须写入 canonical absolute、尚不存在的路径,拒绝 symlink 与覆盖;
- 工具只修改 plan 中经 before digest 证明的仓库文件,不触碰 legacy 根 version
- 版本迁移完成后仍须经过完整回归、GitNexus `detect-changes` 和人工阶段提交。
## 失败与恢复
- audit 漂移:先修复 authority 或受管表面,不在发布 workflow 内临时覆盖;
- plan 后源码漂移:废弃旧 plan,重新 audit/plan/review
- apply 部分完成:保留同一 plan,使用新 report path 原样重放;
- report path 已存在:选择新 path,不覆盖旧证据;
- 非 3.x、降级或非法 SemVer:拒绝迁移,另行走兼容/回滚决策;
- Git review 发现非预期文件:不提交,修复受管集合或计划生成器后重新执行。
## 被拒绝的替代方案
### 让根 2.x `package.json` 成为 3.0 版本源
拒绝。该文件仍服务 legacy 产品与现有构建,强行改成 3.x 会把兼容线和新架构发布线混为一体。
### 在 release workflow 内直接 `sed` 全仓版本
拒绝。它没有可审阅的精确文件集合、before digest、全量预检或部分失败恢复,还会让 tag 构建修改 checkout。
### 为每个 package 使用独立版本
拒绝。3.0 当前发布的是同一产品候选和闭合镜像集合;独立版本会放大部署 compatibility matrix。若未来确需独立发布,
应以新的 package/release RFC 显式改变 authority,而不是允许静默漂移。
## 验证
- 版本 identity/audit/plan/apply/replay/partial recovery/no-mutation preflight/CLI 负向门已实现;
- release candidate、Cluster/Local image、OCI、部署、CloudNativePG、物理 Edge 与外部恢复定向回归 177/177;
- backend 1,254 pass/2 条件 skip/0 fail18-package clean build/test 退出 0package boundary 保持 18 个 package、
`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 modules
application+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
- 格式与 `git diff --check` 已通过;GitNexus 索引与 `detect-changes` 在阶段提交前最终刷新;
- 本 Gate 不修改数据库或 HA 拓扑,PostgreSQL physical HA 复用 D-331/D-333 的 18.6 arm64 142/142、timeline `1→2`
基线;若完整回归发现数据库/部署契约漂移,则必须重新运行 PostgreSQL HA 门而不能复用。