6.7 KiB
ADR-0473:Service Manager Legacy Rollback Commit
- 状态:Accepted
- 日期:2026-08-20
- 关联 RFC:QL-RFC-0001 D-64、D-274、D-275、D-379、D-380
- 关联 ADR:ADR-0314、ADR-0315、ADR-0362、ADR-0363、ADR-0472
背景
ADR-0472 已使 systemd/OpenRC adopted cutover 能在 Owner authority 内把安全候选推进到
rollback_prepared,但它刻意不授予 root mutation,也不能证明旧服务已经重新运行。若 root 直接把
rollback_prepared 当作启动授权,Owner 的数据判断、init mutation 与最终实例状态会混成一个不可审计步骤;若在响应丢失后
再次执行 start,又可能越过崩溃窗口重复副作用。
本阶段还必须同时适配低配路由设备和集群节点:回滚不能引入新 daemon、watcher、连接池或部署对象,也不能为了源码目录变密就 制造单文件 workspace package。编辑前 GitNexus 对 preparation、service bridge、deployment CLI、live actor 与 Docker gate 涉及的既有符号完成 upstream impact;均为 LOW,最多 3 个直接/累计上游、0 条已识别 execution flow。
决策
1. Owner 授权与 root mutation 分离
Owner 只能通过私有命令文件执行:
ql3-local-deploy service-legacy-rollback-authorize --command-file <private.json>
授权必须重新验证当前 instance head、rollback_prepared record、Application 原始字节摘要、legacy-silence commitment 原始字节
摘要、目标 descriptor 摘要和 manager kind,并 no-replace 发布 legacy_restart_requested。preparation 不是 root 授权,root bridge
只接受这一种当前 head 和 exact authorization digest。
2. root bridge 只允许固定服务和固定 argv
root bridge 的唯一新操作是 local.deployment.service-manager.legacy-rollback.execute。它只允许:
- legacy 服务名
qinglong与 target 服务名qinglong3; - systemd descriptor
/etc/systemd/system/qinglong.service或 OpenRC descriptor/etc/init.d/qinglong; - 受审的固定
systemctl或rc-serviceargv,不接受 shell、任意 executable、服务名或路径; - 启动前同时证明 legacy inactive、target inactive,并复验 Owner application/commitment/authorization 与 descriptor 原始摘要。
bridge 在任何 start 前先 no-replace 写 durable root barrier。barrier 之后的所有重放都只能 inspect,永不再次 start。
3. 响应丢失按双服务观察收敛
若 manager 实际完成 start 但响应丢失,重放读取 barrier 并检查两个固定服务:只有 legacy active、target inactive,且进程身份与
manager 观察一致时,root outcome 才是 proved running。若 barrier 已存在但无法证明上述事实,结果固定为 unproved,交给 Owner
终结为 manual_required;不得猜测、删除 barrier、替换 descriptor 或自动启动 target。
root outcome 先于 Owner outcome 持久化,因此 root 成功后 Owner 进程崩溃仍可用相同输入恢复,不重复 init mutation。
4. Owner 是实例终态唯一写者
Owner 通过:
ql3-local-deploy service-legacy-rollback-consume --command-file <private.json>
消费 exact root outcome。只有 root 证明 legacy running、target stopped,且 authorization/head/digest 全部一致时,才 CAS 到
legacy_running;任一不确定、漂移或双服务冲突都进入 manual_required。exact replay 返回同一 completion,不覆盖已存在的不同
Owner outcome。
legacy_running 只证明 init/process running 与 target stopped,不代表 QingLong 2.x HTTP、任务调度、数据库或业务健康。
5. 保持部署与 package 边界
实现留在现有 @qinglong/local-owner-cli。为避免 service-manager/ 继续平铺超过直接源码文件阈值,回滚子域内聚为:
service-manager/legacy-rollback/
preparation.ts
contract.ts
consumer.ts
bridge.ts
不新增 workspace package、production dependency、binary、daemon、timer、watcher、socket、数据库连接、systemd/OpenRC unit 或 Kubernetes workload。root bridge 仍是显式短生命周期命令。
被否决方案
- 把
rollback_prepared直接交给 root:准备事实不是启动授权,拒绝。 - barrier 重放再次调用 start:响应丢失会重复副作用,拒绝。
- root 直接写 instance head:会混淆 OS mutation 与 Owner 状态 authority,拒绝。
- 只检查 legacy active:target 同时运行时会制造双主,拒绝。
- 把
legacy_running宣称为业务健康:init/process 观察不足以证明 2.x readiness,拒绝。 - 新建 rollback package 或 daemon:没有独立交付/依赖/生命周期依据,并放大路由设备闭包,拒绝。
验收证据
- 聚焦 Owner/contract 门
16/16;Local Owner 全量181 total / 176 pass / 5 conditional skip / 0 fail。 - 18-package clean build/逐包测试单次退出 0;backend 全量
1,523 total / 1,521 pass / 2 conditional skip / 0 fail。 - package boundary、Service Bridge import、Edge import、Cluster dependency、Cluster/Worker deployment、Console 与 Console
distribution 八项审计全部 compatible/passed。workspace 仍为 18 packages、
singleSourcePackages=[]、shallowSourcePackages=[];Local Owner 为111 source / 110 nested / 1 root binary entry。 - 14 档 Local artifact audit 全部 compatible。基础 Edge/Standalone 为
2,598,669 / 2,598,747bytes、316 files、 57 loaded modules;Adopted 为2,817,964 / 2,818,087bytes、58 loaded modules;Application+AI 为4,501,822 / 4,501,954bytes;MCP 为7,324,601 / 7,324,709bytes。回滚 authority 未进入基础运行闭包。 - systemd live actor 已覆盖 root/non-root 成功、真实 manager start、响应丢失后的 inspect-only 收敛、Owner
legacy_running消费与 exact replay;root barrier-crash 场景证明没有第二次 start,legacy/target 均保持 inactive,Owner 收敛为manual_required。 - OpenRC actor 因本机缺少 Alpine/OpenRC 基础镜像,拉取
node:24-alpine时 credential helper 挂起而未执行;因此本 ADR 不宣称 systemd/OpenRC 全组合门闭合。临时 systemd 容器、测试镜像和临时 tag 均已清理。 - 本阶段不修改 SQL、migration、PostgreSQL repository/role/Pool 或 HA 语义,因此不重新生成 PostgreSQL HA 证据。
未完成
- OpenRC root/non-root success 与 root barrier-crash live actor;
legacy_running后有界、可重放的 2.x readiness/health proof;- 固定物理 Edge 的完整 prepare/authorize/execute/consume 回滚证据;
reconciliation_required的 export、冲突裁决与受审回灌。
本 ADR 关闭 service-manager 回滚的安全 commit 与进程级收敛,不代表 QingLong 3.0 升级/回退 Gate 已全部完成。