mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-23 03:18:09 +08:00
feat(ql3): establish 3.0 incubation baseline
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
# ADR-0195:AI-excluded 本机 Application 候选镜像
|
||||
|
||||
- 状态:Accepted(候选镜像 contract、arm64 build 与 fresh live gate 已实现)
|
||||
- 日期:2026-07-29
|
||||
- 关联 RFC:QL-RFC-0001 D-42、D-156、D-168、D-175、D-183、D-184、
|
||||
D-185
|
||||
- 关联 ADR:ADR-0042、ADR-0088、ADR-0167、ADR-0178、ADR-0185、
|
||||
ADR-0193、ADR-0194、ADR-0196
|
||||
|
||||
## 背景
|
||||
|
||||
D-184 的 Compose 描述符已经拒绝 mutable tag,但仓库此前只有 Cluster
|
||||
control/admin 镜像。直接把 workspace mount 到通用 Node image 可以用于测试,
|
||||
不能作为本机交付物:它包含开发依赖,缺少独立 production lock,也无法证明 AI
|
||||
没有进入默认 Edge/Standalone runtime。
|
||||
|
||||
为 Edge 与 Standalone 各建一个镜像也没有收益。两者使用相同 application 代码和
|
||||
生产依赖,仅由私有配置选择 SQLite journal、页预算和资源 envelope。复制镜像会
|
||||
产生两套 lock、SBOM、签名和漏洞响应。
|
||||
|
||||
## 决策
|
||||
|
||||
### 1. 一个镜像、两个本机 Profile、零新增 package
|
||||
|
||||
`deploy/containers/ql3-local-application` 是部署制品目录,不是 workspace
|
||||
package。镜像运行时精确包含:
|
||||
|
||||
- `runtime-core`;
|
||||
- `local-sqlite`、`local-admin`、`local-profile`、
|
||||
`local-adopted-profile`;
|
||||
- `local-command-file`、`local-secret`、`local-process`、
|
||||
`local-execution`、`local-application`;
|
||||
- `croner@7.0.8` 与 `semver@7.7.4`。
|
||||
|
||||
Edge/Standalone 继续由
|
||||
`qinglong/local-application-process@v2` 私有配置选择。镜像不包含
|
||||
`@qinglong/ai`;`ai.deployment` 只能为 D-184 生成的 `excluded`。后续 AI
|
||||
镜像若成立,必须作为独立 opt-in 制品和预算评审,不能修改默认镜像闭包。
|
||||
|
||||
### 2. Builder authority 不进入 runtime
|
||||
|
||||
Dockerfile 的两处 base 都直接固定为同一 Node 24.18.0 Bookworm Slim OCI index
|
||||
digest,不提供 `NODE_IMAGE` build argument。build dependency root 独立锁定
|
||||
TypeScript、Node/Semver types 与 Drizzle schema 编译类型;`ql3-ai` 只在
|
||||
workspace builder 中满足 application 的静态类型编译。
|
||||
|
||||
production dependency root 使用另一份 lock,只安装 `croner` 与 `semver`。
|
||||
最终 stage 从 builder 仅复制上述十个内部 package 的 `package.json` 与 `dist`;
|
||||
删除 npm 自动生成但 entrypoint 不需要的 `.bin` 链接,以及 TypeScript
|
||||
`.js.map`/`.d.ts.map` 调试映射;不复制 AI、Drizzle、TypeScript、cache、源码或
|
||||
开发类型。所有 `npm ci` 都禁用 lifecycle scripts。
|
||||
|
||||
### 3. 镜像身份与运行 envelope
|
||||
|
||||
镜像默认:
|
||||
|
||||
- `USER 65532:65532`;
|
||||
- `NODE_ENV=production`;
|
||||
- 唯一 entrypoint 为 `ql3-local-application`;
|
||||
- 不声明端口或 health listener;
|
||||
- 标记 `edge,standalone` 与 `ai=excluded`。
|
||||
|
||||
镜像自身不内置可写数据层。D-184 Compose 描述符必须继续固定:
|
||||
|
||||
- 由 host deployment owner 覆盖 numeric UID:GID;
|
||||
- read-only root filesystem;
|
||||
- `network_mode: none`;
|
||||
- drop all capabilities 与 `no-new-privileges`;
|
||||
- 唯一 `/var/lib/qinglong3` bind;
|
||||
- 16 MiB noexec tmpfs;
|
||||
- Edge 128 MiB/64 PID,Standalone 256 MiB/256 PID。
|
||||
|
||||
默认 numeric user 是无 Compose 覆盖时的最小权限兜底,不代表它能读取任意 host
|
||||
volume。
|
||||
|
||||
### 4. 候选证明与 release 证明分开
|
||||
|
||||
静态审计复核 base digest、两份 manifest/lock、build/runtime package 闭包、
|
||||
非必要文件删除、禁用 install scripts、默认 user、entrypoint 与 labels,并以
|
||||
mutation fixture 拒绝 mutable base、AI runtime copy、额外 production
|
||||
dependency、非必要文件回归和 lock 漂移。
|
||||
|
||||
真实 live contract 使用 D-184 prepare 分别创建 fresh Edge 与 Standalone
|
||||
volume,再在 read-only、network-none 容器中以各自 128 MiB/64 PID 与
|
||||
256 MiB/256 PID envelope 启动候选镜像。只有观察到 `active`、由
|
||||
`docker stop` 触发 `SIGTERM`、`stopped`、exit 0,并在退出后取得 SQLite
|
||||
`integrity_check=ok` 才通过。
|
||||
|
||||
CI 在原生 amd64 与 arm64 runner 重复 build、identity、CycloneDX inventory、
|
||||
`--help` 和 fresh live contract。ADR-0196 又把本机 profile 接入共享 attested
|
||||
OCI 与 release matrix;当前本机 arm64 成功仍不能替代尚未执行的远端双架构
|
||||
结果。
|
||||
|
||||
本 ADR 不接受以下 release 声明:
|
||||
|
||||
- 本地 tag 或 Docker image ID 是可分发 digest;
|
||||
- 单架构镜像代表双架构 OCI manifest;
|
||||
- lock 文件代表 SBOM;
|
||||
- Dockerfile 存在代表 provenance/signature;
|
||||
- 128 MiB Docker 门代表固定物理路由器的闪存、冷启动或断电证据。
|
||||
|
||||
## 当前证据
|
||||
|
||||
- 静态 contract:`findings=[]`;
|
||||
- mutation audit:6/6(含非必要文件与双 Profile/双架构 CI contract);
|
||||
- runtime inventory:10 个内部 package、2 个外部 package、AI absent,
|
||||
611/640 files、4,897,102/5,242,880 bytes、无 symlink/special file;
|
||||
- 本机镜像:Linux arm64、默认 `65532:65532`;
|
||||
- uncompressed image:251,932,346 bytes;
|
||||
- Edge live:128 MiB、0.5 CPU、64 PID、network none、read-only root;
|
||||
- Standalone live:256 MiB、0.5 CPU、256 PID、同一镜像与隔离边界;
|
||||
- 两个 application:各 19 个低敏事件,active 后 SIGTERM graceful stop;
|
||||
- SQLite:`integrity_check=ok`。
|
||||
|
||||
## 后续发布门
|
||||
|
||||
- 原生 amd64/arm64 CI 的实际成功记录;
|
||||
- ADR-0196 已实现但尚未取得成功记录的双架构 OCI index、逐平台 digest、
|
||||
CycloneDX/SPDX、provenance、keyless signature 与远端 registry 回读;
|
||||
- npm high/critical 与 SPDX license policy 已实现;base/OS vulnerability
|
||||
scanner 仍待完成;
|
||||
- 固定低配路由器的存储占用、冷启动、idle RSS、断电、ENOSPC/EROFS;
|
||||
- image upgrade/rollback 与 D-184 service activation controller。
|
||||
Reference in New Issue
Block a user