7.9 KiB
ADR-0263:显式 Cluster AI 组合与 Provider Credential Authority
- 状态:Accepted
- 日期:2026-08-02
- 关联:RFC D-08、D-12、D-85、D-124、D-156、D-159、D-244;ADR-0167、ADR-0169、ADR-0261、ADR-0262
背景
ADR-0169 已定义 Project-bound Provider credential、可清零 Secret material 和 audit-before-network,但当时还没有 Cluster 产品组合:binding 与 audit 没有 PostgreSQL authority,Secret material 没有可部署的 Cluster adapter,默认 Cluster 镜像也不能安全地 选择性包含 AI。
QingLong 3.0 同时服务低配路由设备和多副本 Cluster,因此不能通过以下方式补齐能力:
- 让默认 control image、Edge 或 Standalone 常驻安装/加载 AI;
- 为 binding、Secret adapter、composition 或 CLI 各拆一个单文件 workspace package;
- 让常驻 control 持有 Kubernetes API、Secret list/watch 或 credential mutation 权限;
- 把静态环境变量 token、ConfigMap 明文或进程内 cache 当作 credential authority;
- 只发布一个内容随构建参数变化、却共享同一镜像身份的 Cluster Control artifact。
决策
1. Credential catalog 与 audit 使用 append-only PostgreSQL authority
在既有 @qinglong/ai 包内新增显式 catalog/storage subpath,不新增 workspace package。
pg-9012-ai-model-provider-credential-catalog 在 ql3_ai schema 追加:
- immutable binding revision;
- generation/CAS 驱动的
bind|revoketransition; - content-free credential use audit。
runtime 只取得 current binding read 与 audit append;binding mutation 只属于既有
ql3_ai_maintenance authority。exact mutation 可重放,generation、command 或 binding
identity 漂移必须冲突。audit 只保存 Project、Provider、request、operation、binding
revision/digest 和数据库时间,不保存 SecretRef、token、header、Prompt 或输出。
2. Cluster Secret material 使用只读 projected-file adapter
首个 Cluster material adapter 接受一个部署注入的绝对只读目录。文件名是 canonical SecretRef 的 lowercase SHA-256;每次调用重新解析并读取一个有界 regular file:
- 允许 Kubernetes atomic-writer symlink,但最终文件必须仍位于受信 root 内;
- 拒绝可写、可执行、other-readable、hard-link、路径/identity/size 漂移;
- material 以 owned bytes 返回并由 authorization lease 清零;
- 不使用 Kubernetes client、ServiceAccount token、list/watch、cache、timer 或后台进程。
该 adapter 可以消费 Kubernetes Secret、CSI 或 Secret operator projection,但不把这些 projection 冒充最终 KMS/HSM。轮换由外部 authority 原子替换 projection,下一次调用自然 读取新 material。
3. Cluster AI 必须是显式 composition root
AI 产品组合留在 @qinglong/cluster-control/ai-production,复用既有认证、Project Policy、
route registry、生命周期和 PostgreSQL runtime contract。只有独立 AI entrypoint 解析
QL3_CLUSTER_AI_ENABLED=true 及 AI 配置,并按以下顺序 fail closed:
- 校验 projected Secret root 与可选 Prompt output keyring;
- 建立独立、有上限的 PostgreSQL runtime pool;
- 装配 credential reader/audit、Secret material 与 projected Provider authority;
- 执行有界 Prompt recovery;
- 将 Prompt execution capability 注入既有产品 route;
- 再启动 Cluster Control,并在任一侧不可用时统一有界停止。
默认并发为 4、recovery page 为 32、AI 数据库连接为 4,且都有硬上限。该增量只开放 已经受审的 Prompt execution;Prompt output read、credential management 和通用裸 model gateway route 仍保持关闭。
4. 默认与 AI 镜像是两个独立供应链 artifact
同一 Dockerfile 提供两个显式 target:
runtime/qinglong3-cluster-control:只含 runtime-core、cluster-postgres、 cluster-control,使用干净输出目录编译并断言不存在 AI package、AI composition 和 AI CLI;runtime-ai/qinglong3-cluster-control-ai:额外包含@qinglong/ai和独立 AI CLI。
CI、OCI layout、SBOM、OS vulnerability scan、签名/证明和 release matrix 均把
control-ai 作为第四个独立 artifact,与 control、admin、local 分别 pin digest。不能用
同一 tag 的隐藏 build arg 改变依赖闭包。
5. Kubernetes Cluster AI 是 opt-in component
默认 ql3-cluster base 保持 AI-free。components/cluster-ai 只在显式 overlay 中:
- 将 control image 替换为独立 AI image;
- 注入 canonical Provider authority ConfigMap;
- 以
0440只读 Secret volume 提供 digest-named material; - 保持
automountServiceAccountToken: false,不增加 Kubernetes RBAC/API egress; - 要求私有 overlay 独立 pin AI image digest。
6. Package 边界不因该能力继续细拆
workspace 保持 19 个 package。catalog、repository、projection adapter、composition 与 CLI
分别进入已经承担对应依赖/权限/部署责任的 ql3-ai 或 ql3-cluster-control subpath。
源码文件数量只能触发复审,不能单独决定 package;新增 package 仍必须满足 RFC D-85 的
部署、权限、依赖闭包、多个 production consumer 或独立供应链责任门。
当前唯一单源 package @qinglong/local-command-file 有三个 production importer,并提供
共同的 POSIX private-file/TOCTOU 安全协议,因此暂时保留;如果 consumer 收敛为单一同包
入口,或不再形成共享安全边界,则必须回并为现有 subpath。
被否决方案
- 默认 control image 直接安装 AI:让禁用 AI 的节点承担依赖、漏洞与演进成本。
- 每个 AI adapter 一个 package:没有独立部署或权限收益,重复单文件包问题。
- 环境变量保存 Provider token:无法形成 Project-bound revision、轮换和 durable audit。
- 常驻 control 读取 Kubernetes Secret API:扩大 ServiceAccount、RBAC、网络和缓存边界。
- 一个镜像 tag 通过环境变量切换 AI:无法由 SBOM、签名和 digest 证明实际闭包。
- 把 projection 宣称为 KMS:它只解决 Pod 内只读 material delivery,不解决外部 key custody、wrapping、灾备或 lost-secret ceremony。
验证
@qinglong/cluster-control:175 项中 173 通过、2 条外部条件跳过、0 失败;@qinglong/ai:154 项中 151 通过、3 条外部 PostgreSQL 条件跳过、0 失败;- Cluster AI composition 独立测试 3/3;deployment audit 40/40;
- release/SBOM/OCI/OS vulnerability policy 合并测试 117/117;
- frozen lockfile install、Cluster dependency audit、deployment audit 和 release audit 全绿;
- 实际 Docker
runtime不含 AI package/CLI/composition,runtime-ai三者均存在且 AI CLI 可执行;实际control-aiinventory 为 47 components,其中 4 个 internal、43 个 external; - PostgreSQL 18.4 arm64 physical-streaming HA 完成
remote_apply、timeline 1→2、旧主 fencing、pg_rewind、双 fresh control;binding bind/revoke/rebind 与 content-free audit 在晋升后保持一致,总 gatepassed=true; - 所有
ql3-ha-*临时资源已清理,既有 evidence control-plane 未被修改; - workspace 仍为 19 个 package,dependency findings 为空。
后续门禁
- 为 binding bind/revoke、测试连接和 audit query 增加经过认证、Policy 与 quota 约束的 Cluster 管理 ceremony;常驻 runtime 不取得 mutation authority;
- 引入真正的 KMS/Vault/HSM custody adapter、首次 provision、active rotation、备份恢复与 lost-secret 人工流程;
- 在真实 Kubernetes API/CSI/Secret operator 上完成投影轮换、Pod rollout、网络隔离和 credential 丢失故障注入;
- 补齐真实 Provider 的计费、限流、超时和故障注入后,再评审更多 HTTP/MCP/UI route;
- 持续以镜像字节、文件数、loaded modules、RSS、连接数和冷启动验证低配与 Cluster 两端预算,不能用 package 数替代运行成本证据。