Files
qinglong/docs/adr/ADR-0270-authenticated-local-plugin-package-workflow-product-entry.md
T

5.3 KiB
Raw Blame History

ADR-0270:受认证的本机 Plugin Package Workflow 产品入口

  • 状态:Accepted
  • 日期:2026-08-04
  • 关联 RFCQL-RFC-0001 D-08、D-09、D-12、D-70、D-212、D-213、D-250、D-251
  • 关联 ADRADR-0223、ADR-0227、ADR-0228、ADR-0229、ADR-0269

背景

QingLong 3.0 已完成 Plugin Package Workflow 的 immutable plan、双方言 admission、frontier、 Task Attempt、执行、恢复、整体取消、唯一 scheduler cadence 和低资源门。但是本机产品只有 Package 安装/发布与 application runtime,没有受认证的 operator 入口来发现和启动已发布 Workflow。测试夹具能 直接调用 repository 不等于部署用户具备可用产品链。

如果 CLI 接受完整 publication、materialized revision 或 plan,调用者会取得本应由服务端权威派生的 generation/digest 字段;如果先做 Policy 检查再在另一个事务 admissioncredential revoke、RoleBinding 变化或 Project archive 可以穿过 TOCTOU 窗口。

决策

1. 在既有 Owner CLI 增加 ql3-workflow

命令只读取当前 UID 的私有 0600 command file,提供:

  • workflow.inspect:使用 run.read,只返回当前 Package automation publication 的 Workflow 名称、 enabled 状态、Step key、Task key 与依赖;
  • workflow.start:使用 run.start,只接受 Project、Package、Workflow 与 caller-owned planId/runId/stepRunIds。publication、generation、revision、Task definition ref/digest 和完整 plan 全部由当前 durable authority 派生。

Owner、Admin、Operator 可按现有 role matrix 启动;Viewer 只有 inspect 权限。两种操作都要求稳定强 User 与当前 credential。命令输出不含数据库路径、credential、Package digest、plan digest、Task spec 或业务参数。

2. 授权与 admission 必须原子提交

workflow.start 在现有 SQLite BEGIN IMMEDIATE 内重新验证:

  1. credential version、pepper binding、状态和有效期;
  2. active Project 与 exact Project/RoleBinding version fence
  3. allowed workflow.start security audit identity
  4. current active install/lifecycle/quarantine/publication/materialized revision/Workflow/Task evidence
  5. immutable Workflow Run、全部 StepRun、Event、mutation 与 admission receipt。

任一项失败回滚全部事实。底层通用 admission repository 保留原单参数接口,只增加可选的事务内 guard application scheduler 与既有 repository caller 不取得管理 authority。

3. 重放绑定 caller-owned identity

首次 start 使用 command 中的 UUID v4 planIdrunId 与每个 Step 的 stepRunId。结果未知时必须原样 重放同一 command filerepository 先读取 durable plan,逐项比较 Project/Package/Workflow/Run/Step identity,再返回 existing,不能读取 current head 后重新生成另一 plan,也不能产生第二个 Run。

4. 不增加低配常驻成本

能力位于既有 runtime-corelocal-sqlitelocal-adminlocal-owner-cli 显式 subpath。workspace 保持 19,不增加 migration、表、第三方 dependency、连接、daemon、listener、timer 或 watcher。 ql3-workflow 只在 operator 调用时短生命周期加载;实际执行继续由 application 已有唯一 scheduler cadence 接管。

替代方案

  • 让用户提交完整 execution plan:拒绝。会把 publication/generation/Task digest authority 交给调用者。
  • CLI 先授权、随后直接调用普通 admission:拒绝。Role/credential revoke 可穿过事务边界。
  • 为 Workflow API 新建 daemon 或 workspace package:拒绝。本机已有安全 console、Policy、SQLite 和 scheduler authority,新增常驻面只会扩大路由器资源与供应链成本。
  • CLI admission 后同步等待 Workflow 完成:拒绝。长连接会把 CLI 生命周期混入 durable scheduler, 也会在终端断开时产生错误取消语义。

验证

  • Owner CLI 93/93
  • Runtime Core 431/431,其中新增授权契约直接证明 exact-shape、allowed audit/fence 绑定与 subpath-only
  • Local SQLite 192/192
  • Local Admin 83/83
  • 真实 edge SQLite 产品测试证明 inspect、created→existing 三次重放、1 Run、2 StepRun、1 start audit
  • Viewer start 被 permission_missing 拒绝且保持 0 Run
  • transaction guard 的新建、重放与拒绝回滚门通过;
  • 精确依赖边界 45/45、全仓 dependency/package-boundary/local-image audit 均为 findings=[]workspace 仍为 19
  • 完整 19-package 门退出 0;后端总回归为 1,094 pass/2 条件 skip/0 fail
  • 十档 Edge/Standalone、Adopted、Application 与 AI artifact 全部 compatible=true:最小 Edge 为 3,506,692 bytes/324 files/10,780,672 bytes RSS,最大组合 Standalone Application AI 为 5,874,007 bytes/474 files/20,496,384 bytes RSS,均未放宽预算;
  • PostgreSQL 18.4 arm64 physical HA 回归 gates.passed=true,覆盖 remote_apply、timeline 1→2、旧主 fencing、pg_rewind 只读重入和两个 fresh control replicas;本轮隔离的 ql3-ha-* container/volume/network 均零残留。

影响

Plugin Package Workflow 第一次具有部署用户可调用的本机产品入口。它只负责安全 admission,不替代 application、scheduler、Worker 或 Executor。远程 Cluster transport、UI/MCP 入口和固定物理设备断电/ ENOSPC 证据仍是独立后续门。