Skip to content

Commit 09ef174

Browse files
committed
feat(ql3): bridge legacy panel to bounded run logs
1 parent fa730da commit 09ef174

11 files changed

Lines changed: 328 additions & 53 deletions

docs/QINGLONG_3_0_ARCHITECTURE_RFC.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# QingLong 3.0 Architecture RFC
22

3-
- D-428/ADR-0530(源码候选,等待可下载同源装配与双架构阶段实物):在 D-427 的只读 Cron Adapter 上增加显式 Local 面板能力发现和启动边界,而不是伪造完整 2.x 后端。公开、无敏感数据的 exact `GET /api/health`、`GET /api/system`、`GET /api/v3/capabilities` 只接受无 body 与可选单个数字 `t`;认证后的 `GET /api/user`、`GET /api/system/config` 仍经过 Bearer、`task.read` Policy、durable audit 与 credential reconfirm,并只接受 User principal。capability v1 区分 Edge/Standalone 的 64/256 Cron 行与 16/32 KiB 日志块预算,并明确关闭 legacy login/mutation、Subscription、Script、Env 和 WebSocket。现有面板源码只在严格发现 `qinglong3` capability 后进入 3.0 模式:登录页改收 `ql3c_` API Credential,凭据仅驻留模块内存且刷新即丢失;认证成功只进入 `/crontab`;菜单、请求和 Modal 降级为名称/命令描述符/状态/schedule 的有界只读列表,不请求 View、Subscription、非空搜索/排序,也不建立 WebSocket。2.x 模式保持原行为。该切片不新增 package、production dependency、migration、数据库连接、listener、timer、watcher 或后台进程;默认 headless、Cluster authority 与 Node 24 runtime 均不变,旧 Umi 暂用 Node 20 只作为 legacy migration build toolchain。Local API 12-package closure 与 89/89、18-package 完整测试、package/import/dependency audit、旧面板 production build 均通过;Playwright 同源源码旅程验证了登录、只读列表和刷新清凭据,最终 0 console error。仍须把改造静态资源装入可下载 Console、在 exact Console + Local API + SQLite 上重跑真实 credential journey、通过远端 CI 和双架构 artifact,才能声明阶段页面产物可直接部署。
3+
- D-429/ADR-0531(源码候选,等待远端 CI 与 exact 双架构 Console 实物):现有面板的 Cron “日志”入口不恢复 2.x `/api/crons/:id/log` 或文件系统日志权威,而是复用规范 v3 Run/Attempt/Artifact 链。`BoundedRunListItem` 仅增加经 128 字节无控制字符验证的可选 `triggerId`;页面按 `triggerId + taskId` 在 Edge 64/Standalone 256 条 Run 总预算中定位最新 Run,再读取 detail 的 latest Attempt 与 16/32 KiB 首个日志片段,明确呈现 pending/retired/truncated。所有请求继续走 Bearer、Project Policy、durable audit、credential reconfirm 与 Artifact retention;不暴露路径、Artifact id、Secret 或其他 Run 私有字段。QL3 Action 列只开放日志,列表关闭旧 10 秒轮询,日志关闭旧 2 秒轮询,仅由初次进入、点击与手动刷新驱动;2.x 行为保持不变。没有新增 package、dependency、migration、schema、listener、连接或后台进程,headless 与 Cluster authority 不变。本地 runtime-core 594/594、兼容回归 4/4、Node 20 production build、240 files / 11,965,017 bytes 闭包审计和真实 Chromium journey 已通过;浏览器稳定 15 秒只有一次 Cron list,日志稳定 5 秒只有 Run list/detail/log 各一次。
4+
5+
- D-428/ADR-0530(exact 双架构阶段实物已交付):在 D-427 的只读 Cron Adapter 上增加显式 Local 面板能力发现和启动边界,而不是伪造完整 2.x 后端。公开、无敏感数据的 exact `GET /api/health`、`GET /api/system`、`GET /api/v3/capabilities` 只接受无 body 与可选单个数字 `t`;认证后的 `GET /api/user`、`GET /api/system/config` 仍经过 Bearer、`task.read` Policy、durable audit 与 credential reconfirm,并只接受 User principal。capability v1 区分 Edge/Standalone 的 64/256 Cron 行与 16/32 KiB 日志块预算,并明确关闭 legacy login/mutation、Subscription、Script、Env 和 WebSocket。现有面板源码只在严格发现 `qinglong3` capability 后进入 3.0 模式:登录页改收 `ql3c_` API Credential,凭据仅驻留模块内存且刷新即丢失;认证成功只进入 `/crontab`;菜单、请求和 Modal 降级为名称/命令描述符/状态/schedule 的有界只读列表,不请求 View、Subscription、非空搜索/排序,也不建立 WebSocket。2.x 模式保持原行为。该切片不新增 package、production dependency、migration、数据库连接、listener、timer、watcher 或后台进程;默认 headless、Cluster authority 与 Node 24 runtime 均不变,旧 Umi 暂用 Node 20 只作为 legacy migration build toolchain。提交 `fa730da0912d0e3c503697e7816aa0b14fa02165` 的普通主 CI run `33597913690` 为 42 success / 3 expected condition skip / 0 fail,Console artifact run `33597938992` 为 43 success / 2 expected skip / 0 fail;amd64/arm64/milestone artifact `9834695619`/`9834657575`/`9834716653` 保留至 2026-10-02。下载后的 v7 milestone `SHA256SUMS` 与离线 auditor 均返回 `compatible=true`,D-428 因此已经是可直接试运行的阶段页面产物。
46

57
- D-427/ADR-0529(双架构阶段实物已交付):开始把现有 2.x 面板从“不能零改直连”推进为受控页面复用,而不是把旧 Express Service 或数据库写 authority 搬回 3.0。第一切片只在既有 `@qinglong/local-api/panel-compatibility` 子域开放认证后的 `GET /api/crons`:正式 Bearer credential、`task.read` Policy、durable audit、credential reconfirm 后,按 Edge 64/Standalone 256 行上限读取 `qinglong/cron@v1` Trigger 前缀,并以 Trigger 固定的 `taskId/revision/contentDigest` 读取 pinned Task revision。每个 Trigger 投影成一条旧 Cron 包络,字符串 `triggerId` 保持稳定身份,schedule/timezone/misfire 来自规范化 Trigger;command 只返回 `ql3:<kind>:<taskId>@<revision>` 描述符,不暴露 argv、环境、Secret、label、mutation 或 digest。缺失 pinned Task、identity 漂移、未知 Trigger schema、异常页和超预算均整体失败关闭。首切片只接受旧页面初始空 search/filter 与有界 page/size;搜索、排序、View query 和全部写操作明确拒绝。它不新增 package、dependency、migration、连接、listener、timer 或 watcher;headless 与 Cluster 路径不变,也不提供 2.x login/JWT、静态面板、WebSocket、Cron View、Subscription、Script、Env 或 Run/Log 兼容。本地真实 SQLite/credential/Policy/HTTP 集成、Local API 83/83、18-package clean build/test 和 Edge/Standalone Application API 资源门已通过。提交 `83966a128705f6ef0ae54367c8f656e3d578e9c6` 的显式 Local headless [run 33576693917](https://github.com/whyour/qinglong/actions/runs/33576693917) 与 Local Console [run 33578754251](https://github.com/whyour/qinglong/actions/runs/33578754251) 均成功;headless amd64/arm64/milestone artifact `9827434236`/`9827259756`/`9827553099`,Console `9828792297`/`9828714089`/`9828941802`,均未过期并保留至 2026-10-02。D-427 因此闭合为后端阶段实物;它仍不包含改造后的 2.x 静态面板,页面交付由 D-428 独立闭合。
68

docs/adr/ADR-0529-bounded-read-only-local-panel-cron-adapter.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,4 @@ QingLong 2.x 面板以 `/api/crons`、数值型 Cron 行和 `{code,data}` 包络
5858

5959
提交 `83966a128705f6ef0ae54367c8f656e3d578e9c6` 的显式 Local headless [run 33576693917](https://github.com/whyour/qinglong/actions/runs/33576693917) 与 Local Console [run 33578754251](https://github.com/whyour/qinglong/actions/runs/33578754251) 均成功。headless amd64/arm64/milestone artifact 为 `9827434236`/`9827259756`/`9827553099`,Console 为 `9828792297`/`9828714089`/`9828941802`;均绑定同一 source revision,保留至 2026-10-02。headless 继续不携带 Local API/旧面板;Console artifact 携带本 Adapter,但仍只证明后端兼容切片,不包含改造后的 2.x 静态面板。
6060

61-
后续按 `health/system/user capability → Run/Log read → 显式写操作` 推进。ADR-0530 已完成 capability/bootstrap 与旧面板源码的内存凭据、菜单降级、只读 Crontab 适配;仍须完成同源静态资源装配和真实浏览器 journey,才能把该页面作为可下载阶段产物交付。完整 2.x 零改兼容不作为 3.0 目标。
61+
后续按 `health/system/user capability → Run/Log read → 显式写操作` 推进。ADR-0530 已完成 capability/bootstrap、同源静态装配、真实浏览器 journey 和双架构阶段实物;ADR-0531 继续以规范 v3 API、caller-driven 读取和 Profile 预算开放 Cron 日志。完整 2.x 零改兼容不作为 3.0 目标。

docs/adr/ADR-0530-bounded-local-panel-capability-bootstrap.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ADR-0530:有界 Local 面板能力发现与启动适配
22

3-
- 状态:Accepted(D-428 本地同源装配候选已闭合,等待远端 CI 与双架构可下载实物门
3+
- 状态:Accepted(D-428 exact Console 双架构阶段实物已交付
44
- 日期:2026-09-02
55
- 关联 RFC:QL-RFC-0001 D-428、D-427、D-423、D-424
66

@@ -40,13 +40,14 @@ ADR-0529 已交付认证后的只读 `/api/crons` Adapter,但现有 2.x 面板
4040

4141
本地装配候选已经通过 12-package Console closure、719 files / 16,162,123 bytes(上限 768 files / 20 MiB)镜像审计,以及面板 240-file 哈希/磁盘闭包复核。最终 arm64 Edge 镜像 `sha256:27472cf1bdd66d9fa4e937622ef69d4e36f74918a759de62818b4e59d265714c` 已完成 fresh setup/replay、Owner provision/challenge/claim/presentation/ack、首个 Task 执行与日志标记、graceful stop、SQLite integrity 和 HTTP 200/401 边界,结果为 `compatible=true`
4242

43-
真实浏览器已验证现有页面使用内存中的 `ql3c_` credential 完成 `/login``/crontab`,53 个同源静态请求全部为 200,`/api/health``/api/system``/api/v3/capabilities``/api/user``/api/system/config``/api/crons` 均为 200;最终镜像同时验证 `/console` 原生管理台与 `/login` 旧页面共存。旧页面仍引用的外部图标/装饰图片被严格 CSP 阻止,页面功能可用但这些装饰会缺失;本阶段不为消除装饰错误而放宽网络或 CSP。远端 CI 和可下载双架构实物仍待闭合。
43+
真实浏览器已验证现有页面使用内存中的 `ql3c_` credential 完成 `/login``/crontab`,53 个同源静态请求全部为 200,`/api/health``/api/system``/api/v3/capabilities``/api/user``/api/system/config``/api/crons` 均为 200;最终镜像同时验证 `/console` 原生管理台与 `/login` 旧页面共存。旧页面仍引用的外部图标/装饰图片被严格 CSP 阻止,页面功能可用但这些装饰会缺失;本阶段不为消除装饰错误而放宽网络或 CSP。
44+
45+
提交 `fa730da0912d0e3c503697e7816aa0b14fa02165` 的普通主 CI [run 33597913690](https://github.com/whyour/qinglong/actions/runs/33597913690) 为 42 success / 3 expected condition skip / 0 fail;显式 Console artifact [run 33597938992](https://github.com/whyour/qinglong/actions/runs/33597938992) 为 43 success / 2 expected skip / 0 fail。该 run 交付 amd64/arm64/milestone artifact `9834695619`/`9834657575`/`9834716653`,大小 `239011275`/`234410955`/`6797` bytes,保留至 2026-10-02;下载后的 milestone `SHA256SUMS` 与 v7 auditor 均通过并返回 `compatible=true`。D-428 因此闭合为可直接试运行的 exact 双架构阶段页面产物。
4446

4547
仍未完成:
4648

47-
1. 推送后通过远端完整 CI,并生成、下载和离线复核 exact amd64/arm64 Console Trial Kit 与 milestone;
48-
2. 把旧面板引用的外部图标和装饰图片转为受审本地资产,做到严格 CSP 下无外部请求;
49-
3. 为旧页面增加 Run/Log 只读 adapter 后再开放日志入口;
50-
4. 写操作必须逐项映射到 3.0 revision、Policy、presence/approval、audit 和 mutation fence,不能用通配兼容路由一次性开放。
49+
1. 把旧面板引用的外部图标和装饰图片转为受审本地资产,做到严格 CSP 下无外部请求;
50+
2. Run/Log 入口由 ADR-0531 以规范 v3 API 的 caller-driven 客户端桥接继续推进;
51+
3. 写操作必须逐项映射到 3.0 revision、Policy、presence/approval、audit 和 mutation fence,不能用通配兼容路由一次性开放。
5152

52-
在远端实物门完成前,本 ADR 声明的是“当前提交可装配并实跑现有面板的受控子集”,不是 Public Release,也不声明完整 2.x 面板可以零修改直连。
53+
本 ADR 声明的是“已有 exact 双架构阶段产物可装配并实跑现有面板的受控子集”,不是 Public Release,也不声明完整 2.x 面板可以零修改直连。
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# ADR-0531:现有面板到规范 Run 日志的有界桥接
2+
3+
- 状态:Accepted(D-429 源码候选;远端 CI 与双架构 Console 实物待 gate)
4+
- 日期:2026-09-04
5+
- 关联 RFC:QL-RFC-0001 D-429、D-428、D-415
6+
7+
## 背景
8+
9+
ADR-0530 已把现有 2.x 面板作为受限静态客户端装入 Local Console,并只开放 Cron 列表。用户仍无法从该页面观察一次定时执行的日志。恢复旧 `/api/crons/:id/log`、文件系统日志目录或 2 秒轮询,会复制已经存在的 3.0 Run/Attempt/Artifact 权威,并给 Edge 路由设备增加持续请求。
10+
11+
Run 聚合已经持久化可选 `triggerId`,规范 Local API 已提供有界 Run list、Run detail 与 Attempt log range read。缺口不是新的日志后端,而是安全地把这条规范链交给受限旧页面。
12+
13+
## 决策
14+
15+
- `BoundedRunListItem` 增加可选 `triggerId`。只有值存在且满足 128 字节无控制字符边界时才投影;其余 Run 私有字段仍不跨越 projection。
16+
- 旧面板不新增 `/api/crons/:id/log` 兼容路由。用户点击某个 Cron 的“日志”后,页面按 capability budget 分页读取 `/api/v3/projects/:project/runs`,以 `triggerId + taskId` 精确选择最新 Run,再读取 Run detail 的 latest Attempt 和该 Attempt 的首个日志片段。
17+
- 每次日志片段仍经过既有 Bearer authentication、`artifact.read` Policy、durable audit、credential reconfirm 与 Artifact retention 检查。页面不接触文件路径、Artifact id 或 Secret。
18+
- Edge 最多扫描 64 条 Run、读取 16 KiB;Standalone 最多扫描 256 条 Run、读取 32 KiB。每页最大 64 条。未找到、尚未就绪、已清理、运行中无 Artifact 和截断状态必须显式呈现。
19+
- QL3 模式下 Cron 列表不再运行旧页面的 10 秒轮询,日志也不运行旧页面的 2 秒轮询。初始列表只读一次,后续列表由分页/页面动作触发;日志只由点击和“刷新”按钮触发。
20+
- QL3 的 Action 列只保留“日志”。运行、停止、更多、创建、批量操作和写 Modal 继续隐藏;2.x 模式保持原行为。
21+
22+
## 部署与架构边界
23+
24+
- 不新增 workspace package、production dependency、migration、schema、数据库连接、listener、timer、watcher 或后台进程。
25+
- 默认 headless 产物不含旧面板,资源占用不变。Console 仍使用同一个 loopback Local API 和同一个受限静态闭包。
26+
- Cluster 不复用 Local 面板 shell;`triggerId` 是 profile-neutral 的 Run 低敏感关联字段,因此规范 Run projection 可被 Local/Cluster 消费,但本 ADR 不新增 Cluster UI。
27+
- 这是一条迁移期客户端桥接,不把 2.x 页面定义为 QingLong 3.0 的领域模型或长期管理面。新的 3.0 能力优先进入原生 `/console`
28+
29+
## 验证与剩余门禁
30+
31+
本地已完成 runtime-core 594/594、Local API 93/93、18-package clean build/test、后端 1685 项(1683 pass / 2 environment skip / 0 fail)、兼容闭包回归 4/4、Node 20 production panel build,以及 package boundary、Edge import、Cluster dependency 和 240 files / 11,965,017 bytes 离线闭包审计。真实 Chromium mock journey 验证了 QL3 credential 登录、只读 Action 列、Run list → Run detail → Attempt log 三个规范请求和 Base64/UTF-8 日志展示;页面稳定 15 秒只有一次 Cron list,日志打开后稳定 5 秒没有自动重读。
32+
33+
仍须完成 GitNexus staged/default-branch change detection、阶段提交、远端完整 CI,并生成、下载和离线复核 exact amd64/arm64 Console Trial Kit 与 milestone,才可把 D-429 标记为双架构阶段实物已交付。
34+
35+
## 不做的方案
36+
37+
- 不恢复旧文件日志 API 或任意路径读取;
38+
- 不把日志轮询速度做成配置项;低端设备默认仍会付出持续成本;
39+
- 不在本切片开放 Run start/stop、Cron mutation 或完整 `/log` 页面;
40+
- 不为复用旧页面而把 Local SQLite/POSIX authority 带入 Cluster。

docs/adr/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,8 @@
533533
| [ADR-0527](./ADR-0527-reviewed-automation-reconciliation-application-and-rollback.md) | 受审核 Automation Reconciliation 应用与显式回滚 | Accepted(exact headless 双架构阶段实物已交付) |
534534
| [ADR-0528](./ADR-0528-cross-domain-reconciliation-completion-rehearsal.md) | 跨域 Reconciliation Completion 演练 | Accepted(D-426c3 源码候选;双架构阶段实物待 gate) |
535535
| [ADR-0529](./ADR-0529-bounded-read-only-local-panel-cron-adapter.md) | 有界只读 Local 旧面板 Cron Adapter | Accepted(D-427 双架构阶段实物已交付) |
536-
| [ADR-0530](./ADR-0530-bounded-local-panel-capability-bootstrap.md) | 有界 Local 面板能力发现与启动适配 | Proposed(D-428 源码候选;可下载同源装配与双架构实物待 gate) |
536+
| [ADR-0530](./ADR-0530-bounded-local-panel-capability-bootstrap.md) | 有界 Local 面板能力发现与启动适配 | Accepted(D-428 exact Console 双架构阶段实物已交付) |
537+
| [ADR-0531](./ADR-0531-canonical-run-log-bridge-for-legacy-panel.md) | 现有面板到规范 Run 日志的有界桥接 | Accepted(D-429 源码候选;远端 CI 与双架构 Console 实物待 gate) |
537538

538539
## 规则
539540

0 commit comments

Comments
 (0)