Files
qinglong/docs/adr/ADR-0454-target-instance-manual-primary-canary-ceremony.md
T

9.0 KiB
Raw Blame History

ADR-0454:目标实例 Manual Primary Canary 与显式回滚仪式

  • 状态:Accepted(仪式实现完成;首次真实用户目标实例执行仍待运维)
  • 日期:2026-08-19
  • 关联 RFCQL-RFC-0001 D-361、PR-4、PR-5
  • 关联 ADRADR-0002、ADR-0449、ADR-0450、ADR-0451、ADR-0453
  • AmendsADR-0453 的首次目标实例 canary 操作缺口
  • Amended byADR-0455 的 Profile-bounded durable runtime activation receipt

上下文

ADR-0453 已提供 process-epoch capture authority、clean-shutdown evidence、closed terminal audit、compiled-backend rollback/resource report、Primary gate bundle 与 rollout manifest v2 loader,但维护者仍需手工拼接多个命令、文件名、时间窗口和摘要。只提供底层 gate 会留下四类运维缺口:

  1. canary 开始前没有不可变计划绑定 Profile、精确样本数和当时的 live rollout 基线;
  2. terminal/resource/gate 输出容易经 shell 重定向得到宽权限、部分写入或互相不属于同一 session 的文件;
  3. qualification 与写入 live manifest 之间没有显式人工边界,配置选择又容易被误报成“当前进程已经激活”;
  4. rollback 没有绑定被替换 manifest 的摘要,也没有 crash-replay intent/completion 链。

Edge 可能是 128 MiB 路由设备,不能为 canary 新增 daemon、watcher、遥测栈或第二数据库;Standalone 可能运行在集群节点上,但本仪式仍只裁决本机 edge|standalone Profile,不得借宿主机形态伪装成 cluster-control|worker Primary 证据。

决策

  1. 新增 qinglong/manual-primary-canary-plan@v1prepare 只接受受控 session ID、edge|standalone、Edge 精确 8 条或 Standalone 32128 条中由 operator 选定的精确 admission 数;它记录当前 qinglong3-rollout.json 为 absent 或 disabled+SHA-256。已有 enabled manifest 时拒绝准备。
  2. plan 固定派生全部 basename,不接受调用方提供输出路径。config root 必须是当前 UID 拥有、非 symlink、group/world 不可写的真实目录;所有 artifact 均以 0600、同目录临时 inode、file fsync、hard-link no-replace 与 directory fsync 发布。重复调用只接受逐字节相同文件。
  3. prepare 只输出三项部署环境:实际 Profile、QL3_SHADOW_ORIGINS=manual 与唯一 capture basename;它不写 enabled manifest、不启动任务、不重启服务。 operator 必须在隔离窗口中通过既有 Legacy 产品入口精确执行计划数量的 manual admission,并干净关闭同一 worker;任何额外 manual execution 都使样本不相等。
  4. observe 只有在 capture qualified、单一 manual origin、计数精确且窗口结束至少五分钟后,才以固定参数启动 Node 24 terminal auditor。数据库必须为非 symlink、 group/world 不可写的普通文件;auditor 只读打开 SQLite。调用方不能注入 origin、window、settling、child script 或 shell。
  5. resource 用固定 full + require-compiled + 8 samples 启动 ADR-0451 runner。它使用自身临时 SQLite,不接触生产数据库;低配设备必须在应用停止后运行,不能把 与常驻 workload 争用内存后的失败解释为产品回归。
  6. qualify 复用 ADR-0453 gate,但额外绑定 plan 文件摘要、三份 source 的原始文件摘要、三份 canonical JSON 摘要、精确 admission target 与 gate 文件摘要。 现有 gate、partial qualification 或 response loss 只能通过原文件重放;source 在 qualification 后被替换时,mutating CLI 与独立 auditor 都失败关闭。
  7. approve 是唯一写 live manifest 的操作。它要求显式 approvedBy,审批最短一分钟、最长 24 小时;先复核 plan 时的 absent/disabled 基线,disabled 基线先 no-replace 归档,再以同目录 fsync 临时文件和最终摘要复核发布 schema v2 manifest。结果状态固定为 activation_approved/primary_selected,并明确 requiresRestart=trueruntimeActivationObserved=false;配置选择不得冒充 HTTP worker 已完成 startup reconciliation 和 router activation。
  8. 应用重启后,实际运行态由 bootstrap 的 selected → reconciled → durable active receipt → activated 证明。ADR-0455 已让独立 auditor 复核 receipt 与 Linux boot/PID/start-time 联合身份,并新增 active 要求;off|rolled-back 同时要求不存在仍 current 的 runtime。非 Linux portable receipt 不能获得 current 结论。
  9. rollback 只接受四个固定 reason 与有界 operator。它先 no-replace 发布 intent,绑定当前 enabled manifest SHA-256 和目标 disabled SHA-256,再复核当前摘要并原子替换 live manifest,最后发布 completionintent 或 completion response loss 可用相同参数重放。disabled 已有效但不同于本 session 的目标时拒绝覆盖。
  10. 审批过期后,loader 对下一次 bootstrap 必须 fail-closed 为 off;状态/auditor 报 approvalExpired=truerolloutMode=off。无 watcher 的既有进程不会仅因磁盘 审批过期而自动卸载 router,故 off 审计会在 current receipt 仍存活时失败。operator 必须显式 rollback 并停止/重启应用;过期不能被当作自动续期、自动删除或已停止证明。

被拒绝的替代方案

常驻 watcher 自动检测 capture 并启用 Primary

拒绝。它把一次性证据变成后台控制面,增加路由设备 timer/文件监控成本,并绕过独立人工审批。

Canary CLI 自动触发八个用户任务

拒绝。工具没有用户会话、Task Policy、脚本内容或副作用 authoritysynthetic spawn 不能证明真实 Legacy 产品入口的 admission capture。

用 enabled manifest 存在表示 Primary 已运行

拒绝。manifest 只在下次 bootstrap 被读取;进程可能尚未重启、startup reconciliation 可能失败或审批已经过期。selection 与 runtime activation 必须分开陈述。

原地覆盖证据和 rollout 文件以方便重试

拒绝。覆盖会丢失冲突和 crash window。证据采用 no-replacelive rollout 只在摘要复核后原子替换,并由 previous/intent/completion 文件保留恢复链。

资源、安全与部署影响

  • 正常 QingLong runtime 不新增 import、timer、watcher、listener、数据库连接、schema、migration、package 或生产依赖。全部动作由 operator 一次性调用。
  • plan/qualification/selection/rollback 报告不包含数据库路径、命令、Task、Run、Cron、PID、日志、用户输出、错误正文或 Secretstdout 只返回 stage、Profile、样本数和布尔状态。
  • observe 只读生产 SQLiteresource 只使用 runner 的临时 SQLite。Edge 应在应用停止后运行 resourceStandalone 也不得与同机生产 canary 并发争用。
  • POSIX owner 是本机信任根。摘要复核能防止误覆盖和非协作漂移,但不能防御同一 UID 在最后复核与 rename 之间的恶意并发;共享 config root 或远程 delegation 需要 另行引入签名/锁服务,不得把本仪式描述成多写者共识。
  • 本仪式不适用于 cluster-control|worker,也不证明物理路由、flash wear、断电、跨主机签名或真实生产任务安全。

验证

  • domain/CLI 聚焦矩阵覆盖 Edge/Standalone 样本预算、exact shape、短期审批、prepare 重放、unsafe root、disabled baseline drift、source replacement、partial qualification、selection receipt response loss、审批过期、rollback intent/completion response loss及独立审计。
  • 真实 compiled backend 已通过 D361 prepare → resourceEdge plan 保持 automatic activation falseresource 阶段产生 qualified full rollback evidence enabled/off 进程 peak RSS 分别为 109,953,024 / 102,383,616 bytes,真实 Legacy child 均 exit 0Shadow Run delta 从 1 收敛为 0。
  • 阶段门已重跑:聚焦 24/24build:back、完整 backend 1,481 pass / 0 fail / 2 conditional skip、18-package clean build/test、四项架构审计与 14/14 artifact audit 全部通过;产物字节与 D-360 一致。隔离 frozen-lockfile Linux arm64 Docker 的 128 MiB router/256 MiB Edge release peak 分别为 81,887,232 / 148,840,448 bytesmemory.events max/oom/oom_kill 增量均为 0。
  • D361 不修改 PostgreSQL schema/migration、依赖树或 Kubernetes 拓扑,因此不重跑 PostgreSQL HA;任何仓库 synthetic fixture、compiled resource child 或 Docker arm64 结果都不沿用、也不冒充尚未执行的真实目标实例 manual capture/activation。

后续

维护者仍需在一台真实目标 Edge 或 Standalone 实例执行 Manual Primary Canary 操作手册,并保留 capture、terminal、resource、 gate、qualification、selection、bootstrap activated audit 与 rollback completion。其他 origin 必须建立自己的 admission authority 与 gate;固定物理路由/flash/断电、 多写者 config authority 仍是独立后续工作;运行态 durable activation receipt 已由 ADR-0455 补齐,但首次真实目标实例执行仍待运维。