feat(ql3): establish 3.0 incubation baseline

This commit is contained in:
whyour
2026-08-12 00:25:26 +08:00
parent 4bf92dcfeb
commit c699c32461
2817 changed files with 779642 additions and 653 deletions
@@ -0,0 +1,204 @@
# ADR-0242:受批 Worker Credential 管理与一次性执行边界
- 状态:Proposed
- 日期:2026-08-01
- 关联 RFCQL-RFC-0001 D-23、D-58、D-175、D-207、D-224、D-225、D-226
- 关联 ADRADR-0141、ADR-0142、ADR-0185、ADR-0217、ADR-0234、ADR-0240、ADR-0241
- 承接:ADR-0241 尚未完成的强 User、双人批准与 TokenRequest session 产品组合
## 背景
ADR-0241 已把 Kubernetes delivery capability 收敛为 callback-scoped、内存中的一次性
TokenRequest session,但它只解决“已获得执行授权后如何安全签发和销毁 token”。如果产品入口
直接让调用者构造 delivery 参数,仍会缺少三个关键事实:谁申请、批准的精确目标是什么、执行时
是否仍与批准内容和 Project authority 一致。
该问题也不能通过新增一组细粒度 workspace package 或常驻 credential controller 解决。
QingLong 同时面向低配路由设备与集群节点:前者不应安装 PostgreSQL/Kubernetes SDK、连接池和
后台轮换循环;后者则必须把可被网络调用的管理 authority 与持有 Kubernetes delivery capability
的执行 authority 分开。
## 决策
### 1. 产品链固定为四段持久事实
Cluster Worker credential 的 `issue|rotate` 固定执行:
1. 强 User principal 在 Authority Project 内通过 `worker.manage`,创建最长 15 分钟、不可变且
不含 token/Secret/kubeconfig 的 management plan
2. 同一申请者基于 plan digest 发起 `high` risk、`separation_of_duty` ApprovalRequest
3. 另一名具有 `approval.decide` 的强 User 对 exact action/plan/preview digest 作出决定;
4. caller-driven executor 重新读取 plan/approval/Project fence,原子 consume approval 并取得
durable dispatch 后,才进入一次性 TokenRequest session 和可恢复 delivery issuer。
approval、dispatch、credential mutation 与 delivery 都使用稳定 identity 和 exact replay。token
只存在于 session callback 内,不能进入 plan、approval、PostgreSQL、结果、日志或审计事件。
### 2. Manager 与 Executor 使用不同数据库角色
`ql3_worker_credential_manager` 只读 Project/RoleBinding/schema facts,可创建 plan、
ApprovalRequest 和 Audit;它不得读写 credential、delivery、stage discard 或 dispatch。
`ql3_worker_credential_executor` 只读 plan 与 Project authority,可 consume ApprovalRequest、追加
dispatch/credential/mutation/delivery/stage-discard/Audit;它不能创建或改写 plan,也不能取得其他
runtime、Package 或 migration authority。两个角色都不是 superuser、owner、createdb、createrole、
replication 或 bypassrls;每个部署连接上限为 4,并只执行 approval policy fence function。
迁移 `pg-0047` 建立 immutable plan 与上述 grant`control-core` 推进到 v46`pg-0048` 只调整
credential lifetime check,使批准时刻早于实际创建时刻仍可执行,同时要求 expiry 晚于
`GREATEST(createdAt, notBefore)`,并推进到 v47`pg-0049` 把 durable execution receipt 的
SELECT/INSERT/UPDATE 仅授予 executor 并推进到 v48`pg-0050` 再建立使用数据库时钟、
exact replay receipt 的 manager quota bucket,把共享 identity keyset ledger 的 authority 严格扩展为
Plugin Package/Worker Credential 两值,并仅给 Worker manager 相应读写权限,推进到 v49。历史迁移
不原地改写。
共享 `approved_action_executions` 表的 dispatcher 必须把自身注册 handler 的 action types 下推到
repository 查询。没有匹配 handler 的 executor 不得领取、租约或 block 其他 authority 的动作。
### 3. 批准时间与执行时间必须分离
plan 固定批准的 `credentialNotBeforeAtMs``credentialExpiresAtMs`。执行因人工审批延迟时,
不得把 not-before 改成当前时间,否则批准摘要失效;也不得创建已经到期的 credential。执行端
要求当前时间仍早于 plan、dispatch 和 credential expiry,再按批准的原始时间签发。rotation
还必须确认 predecessor 是同一 Worker 当前有效 credential。
### 4. 不按源码文件拆 workspace package
本能力分别落在既有 package 的显式 subpath
- `runtime-core/worker-credential-management-plan`Profile-neutral plan contract
- `cluster-postgres/worker-credential-manager`manager-only repository/readiness
- `cluster-postgres/worker-credential-executor`executor-only repository/readiness
- `cluster-admin/worker-credential-management`:强 User 管理 facade
- `cluster-admin/worker-credential-management-executor`:一次性执行组合。
它们不是新的发布、部署或 dependency root,因此不建立单文件 package。只有出现独立制品、独立
第三方重依赖、必须从常驻闭包排除的 authority,或三个以上 package 需要稳定依赖反转时,才允许
重新评审 package 边界。
### 5. Edge/Standalone 与 Cluster 不共担部署成本
Edge/Standalone 不导入上述 PostgreSQL/Kubernetes 管理 subpath,不创建这两个角色、连接池、
TokenRequest client、timer 或常驻进程;本机身份和 credential ceremony 继续由短生命周期 Owner
CLI 与 SQLite authority 完成。路由设备运行 Worker 时仍使用同一受预算约束的 Worker runtime
但 Cluster 管理 SDK 不进入其制品闭包。
Cluster 可提供独立认证后的 manager transport,但 executor 必须保持一次一命令/一次 Job 的
caller-driven 生命周期:打开至多一个受限数据库资源,consume durable approval,创建一次
TokenRequest session,执行或重放 delivery,然后销毁 Kubernetes client 并关闭数据库。不得把
executor 变为常驻 controller、轮换 timer、watcher、leader election 或 sidecar。
## 不采用方案
### 把 manager 与 executor 合成一个 admin role/process
拒绝。网络管理入口一旦被利用,就会同时获得 approval 创建和 Kubernetes delivery capability
separation-of-duty 只剩应用层约定,无法由数据库 grant 和部署凭据证明。
### 每个 plan/repository/service 新建一个 package
拒绝。这些模块没有独立部署、发布或第三方依赖边界,会增加 importer、lock、SBOM、build 和升级
成本,却不能进一步缩小运行时 authority;显式 subpath 已能提供需要的可见性和审计门。
### 常驻 controller 自动签发和轮换
拒绝。它会长期持有 issuer、delivery 与数据库 authority,并增加 timer、重试、leader 和连接
生命周期;低配设备不需要这套成本,Cluster 的低频高风险操作也更适合显式受批执行。
### 批准后把 not-before 重写为执行时间
拒绝。它会改变已批准 plan 的语义与 digest;若不重写 digest 就是越权,若重写 digest 则必须
重新审批。正确做法是保留批准时间并验证执行时尚未过期。
## 影响
- CloudNativePG 数据库角色由六个增至八个,新增两个离散 credential Secret 示例;
- workspace package 数不增加,Edge/Standalone production closure 不增加 Cluster 依赖;
- Cluster Admin 在同一 package 内增加 management transport/HTTP/client/process 显式 subpath、
manager/client/executor CLI binary、opt-in 双副本 Kubernetes Deployment 与 caller-driven Job
不增加 workspace package。
manager process 使用独立 Worker manager Pool、durable quota 与 authority-scoped identity ledger
不取得 executor、Kubernetes API、Secret 或 pepper authorityexecutor Job 只取得显式 600 秒
issuer token、exact delivery ServiceAccount 的 TokenRequest 和 executor PostgreSQL role
- 运维工作站通过独立 opt-in management client Job 发起单条命令;该 Job 无 RBAC/API token
只把不可变 request、短期强 User assertion 与受审 CA 分离投影,预检仅重试 TLS 1.3
`/readyz`,生产 client 主进程不自动重试业务请求;
- executor 在 approval consume 后失败时保留 durable dispatch,后续以同一 identity 恢复,不重新
请求人工批准,也不重签不同语义的计划;
- executor 对 execution baseline 执行 claim→start→complete;成功回执精确绑定 delivery identity 与
publication digest,重放只读 durable delivery,不再次进入 TokenRequest session
- plan 与 PostgreSQL 只持目标、摘要、时间和低敏证据,不持 bearer token。
## 验证
当前实现证据:
1. manager/executor PostgreSQL readiness 正向与越权负向测试通过,两个 package entrypoint 的
capability 集合互斥;
2. management 的 plan/propose/decide/inspect happy path 已覆盖强 User、Project
`worker.manage`/`approval.decide`、双人决定、immutable exact replay 与配置收窄;
3. runtime/admin/delivery 已覆盖审批延迟后仍按原 not-before 创建、已过期拒绝与 delivery recovery
4. PostgreSQL migration/schema/manifest 全量测试通过,`pg-0047`/`pg-0048`/`pg-0049`/`pg-0050`
有独立 predecessor、capability 和 grant/constraint 契约;control-core 已到 v49
5. CloudNativePG deployment audit 已验证八角色和 Secret 映射;
6. 真实 K3s `v1.34.3+k3s1` + PostgreSQL 18 纵切面完成两次 plan、职责分离批准、consume、
TokenRequest、delivery 与 succeeded execution receipt;同一 execution 的精确重放没有再次签发 token;
7. PostgreSQL 18.4 arm64 physical HA 在 v49 上通过 `remote_apply`、timeline 1→2、旧主 fencing、
未确认分区提交排除、`pg_rewind` 只读同步重入、fresh control replicas 与全部领域 gate。
8. management transport 仅公开 plan/propose/decide/inspect,认证失败、弱 assurance、扩展 shape 与
内部 execute 均在管理 authority 前拒绝;响应只含 plan/approval 低敏摘要;
9. Worker HTTPS host 复用既有 TLS 1.3、认证前连接/peer/global shield、并发/超时/body/response
上限,但路径固定为 `/api/v3/worker-credentials/management`Plugin Package 路径在同一实例返回
404Worker/Plugin HTTP 11 项联合回归与原普通/Kubernetes tunnel client 15 项回归通过;
10. Worker client/CLI 复用 canonical 私有文件、CA/servername、TLS 1.3、无 redirect、单请求与
bounded response 实现,四类结果 exact-validate,附加 authentication ID、secret-bearing shape 或
内部 execute 结果失败关闭;本能力未新增 packageADR-0243 删除孤立 cutover 后当前为 19
11. manager durable quota 在 Project Policy 后、任何 plan/approval state read 前执行,四类 operation
使用数据库时钟、固定窗口与有界 receipt ledger;精确重放不重复计数,拒绝映射为 HTTP 429;
12. Worker manager process/CLI 已接入专用 role readiness、authority=`worker-credential-management`
identity ledger、quota、TLS 1.3 HTTP 与有序 drain/close;禁用态只读 enable 开关且零文件/数据库
副作用。新旧 manager 进程 14/14caller-driven executor process/CLI 已固定 exact command、私有
32-byte pepper、单连接 Pool、两次 issuer authorization confirmation、一次 TokenRequest session 与
失败保真销毁与低敏 CLI 输出,专项 7/7cluster-admin 全量 174 pass/1 条件 skip
13. opt-in Kubernetes base/CloudNativePG overlay 已完成双副本、PDB、required anti-affinity、零
ServiceAccount token、只读 TLS/identity/CA 投影、label-only ingress、DNS/PostgreSQL-only egress、
manager-only CNPG credential 与 fail-closed image digest;独立 executor base/CNPG operation 采用
caller-driven Job、`backoffLimit=0`、600 秒投影 issuer token、existing exact TokenRequest RoleBinding、
command/pepper/CA 分离只读投影、executor-only CNPG credential、无 ingress 与 DNS-only base egress
Kubernetes API 必须由私有 overlay 指定 exact CNI destination。独立 management client operation
固定 `backoffLimit=0`、零 token/RBAC、DNS + manager:8444-only egress、不可变三输入和独立
fail-closed digestdeployment audit 28/28 变异测试通过;
14. PostgreSQL 18.4 arm64 physical HA 在 v49 再次运行,八角色专用 readiness 在 promotion 前后均
通过;新增 Worker manager 双数据库实例矩阵以 16 个并发请求证明 8 admitted/8 limited、重放
零额外计数、autocommit response loss 精确收敛,并把 identity ledger 推进到 generation 3,证明
restart rollback、same-generation rewrite、implicit removal 拒绝与 COMMIT response loss 收敛。
`remote_apply`、timeline 1→2、fencing/partition/`pg_rewind`/只读同步重入和总 gate 均继续为 true;
该证据不冒充真实 Kubernetes Pod、HTTP listener 或外部 IdP 演练。
15. 真实 K3s `v1.34.3+k3s1` + PostgreSQL 18 门已用生产 `cluster-admin` 镜像运行第三次
caller-driven credential rotation:首次 Job 返回 `published``tokenRequestUsed=true`,第二个
独立 Job 精确重放相同 command 时返回 `existing``tokenRequestUsed=false`。两个 Job 均使用
`backoffLimit=0`、executor-only 单连接数据库凭据、无 automount token、600 秒投影 issuer token、
无 ingress 和精确 API Service/backend/PostgreSQL `/32` egress。最终 3 个 plan/consumed approval/
dispatch/succeeded execution/credential/published delivery、12 条安全审计、Recreate stop-before-start、
Bound PVC journal 与 identity generation rollout 全部收敛,总 gate 为 true。
16. 三节点 K3s + PostgreSQL 18 的独立 manager 门以两个 required anti-affinity Pod、生产
Worker management client 和 TLS 1.3 精确 Pod 寻址完成 8 admitted/8 limited;配额已满后的
跨 Pod exact replay 返回 `existing`,最终 plan/consumed/receipt 均为 8。identity projection
依次覆盖 generation 1、2 overlap、3 revokegeneration 2 rollback surge 以 exit 1 失败关闭且
两个旧 Pod 保持 Ready。停库后两个业务请求均为 503、Ready 均为 503、Live 均为 200;数据库
重启不允许旧实例原地解除 availability fence,只有 fresh rollout 的两个 Pod 返回 200。一次性
client Job 仅对没有远端响应的 transport failure 复用同一幂等命令做有界重试,不重试任何
HTTP 业务拒绝。该门同时发现并修复计划 repository 把 `plannedAtMs``expiresAtMs` 与派生 digest
错当为调用方语义、导致跨 Pod exact replay 500 的问题;不同 target/requester 仍冲突。facade
同时把无效计划和 semantic conflict 分别稳定映射为 HTTP 400/409,不再泄漏成 500。
17. 同一三节点 K3s 门现在直接加载仓库内 management client ServiceAccount、NetworkPolicy 与 Job
只把镜像替换为本次构建的生产 Admin image。固定 `qinglong3-system` DNS、TLS 1.3 `/readyz`
init、不可变 request/assertion/CA、零 projected token 条件下,init/main 均 exit 0client
`restartCount=0``worker-credential.inspect` Job Complete;报告新增
`gates.committedOneShotClientOperation=true` 且总 `passed=true`。该证据不依赖 kubelet 日志代理,
以 Kubernetes Job/Pod 终态证明执行,避免把管理响应复制到 termination message。
## 仍未完成
- 外部 OIDC/client certificate 双 User ceremony、撤销审计与真实生产 ingress;
- 多节点 Kubernetes API/CSI 故障矩阵,以及固定 x64/arm64 路由设备与集群节点资源报告。