mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
feat(ql3): export redacted cluster evidence bundle
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
|
||||
最新增量证据(2026-08-16):
|
||||
|
||||
- D-330/ADR-0422(已接受):同一 loopback-only Cluster field ledger 现可由用户显式导出纯浏览器本地的脱敏 evidence bundle。导出只消费本页已逐次读取的最近 16 条、最多 8 MiB canonical fact,不调用 upstream/BFF、补读详情/分页、轮询、上传或持久化;固定 sanitizer 只保留 operation、非权威本机观察时间、安全枚举/boolean/有界 number、结构计数/分页事实、per-bundle typed alias 与原始 fact canonical byte count/SHA-256,自由文本、名称、路径/URL/command/input/output/environment、reason/error/message、credential/token/session/authorization、未知字段及 Copilot model text 一律省略。bundle 固定为 UTF-8 `qinglong/cluster-console-redacted-evidence-bundle@v1` JSON、最大 512 KiB,顶层 self-digest 明确不是 server signature/audit/action authority;生成器作为第 4 个 digest-bound asset 留在既有 `@qinglong/cluster-admin`,不增加 package、依赖、Cluster/BFF route、数据库、对象存储、Kubernetes workload 或 Edge/Standalone closure。定向门 24/24,Cluster Admin 382 pass/3 条件 skip,完整 18-package test 退出 0,backend 1,224 pass/2 条件 skip/0 fail。真实浏览器以恶意 HTML、credential-like 值、私有路径和 Copilot model text 验证纯文本与零泄漏;3 次显式读取后导出 3,611-byte 可复算 JSON,upstream 计数仍为 3,390×844 无横向溢出且 0 console error/warning。真实 arm64 Admin image `qinglong3-cluster-admin:d330-local` 为 344,543,263 bytes,在 non-root/read-only/network-none/no-capability/no-new-privileges/0.25 CPU/128 MiB/32 PIDs 下验证 10 个产品命令、原生/host-published Console、第 4 个 asset 与内置分发。npm pack dry-run 为 246 files、267,731-byte tarball、1,665,996-byte unpacked;package/dependency/Edge import/Cluster deployment/image release/Console/distribution 审计零 finding。workspace 保持 18 package、`singleSourcePackages=[]`、`shallowSourcePackages=[]`,1,199 个源码中 1,181 个位于职责目录。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。PostgreSQL 18.6 arm64 physical HA 142/142、timeline `1→2`,报告 SHA-256 `c9feb83c98ad2269c7649bd0869921d9dee7cfd00c9bc1a8a7879d81630d37c7`,证据审计与 Docker 残留均为零;本 Gate 没有 schema、migration、SQL、role、Pool 或连接拓扑变化。下一独立 Gate 应交付公开 release digest 的外部工作站 ceremony,或提供独立、离线、无 authority 的 evidence bundle verifier;不得为导出增加服务端聚合、稳定跨包标识、自动抓取或上传能力。
|
||||
- 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 服务。
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
# ADR-0422:浏览器本地生成的脱敏 Cluster Evidence Bundle
|
||||
|
||||
- 状态:Accepted
|
||||
- 日期:2026-08-16
|
||||
- 关联 RFC:QL-RFC-0001 D-330、Phase 2
|
||||
- 扩展:ADR-0421
|
||||
|
||||
## 背景
|
||||
|
||||
ADR-0421 已让值班人员通过同一个 loopback-only Console 显式读取 Run、Task、Workflow 和 Copilot 事实,但证据仍只存在于页面 DOM。截图不利于机器复核,复制原始 JSON 又容易把 Project/Run/Task/Artifact 标识符、用户命名和 Copilot 模型文本直接带出工作站。若为“导出”新增 Cluster API、通用 proxy、服务端 ZIP 组装、对象存储或后台采集器,会扩大 credential、网络、持久化与资源边界,也会把一次人工观察错误升级为新的集群产品能力。
|
||||
|
||||
## 决策
|
||||
|
||||
1. D-330 在既有 `@qinglong/cluster-admin/copilot-console` 中增加第 4 个 digest-bound 静态资产 `evidence-bundle.js`。它同时是浏览器脚本和可由 Node 单测加载的纯生成器;不新增 workspace package、npm 生产依赖、Cluster route、BFF POST route、数据库、文件写服务、Kubernetes workload 或第二分发物。
|
||||
2. 导出只由用户点击“导出脱敏包”触发,只消费当前页面内已经完成的显式读取。它不得调用 `fetch`、打开 socket、补读详情/分页、轮询、重试、排队、上传、调用 clipboard/share API 或读取 session/Cluster credential。
|
||||
3. 页面账本硬限制为最近 16 条且原始 canonical JSON 合计不超过 8 MiB;新证据到达时在 DOM 与内存中同步淘汰最旧记录,并明确显示保留数量。单条仍受 BFF 约 2 MiB response ceiling 约束。bundle 本身不得超过 512 KiB,所有数组最多保留 64 项。
|
||||
4. `qinglong/cluster-console-redacted-evidence-bundle@v1` 只包含 operation、非权威本机观察时间、固定安全枚举、boolean/有界 number、结构计数、分页事实、identifier alias 和每条原始事实的 canonical byte count/SHA-256。自由文本、名称、路径、URL、command、input/output、environment、reason/error/message、credential/token/authorization、未知 key/value 一律不进入 bundle;Copilot output 文本无条件省略。
|
||||
5. Project、Run、Task、Workflow、Package、Step、Artifact、request 与 digest 等标识符按类型在每个 bundle 内稳定映射为顺序 alias,例如 `run-001`。原始到 alias 的映射不写入文件;相同原始标识在同一 bundle 内可关联,不同 bundle 之间不能依赖 alias 稳定性。
|
||||
6. 生成器对每条原始 fact 做键排序 canonical JSON 后计算 SHA-256,再对不含顶层 `contentDigest` 的完整脱敏 bundle 做第二次 SHA-256。该 digest 只用于完整性/复核,不是服务端签名、durable audit、来源证明或行动授权;文件明确声明 `attestation=none`、`actionAuthority=none`、`generatedBy=browser_local`。
|
||||
7. 下载格式固定为 UTF-8 JSON 加末尾换行,文件名不含任何 Project/Run/Task 标识。浏览器只使用 `crypto.subtle`、`TextEncoder`、`Blob` 与临时 object URL;点击后立即移除 anchor 并 revoke URL,不使用 timer、ServiceWorker、IndexedDB、local/session storage 或缓存。
|
||||
8. Console 的 13 个 upstream read operation、`run.read|task.read|artifact.read` 推荐权限、Host/Origin/session、TLS 1.3、并发和 response ceiling 保持不变。该 bundle 不进入 Edge/Standalone 或 Cluster Control/AI closure;路由设备默认制品必须逐字节保持既有边界。
|
||||
|
||||
## 不选择
|
||||
|
||||
- **导出原始账本再提示用户自行脱敏**:把最困难且最容易遗漏的安全步骤交给值班人员,模型文本和用户命名会直接泄漏。
|
||||
- **BFF/Cluster 服务端生成 ZIP**:需要更大 request body、临时文件、压缩库和新的 route,且会让浏览器提交的数据看起来像服务端证明。
|
||||
- **下载前自动补齐所有分页和详情**:形成隐藏的读取放大器,破坏 ADR-0421 的“一次点击、一次读取”。
|
||||
- **用 session key 签名 bundle**:session 是浏览器访问能力,不是签名身份;HMAC 会错误暗示集群来源证明并增加密钥滥用面。
|
||||
- **长期稳定哈希标识符**:即使不包含原文,也会让不同导出物可关联;per-bundle alias 更符合最小披露。
|
||||
|
||||
## 验收
|
||||
|
||||
1. 生成器单测覆盖 exact input、16-entry/8 MiB/512 KiB/64-item ceiling、canonical digest、同包 alias 关联、跨包 alias 重置、原始/未知/自由文本和 credential/session/model output 永不出现,以及循环/非 JSON/非法时间/operation 失败关闭。
|
||||
2. Console server/asset 单测证明第 4 个 asset 经过 realpath/type/UTF-8/size/SHA-256 复验,只从 same-origin 固定 GET path 返回;CSP、Host、Origin、session 和 upstream route vocabulary 不扩大。
|
||||
3. 真实浏览器证明导出按钮初始禁用、读取后可用、下载文件可解析且 digest 可复算、恶意 HTML/credential-like 值和 Copilot output 不存在、alias 可关联;导出期间 upstream request 计数不增加,390px 无横向溢出且 0 console error/warning。
|
||||
4. Console/distribution/package/dependency/Cluster deployment 审计零 finding,真实 Admin image 和 host-published Console 能取得第 4 个 asset;18-package、Cluster Admin、backend 与 14 档 Local artifact 全部通过后,本 ADR 才转为 Accepted 并进行 D-330 阶段提交。
|
||||
|
||||
## 验收结果
|
||||
|
||||
2026-08-16,D-330 完成以下发布门并接受本决策:
|
||||
|
||||
- 生成器、Console server、产品镜像契约与负面架构审计定向测试 24/24;`@qinglong/cluster-admin` 完整测试 382 pass、3 条件 skip、0 fail,18-package clean build/test 退出 0,backend 1,224 pass、2 条件 skip、0 fail。
|
||||
- 真实浏览器以恶意 HTML、credential-like 值、私有路径和 Copilot 模型文本验证纯文本渲染与固定白名单脱敏;3 次显式读取前后,导出没有增加第 4 次 upstream 请求。下载的 3,611-byte JSON 可复算顶层 digest,同一 Project/Run alias 可关联,敏感样本零命中;390×844 无横向溢出,0 console error/warning,清空后内存账本与导出能力同步归零。
|
||||
- 真实 arm64 `qinglong3-cluster-admin:d330-local` 为 344,543,263 bytes;在 UID/GID 10001、只读根、network none、drop ALL、no-new-privileges、0.25 CPU、128 MiB 与 32 PIDs 下通过 10 个产品命令、原生/host-published Console、第 4 个 asset 和内置分发物契约。
|
||||
- npm pack dry-run 为 246 files、267,731-byte tarball、1,665,996-byte unpacked;package/dependency/Edge import/Cluster deployment/image release/Console/distribution 审计全部零 finding。workspace 保持 18 package、`singleSourcePackages=[]`、`shallowSourcePackages=[]`;1,199 个源码中 1,181 个位于包内职责目录,Cluster Admin 为 120 个源码、119 个嵌套源码。
|
||||
- 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,证明证据包未进入路由设备闭包。
|
||||
- PostgreSQL 18.6 arm64 physical HA 142/142,timeline `1→2`,私有报告 SHA-256 为 `c9feb83c98ad2269c7649bd0869921d9dee7cfd00c9bc1a8a7879d81630d37c7`;离线证据审计零 finding,容器、网络和卷零残留。D-330 本身没有 schema、migration、SQL、role、Pool 或连接拓扑变化。
|
||||
@@ -425,6 +425,7 @@
|
||||
| [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 |
|
||||
| [ADR-0422](./ADR-0422-browser-local-redacted-cluster-evidence-bundle.md) | 浏览器本地生成的脱敏 Cluster Evidence Bundle | Accepted |
|
||||
|
||||
## 规则
|
||||
|
||||
|
||||
Reference in New Issue
Block a user