mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
82 lines
6.1 KiB
Markdown
82 lines
6.1 KiB
Markdown
# ADR-0277:本机 Plugin Package Workflow 取消产品入口
|
||
|
||
- 状态:Accepted
|
||
- 日期:2026-08-07
|
||
- 关联:D-207、D-212、D-213、D-251、D-257、ADR-0228、ADR-0270、ADR-0276
|
||
|
||
## 上下文
|
||
|
||
本机 Plugin Package Workflow 已经具备 generation-bound plan、原子 admission、StepRun-aware Task
|
||
执行、application 单 cadence 和整条 Workflow cancellation convergence。`ql3-workflow` 也已经开放
|
||
`workflow.inspect` 与 `workflow.start`。但产品用户仍无法请求取消:现有测试只能直接更新 `Runs` 的
|
||
`cancel_requested_at_ms/cancel_reason`,这会绕过 credential、Project Policy、RoleBinding fence、
|
||
durable audit 与幂等命令协议。
|
||
|
||
底层“知道如何安全收敛”而产品面“只能直写 SQL”不是可用闭环。另一方面,取消请求只表示停止意图,
|
||
不能把 leased/starting/running Attempt 或 running StepRun 直接改成 terminal;它们仍必须由 Worker
|
||
completion、可信 recovery 或本机执行控制链收敛。
|
||
|
||
实现该入口时,撤权测试还暴露出既有 Project Policy latest-head 读取缺陷:RoleBinding 查询按版本倒序
|
||
后使用 `LIMIT 2`,再交给只接受零或一行的解析器。正常出现第二个 append-only 版本时,所有复用该
|
||
Repository 的入口都会把授权变化误报为 storage unavailable,而不是读取最新 binding。
|
||
|
||
## 决策
|
||
|
||
1. 既有 `ql3-workflow` private-command 产品入口增加 schema v1 的 `workflow.cancel`,不新增 CLI、
|
||
workspace package、dependency、migration、表、connection、listener、timer 或 watcher。
|
||
2. command 只携带 Project、Package、Run、mutation、RunEvent、request 与 audit identity;取消原因固定由
|
||
服务端派生为 `user`,调用者不能提交 `shutdown`、`timeout` 或其他内部 authority。
|
||
3. 必须先建立当前强 User credential,再以 `run.stop` 执行 Project Policy precheck。SQLite adapter 在
|
||
同一个 `BEGIN IMMEDIATE` 内重新验证 credential、Project version 与 latest RoleBinding exact fence,
|
||
并确认 Run 属于指定 Project/Package 的 durable Workflow admission。
|
||
4. 首次非终态请求在同一事务中更新 Run cancel intent/version/event sequence、追加
|
||
`run.cancel_requested` 和 allowed `workflow.cancel` security audit。任一写入、围栏或 identity 冲突
|
||
整体回滚。
|
||
5. 同一 command response loss 通过 audit identity、mutation dedupe、RunEvent identity/actor/payload 与
|
||
durable audit time 返回 `existing`,不重复写 Event。新的命令面对既有 intent 返回
|
||
`already_requested`;面对 terminal Run 返回 `already_terminal`。这些状态都不宣称 Workflow 已停止。
|
||
6. 输出只包含 Project/Package/Workflow/Run identity、Run status/version/event sequence 与低敏取消状态;
|
||
不输出 Policy fence、authentication、plan digest、路径、Task spec、Secret 或执行 handle。
|
||
7. `LocalSqliteRunRepository.resolveProjectPolicy` 的 latest binding 查询改为 `ORDER BY version DESC
|
||
LIMIT 1`。这恢复 append-only RoleBinding 的 head 语义,不改变角色矩阵、写入历史或 fence contract。
|
||
8. 本切片只接受 Local 产品取消入口。leased/starting/running 的在途停止仍由现有 application control、
|
||
completion/recovery 收敛;Cluster 继续使用独立 `/runs/{runId}/cancellation` 产品面和 PostgreSQL
|
||
authority,不复用 POSIX command file。
|
||
|
||
## 被拒绝的方案
|
||
|
||
- **CLI 直接更新 `Runs`**:绕过认证、Policy、审计、事务围栏和目标 Workflow 归属。
|
||
- **调用 cancel 即把 Run/StepRun 改 terminal**:伪造外部执行已经停止,允许迟到副作用越过终态。
|
||
- **为 cancellation 再拆 package**:同一 Workflow 产品、Repository 与 application closure 没有独立
|
||
部署或重依赖价值,会重新制造 D-207 已禁止的微包。
|
||
- **把 command time 当幂等语义**:响应丢失后重试时间必然变化;durable audit time 才是首次 winner,
|
||
replay 只比较稳定 command/actor/fence 语义。
|
||
- **继续使用 `LIMIT 2` 检测 RoleBinding 冲突**:append-only 历史存在两行是正常状态,不是重复 head;
|
||
唯一性由 `(project, subject, version)` 与最新版本语义保证。
|
||
|
||
## 接受证据
|
||
|
||
- Runtime Core 436/436、Local SQLite 192/192、Local Admin 83/83、Local Owner CLI 101/101;
|
||
- 真 SQLite 产品测试覆盖 `accepted`、exact `existing`、新命令 `already_requested`、单一
|
||
`run.cancel_requested`、allowed audit、低敏 CLI 输出,以及 Owner→Viewer 第二版本后的 `run.stop`
|
||
拒绝与 Run/Event 零变化;
|
||
- 完整 19-package 门退出 0,完整后端门退出 0;edge import、cluster dependency、package boundary、
|
||
cluster deployment、worker deployment、local image 六项审计全部 compatible;
|
||
- 十档 artifact 全 compatible:Edge/Standalone 3,547,572/3,547,620 bytes,Adopted
|
||
4,146,274/4,146,358,Application 4,633,643/4,633,787,AI 4,882,494/4,882,554,
|
||
Application AI 5,968,637/5,968,793;最大档距 6 MiB 仍有 322,663 bytes;
|
||
- PostgreSQL 18.4 arm64 physical-streaming HA `gates.passed=true`,`remote_apply`、timeline 1→2、
|
||
旧主 fencing、`pg_rewind` 只读同步重入、两个 fresh control replica 与既有 remote Workflow
|
||
cancellation promotion gate 全绿;`ql3-ha-*` container/network/volume 零残留。
|
||
- 刷新后 GitNexus 为 42,502 nodes/96,450 edges/1,672 clusters/261 flows;取消产品链的新增与既有
|
||
入口均为 LOW,`resolveProjectPolicy` 保持 MEDIUM、11 direct/0 affected process;`detect-changes`
|
||
all/compare `develop` 分别为 12 files/31 symbols 与 14/34,均 low/0 affected process。
|
||
|
||
## 剩余边界
|
||
|
||
- Linux `/proc` 下 running Workflow Task 的真实 stop→completion/recovery→parent terminal 门仍由既有
|
||
Local Application 条件测试覆盖,固定路由设备断电/闪存证据仍是发布门;
|
||
- 本 ADR 不新增 Cluster Workflow-specific cancel route,也不替代 Cluster 已有通用 Run cancellation、
|
||
Worker Lease control、attestation 与跨 promotion 证据;
|
||
- UI/HTTP/MCP 对本机取消的远程暴露仍需独立身份、transport、rate-limit 与存在性屏蔽评审。
|