mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 08:05:22 +08:00
feat(ql3): add bounded panel bootstrap
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
# QingLong 3.0 Architecture RFC
|
||||
|
||||
- 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 资源门已通过;仍须完成双架构 artifact 门,并继续实现 capability shell 与 Run/Log read,才能把改造后的现有页面称为阶段性可用。
|
||||
- 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,才能声明阶段页面产物可直接部署。
|
||||
|
||||
- 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 独立闭合。
|
||||
|
||||
- D-426c3/ADR-0528(源码候选,等待 exact 双架构阶段实物):在 D-426c2 的三阶段回滚链上保留 `apply-rollback`,新增显式 `apply-plan` 与 `complete`。完成型 CI 使用完整 2.x schema、空 Apps/Auths、无未知插件表的独立 fixture;外部 completion review 对 blocked 事实直接拒绝,对 Legacy/Target Run History 分别授权 `retain_both/retain_target`,对 Secret/Config 只授权 `manual_external`。`apply-plan` 消费互相独立的 Automation/review decision,依次完成 Automation apply/verify、双侧终态 Run History preservation/verify、Secret/Config plan/verify 和 decision prepare,停在 `secret_config_decision_required`;`complete` 再消费独立 Secret/Config decision,完成 decision/apply/verify,并以 completion v3 同时绑定三类 adapter,要求 `reconciliation_completed`、`adapterCount=3`。Run History 必须位于 Automation apply 与会推进 head 的 Secret/Config plan 之间。completion 后 target/Legacy 仍 stopped,两个 restart 都是 `not_authorized`。针对 readiness 要求 Apps/Auths 必须存在而旧诊断又无条件阻塞 identity 域的矛盾,仅把“Legacy 已知 identity 表全部为空”收窄为 `informational/catalog_evidence`;任一身份行、未知表、目标 identity 或异常仍 fail-closed。Trial Kit/verification/auditor 升为 `@v11/@v9/@v8`、manifest schemaVersion 12,Local milestone 升为 `@v7`/schemaVersion 7,并新增 required `legacyUpgradeReconciliationCompletion=passed`;CI 仍独立保留 Automation apply→rollback 实证,completion 不覆盖 recovery 证据。本切片不增加 package、production dependency、daemon/listener/timer/watcher/连接或稳态资源,默认低配 headless 与 Cluster authority 边界不变。
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# ADR-0529:有界只读 Local 旧面板 Cron Adapter
|
||||
|
||||
- 状态:Proposed(源码候选,尚未进入双架构阶段实物)
|
||||
- 状态:Accepted(D-427 双架构阶段实物已交付)
|
||||
- 日期:2026-09-02
|
||||
- 关联 RFC:QL-RFC-0001 D-427、D-423、D-424、D-426c3
|
||||
|
||||
@@ -25,7 +25,7 @@ QingLong 2.x 面板以 `/api/crons`、数值型 Cron 行和 `{code,data}` 包络
|
||||
|
||||
- 接受旧页面初始读取所需的 `page`、`size`、空 `searchValue`、空 `filters={}` 和 Axios cache-buster `t`。
|
||||
- 非空搜索、排序、View query 或其他字段暂时返回 `400 invalid_panel_cron_list_query`,不能静默忽略并给出错误结果。
|
||||
- `size` 最大 64;`page * size` 在 Edge 最大 64、Standalone 最大 256。Adapter 用同一上限向 Trigger source 做一次有界 keyset 前缀读取,再截取所需页。
|
||||
- `size` 最大 64;页起点 `(page - 1) * size` 必须小于 Edge 64、Standalone 256 行预算。Adapter 以 `min(page * size, maximumRows)` 向 Trigger source 做一次有界 keyset 前缀读取,再截取所需页,因此最后一个不足整页的窗口仍可到达,但不能越过 Profile 上限。
|
||||
- `total` 是当前已观察前缀加一个 `truncated` 继续标记;它足以让旧分页逐页推进,但不执行无界 COUNT 或全表扫描。
|
||||
|
||||
### 领域映射
|
||||
@@ -48,7 +48,7 @@ QingLong 2.x 面板以 `/api/crons`、数值型 Cron 行和 `{code,data}` 包络
|
||||
|
||||
## 验证与后续门禁
|
||||
|
||||
源码候选必须通过:
|
||||
本切片通过:
|
||||
|
||||
1. Adapter 单测:分页、禁用合成、pinned identity、未知 schema、预算和 storage failure;
|
||||
2. HTTP 契约:编码的 `{}` 查询、正式 operation 解析、拒绝非空搜索且不进入 Admission;
|
||||
@@ -56,4 +56,6 @@ QingLong 2.x 面板以 `/api/crons`、数值型 Cron 行和 `{code,data}` 包络
|
||||
4. 真实 SQLite 集成:正式 credential、Policy、Task/Trigger revision 和 durable audit,且响应不出现真实 argv;
|
||||
5. Local API 全包、18-package build/test、dependency/import、Console/Headless image 与双架构 artifact 门。
|
||||
|
||||
后续按 `health/system/user capability → Run/Log read → 显式写操作` 推进。只有改造版面板取消 Local Storage credential、按 capability 隐藏未实现页面,并完成真实浏览器 journey 后,才能声明“现有面板页面可复用”;完整 2.x 零改兼容不作为 3.0 目标。
|
||||
提交 `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 静态面板。
|
||||
|
||||
后续按 `health/system/user capability → Run/Log read → 显式写操作` 推进。ADR-0530 已完成 capability/bootstrap 与旧面板源码的内存凭据、菜单降级、只读 Crontab 适配;仍须完成同源静态资源装配和真实浏览器 journey,才能把该页面作为可下载阶段产物交付。完整 2.x 零改兼容不作为 3.0 目标。
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# ADR-0530:有界 Local 面板能力发现与启动适配
|
||||
|
||||
- 状态:Proposed(D-428 源码候选,等待可下载同源装配与双架构实物门)
|
||||
- 日期:2026-09-02
|
||||
- 关联 RFC:QL-RFC-0001 D-428、D-427、D-423、D-424
|
||||
|
||||
## 背景
|
||||
|
||||
ADR-0529 已交付认证后的只读 `/api/crons` Adapter,但现有 2.x 面板启动时还会读取 `/api/system`、`/api/system/config`、`/api/user`,并假设用户名/密码登录、Local Storage JWT、完整菜单和 WebSocket 可用。仅有 Cron API 时,页面仍不能安全接入;若伪造完整 2.x 能力,则会把尚未实现的写操作、Env、Script、Subscription 和日志入口暴露给用户。
|
||||
|
||||
因此第二切片必须先让页面明确发现“这是 QingLong 3.0、当前 Profile 有哪些能力”,再只启用已闭合的页面和认证方式。兼容层继续是翻译边界,不恢复旧 Express Service、JWT authority 或数据库直写。
|
||||
|
||||
## 决策
|
||||
|
||||
### 能力与启动契约
|
||||
|
||||
- Local API 新增公开只读 `GET /api/health`、`GET /api/system`、`GET /api/v3/capabilities`。它们只接受无 body 的 exact path 与可选单个数字 `t`,仅返回版本、Local Profile、认证种类、能力开关和有界预算,不返回 principal、credential、Project 数据或存储路径。
|
||||
- `GET /api/user` 与 `GET /api/system/config` 继续走正式 Bearer authentication、`task.read` Policy、durable audit 和 credential reconfirm;operation 固定为 `panel.user.get` 与 `panel.system.config.get`,且面板身份只接受 User principal,service credential 失败关闭。
|
||||
- capability schema 固定为 v1。Edge 最多暴露 64 条 Cron、16 KiB 日志块;Standalone 最多 256 条 Cron、32 KiB 日志块;单页最多 64 条。Cluster 不复用该 Local capability shell,后续由独立 Panel Gateway 发布其能力。
|
||||
- 明确声明 `legacyLogin=false`、`legacyMutations=false`、`subscriptions=false`、`scripts=false`、`environmentVariables=false`、`webSocket=false`。现有 v3 Task/Trigger/Run/Log 读 API 可以存在,但本切片的旧页面只启用 Crontab 只读投影。
|
||||
|
||||
### 现有面板源码降级
|
||||
|
||||
- 面板在登录页同源读取 `/api/v3/capabilities`;只有严格匹配 v1 契约才进入 QingLong 3.0 模式,否则保持 2.x 行为。
|
||||
- QingLong 3.0 模式只接受 `ql3c_` API Credential。凭据只保存在当前 JavaScript 模块内存,通过 Authorization Bearer 发送;不写 Local Storage、Cookie、IndexedDB 或 URL,刷新和关闭页面后必须重新输入。
|
||||
- 成功读取 `/api/user` 后进入 `/crontab`。菜单只保留登录、错误页和定时任务;不建立 WebSocket,不请求 Cron View、Subscription 或非空搜索/排序。
|
||||
- Crontab 只展示名称、命令描述符、状态和计划;隐藏创建、选择、批量操作、详情、脚本跳转、日志和全部写 Modal。分页被 capability budget 限制,最后一个不足整页的 Edge/Standalone 窗口仍可读取。
|
||||
- 2.x 模式的数据流、Local Storage token、登录接口、菜单和页面行为保持不变。
|
||||
|
||||
## 部署与资源边界
|
||||
|
||||
- 默认 headless 产物不包含 `@qinglong/local-api` 或旧面板,不新增端口、连接、timer、watcher、后台进程或稳态内存。
|
||||
- 当前约 33 MiB 的旧面板源码构建结果不自动塞入 headless/Console Alpha;同源静态资源装配与体积预算必须作为独立门完成。
|
||||
- 旧 Umi 前端暂用 Node 20 构建只是 legacy migration toolchain,不改变 QingLong 3.0 Node 24 runtime、双架构镜像或支持等级。该过渡门必须在 CI 中独立命名,不能让 Node 20 定义新 package 的运行时兼容性。
|
||||
- Edge 与 Standalone 使用同一代码、不同预算;Cluster 节点不加载 Local SQLite/POSIX authority,也不通过本 Adapter 访问控制面。
|
||||
|
||||
## 验证与剩余门禁
|
||||
|
||||
源码候选已通过 Local API 12-package closure build、89/89 测试、真实 SQLite/credential/Policy/audit HTTP 集成、Node 20 的旧面板 production build、18-package 完整测试与 package/import/dependency audit。Playwright 同源源码旅程也已验证 capability 登录页、内存 credential、只读 Crontab、隐藏写入口与排序/过滤,以及刷新后回到登录页;最终页为 0 console error,仅保留既有国际化 warning。远端 CI 和可下载实物仍待闭合。
|
||||
|
||||
仍未完成:
|
||||
|
||||
1. 在一个可下载 Console 产物中同源装配改造后的面板静态资源,并证明 CSP、缓存和 API 路由优先级;
|
||||
2. 在装配后的 exact Console + Local API + SQLite 上使用真实 `ql3c_` credential 重跑登录 → `/crontab` → 分页 → 401/刷新清凭据的浏览器 journey;
|
||||
3. 为旧页面增加 Run/Log 只读 adapter 后再开放日志入口;
|
||||
4. 双架构资源与 artifact gate,以及对面板体积的可解释预算;
|
||||
5. 写操作必须逐项映射到 3.0 revision、Policy、presence/approval、audit 和 mutation fence,不能用通配兼容路由一次性开放。
|
||||
|
||||
在上述门禁完成前,本 ADR 只说明“现有面板源码能受控接入”,不声明当前已发布 Console artifact 包含该页面,也不声明 2.x 面板可以零修改直连。
|
||||
+2
-1
@@ -532,7 +532,8 @@
|
||||
| [ADR-0526](./ADR-0526-exact-post-write-reconciliation-capture.md) | Exact 写后 Reconciliation Capture | Accepted(同源 exact Console 双架构阶段实物已交付) |
|
||||
| [ADR-0527](./ADR-0527-reviewed-automation-reconciliation-application-and-rollback.md) | 受审核 Automation Reconciliation 应用与显式回滚 | Accepted(exact headless 双架构阶段实物已交付) |
|
||||
| [ADR-0528](./ADR-0528-cross-domain-reconciliation-completion-rehearsal.md) | 跨域 Reconciliation Completion 演练 | Accepted(D-426c3 源码候选;双架构阶段实物待 gate) |
|
||||
| [ADR-0529](./ADR-0529-bounded-read-only-local-panel-cron-adapter.md) | 有界只读 Local 旧面板 Cron Adapter | Proposed(D-427 源码候选;双架构阶段实物待 gate) |
|
||||
| [ADR-0529](./ADR-0529-bounded-read-only-local-panel-cron-adapter.md) | 有界只读 Local 旧面板 Cron Adapter | Accepted(D-427 双架构阶段实物已交付) |
|
||||
| [ADR-0530](./ADR-0530-bounded-local-panel-capability-bootstrap.md) | 有界 Local 面板能力发现与启动适配 | Proposed(D-428 源码候选;可下载同源装配与双架构实物待 gate) |
|
||||
|
||||
## 规则
|
||||
|
||||
|
||||
Reference in New Issue
Block a user