mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-21 18:08:20 +08:00
feat(ql3): add explicit cluster observation console
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
|
||||
最新增量证据(2026-08-16):
|
||||
|
||||
- D-329/ADR-0421(已接受):同一 loopback-only Console/BFF 已扩展为 Cluster field ledger,固定提供 Copilot `inspect|output`、Run list/detail/events/steps、Task list/detail、Workflow list 与 Workflow Run list/detail/events/steps 共 13 个显式只读 operation;browser 仍不能提交 upstream URL/method/header/credential。服务端 exact contract 负责 ID/cursor/limit 校验和 path/query 生成,并复用既有 owner-private `ql3c_`、TLS 1.3、request-ID、2 MiB response 与低敏错误 transport;通用 Project read grammar 只接受审核过的 Run/Task/Workflow GET,拒绝 mutation、absolute URL 与 path traversal。UI 采用仅存内存的 evidence ledger,每次按钮只执行一次读取,分页只在 `hasMore|truncated` 携带 cursor 时由用户显式触发,没有自动 detail cascade、poller、WebSocket/SSE、retry、queue、cache 或后台 timer。实现继续留在 `@qinglong/cluster-admin`,workspace 维持 18 package,部署 credential 推荐只授予 `run.read|task.read|artifact.read`;不回接 2.x Web/session、不新增 Cluster route/schema/SQL/Pool/Kubernetes resident service,也不进入 Edge/Standalone closure。13-operation contract、Console/CLI/TLS 定向门 23/23,Cluster Admin 378 pass/3 条件 skip,完整 18-package test 退出 0,backend 1,223 pass/2 条件 skip/0 fail。真实浏览器完成 Run/Task/Workflow 读取、显式下一页、恶意 HTML 纯文本、390×844 与零 console error/warning,并发现、修正 `[hidden]` 被 panel layout 覆盖的问题;真实 arm64 Admin image `qinglong3-cluster-admin:d329-local` 为 344,518,724 bytes,在 non-root/read-only/network-none/no-capability/no-new-privileges/0.25 CPU/128 MiB/32 PIDs 下验证 10 个产品命令、原生/host-published Console 与内置分发文件。npm pack dry-run 为 245 files、262,246-byte tarball、1,642,267-byte unpacked;package/dependency/Cluster deployment/image release/Console/distribution 审计零 finding,workspace 为 18 package 且无 single-source/shallow package。14 档 Local artifact 全部 compatible;默认 Edge/Standalone 精确保持 2,589,890/2,589,968 bytes、315 files、56 modules,application+AI 保持 4,493,043/4,493,175 bytes,MCP 保持 7,315,930/7,316,038 bytes。本 Gate 无 schema、migration、SQL、role、Pool、连接或 HA 拓扑变化,继续引用 D-323 PostgreSQL 18.6 arm64 physical HA 142/142、timeline `1→2` 基线。下一独立 Gate 应把现场 evidence 升级为可下载的显式脱敏诊断包,或补公开 release digest 的外部工作站 ceremony;不得增加浏览器代理权、自动全量抓取或把 Console 变为 Kubernetes 常驻服务。
|
||||
- D-328/ADR-0420(已接受):Cluster Copilot Console 的 operator-workstation 分发已冻结为既有 `qinglong3-cluster-admin@sha256:…` 多架构 OCI,而不是再发布 Node archive、安装器镜像或第 19 个 workspace package。Admin release workflow 已有 amd64/arm64 原生构建、production dependency audit、BuildKit provenance/SBOM、OS vulnerability scan、扫描后 OCI merge、keyless Cosign signature,以及绑定 repository/workflow/source commit/source tag 的 GitHub provenance、CycloneDX 和 OS-vulnerability attestations;新增 `verify-release.sh` 要求 image digest、40-hex revision 与 `refs/tags/v3.*`,独立复验 exact workflow certificate identity、GitHub OIDC issuer、三类 predicate、OCI bundle 并拒绝 mutable tag、branch ref 与 self-hosted builder。已签名 image filesystem 现在携带 `0555` launcher/verifier 和 `0444` 文档/配置模板,因此 signature 同时覆盖宿主启动路径,不存在第二套依赖树。原生 Console 默认继续只监听 `127.0.0.1` ephemeral port;只有显式 `--container-published-loopback` 加固定高端口才允许容器 network namespace 内监听 `0.0.0.0`,并仍对外报告 `publishedHostAddress=127.0.0.1`。reviewed launcher 只接受 immutable digest、canonical private root、显式命名网络和 `compact|standard` 两档资源,拒绝 `bridge|default|host|none`;`check` 不 publish,`serve` 唯一映射为 `127.0.0.1:<port>:<port>/tcp`,同时固定 non-root `10001:10001`、read-only root、drop ALL、no-new-privileges、8 MiB noexec tmpfs、一个只读 authority mount、`--pull never`、3 秒 stop,compact 为 192 MiB/0.25 CPU/32 PIDs,standard 为 512 MiB/1 CPU/64 PIDs。启动器/验签器/分发审计与 Console 定向门 30/30;release/OCI/SBOM 定向门 75/75,package/dependency/Edge/Cluster deployment/Console distribution 审计全部零 finding。Cluster Admin 376 pass/3 条件 skip,完整 18-package clean build/test 退出 0,backend 1,223 pass/2 条件 skip/0 fail。npm pack dry-run 保持 245 files、258,591-byte tarball、1,616,582-byte unpacked。真实 arm64 image `qinglong3-cluster-admin:d328-local` 为 344,492,529 bytes,验证 10 个产品命令、镜像内五项分发文件及 mode、原生 loopback Console;新增 named-network 现场门选择一个空闲高端口并以 exact `127.0.0.1:P:P` 发布,宿主真实读取页面,同时复验 read-only/non-root/no-capability/no-new-privileges 边界与容器/网络清理。14 档 Local artifact 全部 compatible;默认 Edge/Standalone 仍精确为 2,589,890/2,589,968 bytes、315 files、56 modules,application+AI 仍为 4,493,043/4,493,175 bytes,MCP 仍为 7,315,930/7,316,038 bytes,证明工作站分发没有进入低配路由设备闭包。workspace 保持 18 package、`singleSourcePackages=[]`、`shallowSourcePackages=[]`,Cluster Admin 120 个源码中 119 个位于嵌套职责目录。本 Gate 无 schema、migration、SQL、role、Pool、连接或 HA 拓扑变化,继续引用 D-323 PostgreSQL 18.6 arm64 physical HA 142/142、timeline `1→2` 基线。下一独立 Gate 应在同一 Console/BFF ownership 下增加只读 Run/Task/Workflow 观察面,或补公开 release tag 的外部工作站 ceremony;不得把容器内部 listener 误当宿主 LAN authority、引入第二分发依赖树或把 Console 变成 Kubernetes 常驻服务。
|
||||
- D-327/ADR-0419(已接受):QingLong 3.0 首个 Cluster 浏览器产品面已冻结为独立的 operator-workstation、loopback-only、只读 Copilot Console,而不是继续扩展 2.x Umi `src/pages`、legacy session 与 `/api` proxy。实现内聚在既有 `@qinglong/cluster-admin/copilot-console`,workspace 仍为 18 个 package;统一产品 façade 增加第十个静态命令 `copilot-console`。BFF 只监听 `127.0.0.1` ephemeral port,启动前复验包内 HTML/CSS/JS 的路径、realpath、类型、UTF-8、大小与固定 SHA-256;三项资源合计 24,150 bytes,无外部 asset/font/CDN。Cluster `ql3c_` credential 始终留在服务端 owner-private `0600` 文件且每次上游调用重新读取;浏览器只使用另一份 exact 256-bit session key,服务端只保存 domain-separated digest,页面只保存在内存,不进入 cookie、URL、argv、environment、local/session storage。Browser BFF 仅接受 exact `inspect|output`,复用 D-324 共享 TypeScript client,不执行 CLI 子进程、不直连数据库/application capability,并明确没有 diagnose/cancel、poller、WebSocket/SSE、ServiceWorker、queue/retry/cache 或后台 timer。Host、Origin、单 Authorization、route/operation 和 JSON framing 必须 exact;第三个并发 read 立即 `429`,固定 4 KiB request、约 2 MiB response、2 in-flight、16 connections 和 2 秒 shutdown ceiling。响应全为 `no-store` 且使用 default-deny CSP;模型文本只通过 `textContent` 显示并持续标记为 untrusted/no-action-authority。部署手册固定受信运维工作站生命周期,禁止 Kubernetes workload、Ingress、sidecar、共享 LAN 和容器 `0.0.0.0`;Edge/Standalone、Local MCP、Cluster Control/AI closure 均不导入 Console。npm pack dry-run 确认 245 files、258,012-byte tarball、1,614,503-byte unpacked,包含三项静态资源与全部 BFF/CLI 编译产物;独立审计还发现并修正真实 Admin Dockerfile 原先遗漏 assets 的发布缺陷,并把生产 files 白名单精确收窄到 `assets/copilot-console/*`。真实 Playwright 现场门覆盖 session 解锁、status read、显式 output reveal、390px 响应式布局和键盘路径;含 `<script>` 的模型输出保持纯文本,最终 0 error/0 warning,并修正了现代 HTML `/v` pattern 对未转义 `-` 的兼容问题。Console contract/CLI 12/12、定向产品入口 25/25、Cluster Admin 374 pass/3 条件 skip、完整 18-package clean build/test 退出 0、backend 1,215 pass/2 条件 skip/0 fail;package/dependency/Edge import/Cluster deployment/Console 审计零 finding,OCI/release 64/64、SBOM 11/11。真实 arm64 Admin image `qinglong3-cluster-admin:d327-local` 为 344,479,739 bytes,在 `10001:10001`、read-only root、network none、drop ALL、no-new-privileges、0.25 CPU、128 MiB/32 PIDs 下验证 10 个产品命令,并在同一受限容器内真实启动 Console、读取 digest-bound 页面与干净关闭。14 档 Local artifact 全部 compatible;默认 Edge/Standalone 仍精确为 2,589,890/2,589,968 bytes、315 files、56 modules,application+AI 为 4,493,043/4,493,175 bytes,MCP 为 7,315,930/7,316,038 bytes,证明 Cluster UI 没有进入低配路由设备。本 Gate 无 schema、migration、SQL、role、Pool、连接或 HA 拓扑变化,因此不重跑物理 HA,继续引用 D-323 PostgreSQL 18.6 arm64 142/142、timeline `1→2` 基线。下一独立 Gate 应交付可独立验签的 operator-workstation Admin/Console 分发物,或在同一 3.0 Console ownership 下增加受同一 BFF 约束的只读 Run/Task/Workflow 观察面;不得回接 2.x session、把浏览器变成 Cluster credential holder,或把 Console 变为常驻 Kubernetes 服务。
|
||||
- D-326/ADR-0418(已接受):Cluster Copilot MCP 已补齐明确的外部 host 部署与资源边界。MCP 仍是 stdio 子进程,必须由支持 MCP 的外部 host 按 session 启动并持有 stdin/stdout;它不部署为 Kubernetes Deployment/Service,否则会形成没有消费者却长期持有 Project credential 的孤儿进程。新增 `deploy/mcp/ql3-cluster-copilot/` 提供 digest-pinned host 配置、owner-private client/MCP 配置示例和固定 Docker launcher;launcher 只允许显式命名网络与 `compact|standard|dense` 三档资源,分别限制为 192 MiB/0.25 CPU/32 PIDs/并发 1、512 MiB/1 CPU/64 PIDs/并发 4、1 GiB/2 CPU/96 PIDs/并发 16,并强制 `--pull never --init --read-only --cap-drop ALL --security-opt no-new-privileges --user 10001:10001`,只读挂载一个私有 authority root,禁止 Docker socket、Kubernetes token、数据库 credential、host/default/bridge/none 网络和可写工作目录。统一产品入口新增第九个静态命令 `ql3-cluster-admin copilot-mcp`;`ql3-copilot-mcp --check` 会先复验私有 config/credential/CA,再用无认证、固定 `GET /readyz` 做低敏预检,并在启动前拒绝配置并发超过 host resource class ceiling,serve 路径仍保持无 listener、无 queue/retry/poller/cache。部署审计同时禁止任何 Kubernetes YAML 常驻该 MCP,并修正了一个真实发布缺陷:OCI layout 旧 fixture 仍声称 Admin 镜像入口是 recovery CLI,现已与真实 `product-cli/cli.js` entrypoint 对齐。workspace 仍为 18 package、无 single-source/shallow package;Cluster Admin 保持 116 个源码、115 个位于嵌套职责目录,Admin SBOM 保持 91 components/87 external/4 internal,Control 和全部 Local 闭包不变。专项发布审计 145/145、Cluster Admin 362 pass/3 条件 skip、18-package clean build/test 退出 0、backend 1,210 pass/2 条件 skip/0 fail,package/dependency/Edge import/Cluster deployment 审计零 finding。真实 arm64 Admin image `qinglong3-cluster-admin:d326-local` 为 344,423,357 bytes,在 `10001:10001`、read-only root、network none、drop ALL、no-new-privileges、0.25 CPU、128 MiB/32 PIDs 下验证 9 个产品命令与新 entrypoint。14 档 Local artifact 全部逐档复验且与 D-325 完全一致:默认 Edge/Standalone 为 2,589,890/2,589,968 bytes、315 files、56 modules,application+AI 为 4,493,043/4,493,175 bytes,MCP 为 7,315,930/7,316,038 bytes,证明 Cluster MCP host 部署没有进入低配路由设备。本 Gate 无 schema、migration、SQL、role、Pool、连接或 HA 拓扑变化,因此不重跑物理 HA,继续引用 D-323 PostgreSQL 18.6 arm64 142/142、timeline `1→2` 基线。下一独立 Gate 应冻结 Cluster UI ownership/read-only Copilot surface,或使用公开 release digest 补真实外部 host session 证据;均不得把 stdio MCP 改成常驻服务或扩大其 credential/网络 authority。
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# ADR-0421:显式 Cluster Run、Task 与 Workflow 观察台
|
||||
|
||||
- 状态:Accepted
|
||||
- 日期:2026-08-16
|
||||
- 关联 RFC:QL-RFC-0001 D-329、Phase 2
|
||||
- 扩展:ADR-0419
|
||||
|
||||
## 背景
|
||||
|
||||
ADR-0419/0420 已冻结 loopback-only Console 与签名 Admin OCI 分发,但人的观察面仍只覆盖 Copilot diagnosis。值班人员要判断“有哪些 Task、某个 Run 走到哪一步、Workflow Run 是否截断或失败”,仍需手工拼接 Cluster API URL。让浏览器获得通用 proxy、任意 path 或 `ql3c_` credential 会直接破坏既有 BFF 边界;为这组 UI/transport 文件再建 workspace package,也会恢复已经清理的薄包和额外制品闭包。
|
||||
|
||||
现有 Cluster Control 已拥有 Project-scoped、Policy-checked、有界的 Run list/detail/events/steps、Task list/detail,以及 Plugin Package Workflow list 和 Workflow Run list/detail/events/steps。D-329 不需要新增 route、repository、schema 或数据库读取模型,只需要把既有低敏投影组合成可用、显式且失败关闭的运维产品面。
|
||||
|
||||
## 决策
|
||||
|
||||
1. 观察面继续归属 `@qinglong/cluster-admin/copilot-console` 和同一个签名 Admin OCI;workspace 保持 18 个 package,不新增浏览器依赖、生产依赖、服务或第二分发物。名称保留以兼容已发布命令,但页面产品语义升级为 Cluster field ledger。
|
||||
2. BFF 固定开放 13 个只读 operation:Copilot `inspect|output`;Run list/detail/events/steps;Task list/detail;Workflow list 与 Workflow Run list/detail/events/steps。服务端为每种 operation 生成 exact Cluster API `GET` path/query,浏览器不能提交 URL、method、header、credential、permission 或 response shape。
|
||||
3. `ql3c_` credential 每次请求从 canonical、current-owner、0600 文件重新读取,TLS 继续固定 1.3、显式 CA/DNS、identity encoding、无 redirect/proxy/compression/connection reuse。新 Project read transport 只接受审核过的 Run/Task/Workflow path grammar,并明确拒绝 start/cancellation、绝对 URL、路径穿越与未知 query。
|
||||
4. Run 与 Workflow 共用 `run.read`,Task 使用 `task.read`,Copilot output 继续使用既有 `artifact.read`;部署推荐 credential 只授予这三项 read permission。UI 即使收到权限更宽的 credential,也没有 mutation route 或通用转发器。
|
||||
5. list 默认每页 32、上限 64;只有响应明确 `hasMore|truncated` 且携带下一 cursor 时,页面才出现“显式读取下一页”。读取列表不会自动读取 detail/steps/events,读取 Run 也不会自动级联。没有 poller、watcher、SSE、WebSocket、retry、queue、cache 或后台 timer。
|
||||
6. 页面采用“现场证据账本”而非通用 Dashboard:每次人工读取形成一条仅存于页面内存的按时序 evidence,所有远端值和模型文本都用 `textContent` 写入。reload/pagehide 清空 session 与账本;不使用 cookie、local/session storage、IndexedDB、ServiceWorker、外部 asset/font/CDN。
|
||||
7. BFF 保留 ADR-0419 的 exact Host/Origin/session、default-deny CSP、no-store、4 KiB request、约 2 MiB response、2 in-flight、16 connections 与第三请求即时 429。未知 route、route/operation mismatch、额外字段、cursor 半对、非法 ID/UUID/limit 一律在上游调用前失败关闭。
|
||||
8. Console 仍是短生命周期 operator-workstation process,不成为 Kubernetes Deployment/Ingress/sidecar 或共享 LAN listener。它不进入 Edge/Standalone、Local API/MCP 或 Cluster Control/AI 默认 closure;路由设备的默认制品必须保持不变。
|
||||
|
||||
## 不选择
|
||||
|
||||
- **浏览器通用反向代理**:即使只允许 GET,也会把未来新增 path 静默暴露给页面,无法证明 operation vocabulary 与权限边界。
|
||||
- **扩展 Copilot command schema**:Run/Task/Workflow 是普通 Cluster observation,不应伪装成 diagnosis command;BFF executor 在内部按领域分派。
|
||||
- **复制第二套 TLS/credential client**:会产生配置、TOCTOU、header、body ceiling 与错误投影漂移;D-329 复用同一 Project API authority transport。
|
||||
- **自动加载详情或实时刷新**:扩大读取次数与资源占用,也让值班人员无法区分 durable fact 与页面自行触发的背景读。
|
||||
- **回接 2.x Web 或新建 package**:前者恢复 legacy session/controller/proxy,后者为单一消费者制造薄包和额外发布矩阵。
|
||||
|
||||
## 验收
|
||||
|
||||
1. contract 单测覆盖全部 13 个 operation、exact field set、cursor pair、ID/package/workflow/UUID/limit、固定 path/query 与 mutation/absolute URL 拒绝。
|
||||
2. TLS 端到端覆盖 owner-private credential、TLS 1.3、Bearer、GET-only、request-ID exact matching、远端低敏错误与 credential buffer 清理;既有 Copilot client/MCP/product CLI 回归必须保持兼容。
|
||||
3. Console server/CLI 覆盖 Host/Origin/session、route confusion、无任意 path、并发即时 429、digest-bound assets、container-published-loopback 和 13-operation manifest。
|
||||
4. 真实浏览器覆盖 session unlock、Run/Task/Workflow/Copilot 手动读取、显式下一页、恶意内容纯文本、窄屏/键盘与零 console error;真实 Admin image 复验相同页面、非 root、read-only/no-capability/no-new-privileges 与 host-loopback publication。
|
||||
5. Console、distribution、package、dependency、Edge import、Cluster deployment 审计零 finding;18-package clean build/test、Cluster Admin、backend、14 档 Local artifact 全部通过后,本 ADR 才转为 Accepted 并进行 D-329 阶段提交。
|
||||
|
||||
## 接受证据
|
||||
|
||||
- 13-operation contract、Console server/CLI 与 TLS client 定向门 23/23;Cluster Admin 378 pass、3 条件 skip;完整 18-package test 退出 0;backend 1,223 pass、2 条件 skip、0 fail。
|
||||
- 真实浏览器完成 Run、Task、Workflow 三类 BFF 读取、Task 显式下一页、恶意 HTML 纯文本、390×844 无横向溢出和 0 error/0 warning;验收同时发现并修正了 `[hidden]` 被 panel layout 覆盖的问题。
|
||||
- 真实 arm64 Admin image `qinglong3-cluster-admin:d329-local` 为 344,518,724 bytes;在 non-root `10001:10001`、read-only root、network none、drop ALL、no-new-privileges、0.25 CPU、128 MiB、32 PIDs 下验证 10 个产品命令、原生/host-published Console 与内置分发文件。
|
||||
- Console/distribution/package/dependency/Cluster deployment/image release 审计零 finding。npm pack dry-run 为 245 files、262,246-byte tarball、1,642,267-byte unpacked;workspace 保持 18 package,`singleSourcePackages=[]`、`shallowSourcePackages=[]`。
|
||||
- 14 档 Local artifact 全部 compatible;默认 Edge/Standalone 精确保持 2,589,890/2,589,968 bytes、315 files、56 modules,application+AI 保持 4,493,043/4,493,175 bytes,MCP 保持 7,315,930/7,316,038 bytes。
|
||||
- 本 Gate 不修改 schema、migration、SQL、role、Pool、连接或 HA 拓扑,因此不重复消耗 PostgreSQL HA 现场门,继续引用 D-323 的 PostgreSQL 18.6 arm64 142/142 与 timeline `1→2` 基线。
|
||||
@@ -424,6 +424,7 @@
|
||||
| [ADR-0418](./ADR-0418-explicit-cluster-copilot-mcp-host-deployment.md) | 显式 Cluster Copilot MCP Host 部署与资源边界 | Accepted |
|
||||
| [ADR-0419](./ADR-0419-loopback-read-only-cluster-copilot-console.md) | Loopback-only Cluster Copilot 只读 Console | Accepted |
|
||||
| [ADR-0420](./ADR-0420-signed-admin-oci-console-workstation-distribution.md) | 以签名 Admin OCI 分发 Cluster Copilot 工作站 Console | Accepted |
|
||||
| [ADR-0421](./ADR-0421-explicit-cluster-run-task-workflow-observation-console.md) | 显式 Cluster Run、Task 与 Workflow 观察台 | Accepted |
|
||||
|
||||
## 规则
|
||||
|
||||
|
||||
Reference in New Issue
Block a user