feat(ql3): establish 3.0 incubation baseline

This commit is contained in:
whyour
2026-08-12 00:25:26 +08:00
parent 4bf92dcfeb
commit c699c32461
2817 changed files with 779642 additions and 653 deletions
@@ -0,0 +1,103 @@
# ADR-0256Owner-authenticated Local TaskDefinition Management
- 状态:Accepted
- 日期:2026-08-01
- 关联 RFCQL-RFC-0001 D-85、D-175、D-207、D-239
- 关联 ADRADR-0074、ADR-0085、ADR-0089、ADR-0091、ADR-0092、ADR-0217
## 背景
Fresh Edge/Standalone 已具备版本化 TaskDefinition、内建 `qinglong/command@v1`
语义注册表、原子 execution revision 物化、Owner credential 和 Project Policy,但产品入口
仍只能通过测试或直接 Repository 写入 TaskDefinition。部署者无法用受支持命令完成
create/update/enable/disable/inspect/list,也就无法在 fresh 安装后建立第一个可调度任务。
这个缺口不能靠向常驻 application 暴露写 Repository 解决。路由设备不应因此增加管理
daemon、第二数据库连接、timer 或新的 workspace packageCluster 也不能复用本机文件
credential 和 SQLite authority 来绕过 PostgreSQL/RBAC/多副本管理边界。
## 决策
1. 在既有 `@qinglong/local-owner-cli` 增加唯一短生命周期 binary `ql3-task`,只接受
`run --command-file /absolute/private-command.json`。command file 必须位于 deployment
root 内、由当前 UID 持有、模式 `0600`、不是 symlink;不接受参数拼装的 Task spec。
2. v1 只开放 `task.put|task.inspect|task.list``task.put`
`expectedRevision=null` 创建,以当前 revision 更新;`enabled=false|true` 分别表达
disable/enable 的新 revision,不提供 update-in-place 或 delete。
3. 写入只接受已冻结 registry 中的 Task spec;当前 production registry 仍只有
`qinglong/command@v1`。CLI 不因为 envelope 支持 `script|workflow|agent|tool` 就猜测其语义。
4. 每次命令建立短生命周期 SQLite connection,使用现有 Owner pepper/credential
authentication 和 Project Policy。create/update 分别要求 `task.create|task.update`,查询
要求 `task.read`principal 必须是 strong Userowner/admin/operator 可写,viewer 只读。
5. 写事务在同一 `BEGIN IMMEDIATE` 内重新验证 credential/Identity/pepper fence、Project
version/status、RoleBinding version/state,并原子提交 allowed audit、Task head、immutable
revision、mutation replay 与适用的 local execution revision。任何 fence、semantic、revision
或 audit replay 冲突整体回滚。
6. `mutationId` 同时是 allowed audit event ID`requestId`、actor、Policy fence、operation 和
immutable `occurredAtMs` 都属于 exact replay 语义。调用结果未知时只能原样重放 command
file。复用 mutation 但改变 Task 或 audit 语义必须失败关闭。
7. inspect/list 使用当前 head、最多 256 条的稳定 `taskId` keyset;每页使用新的
request/audit identity。输出只包含 Project/task、revision、name、kind/schema、enabled、
content digest 与时间,不回显 spec/config/command 参数、SecretRef、credential、pepper、
数据库路径或 command-file 路径。
8. 实现只增加现有 `runtime-core``local-sqlite``local-admin``local-owner-cli` 的显式
subpathworkspace 保持 19 个 package,不新增第三方或 production dependency、migration、
daemon、timer、watcher、listener、cache、Pool 或端口。Edge/Standalone 空闲成本为零,只有
operator 发起命令时产生一个短进程和一个 SQLite connection。
9. `ql3-task` 明确不支持 Cluster。Cluster TaskDefinition 管理必须后续通过 PostgreSQL 管理
repository、独立 credential/RBAC、强认证 transport、持久审计和多副本 fence 提供;不能
挂载本机 Owner credential 或把 SQLite command file 当集群管理协议。
## 失败与恢复
- 配置、路径、权限或 Task semantic 失败:修正后创建全新的 command identity
- 认证、授权或 fence 失败:恢复 credential/RoleBinding 后创建新命令,不复用已改变语义的
mutation
- revision conflict:先 inspect 当前 revision,再以新 mutation/时间提交明确更新;
- COMMIT 结果未知:保留原 `0600` command file 并逐字重放;`existing` 表示 durable semantic
已存在,不重新创建 revision;
- audit 与 Task replay 不一致:停止自动重试并人工检查,禁止直接 SQL 修补或删除历史。
## 被拒绝的替代方案
1. **新建 `task-admin` workspace package**:没有独立部署、依赖或权限域,只会让 19 包拓扑
再次碎片化,拒绝。
2. **把写入口放进常驻 local application**:扩大空闲 authority 和攻击面,也让路由设备为偶发
管理持续付费,拒绝。
3. **直接使用 SQLite/Repository 脚本**:绕过 authentication、Policy、audit、semantic registry
和 revision fence,拒绝。
4. **用 `task.enable|disable` 修改 head bool**:破坏 append-only 历史、pinned Run 解释和 exact
replay,拒绝;状态变化必须是新 revision。
5. **让 Cluster 复用本机 CLI**SQLite 单 authority 和本机 credential 不具备 PostgreSQL HA、
多副本竞争或集群 RBAC 语义,拒绝。
## 验证
- `ql3-task` 真实 SQLite 纵切面覆盖 create、exact replay、disable、inspect、keyset list、
operator allow、viewer deny、credential/Policy race rollback、Task semantic drift、audit semantic
drift、私有 command file 与低敏输出;当前 5/5
- `@qinglong/local-owner-cli` 完整 dependency closure strict TypeScript 通过;
- Owner CLI 83/83、local-admin 81/81、local-sqlite 189/189、backend 956 pass/2 条件
skip/0 fail19 个 QL3 package 清理后顺序构建并完成全量测试,所有已执行 suite 零失败;
- dependency boundary 40/40 且 repository audit `findings=[]`Edge import 与 local image
静态 inventory audit 均 compatibleGitNexus compare-to-develop 为 LOW、0 条受影响执行流;
- PostgreSQL 18.4 arm64 physical HA 同轮重新通过 `remote_apply`、timeline 1→2、旧主先
fencing、`pg_rewind` 只读同步重入、两个 fresh control replica 与全部业务 gate
`gates.passed=true`;测试容器、网络、卷零残留。此项只证明 Cluster 基线未回归,不把
本机 `ql3-task` 宣称为 Cluster 产品入口;
- 完整 package/backend/dependency/artifact 回归是合入前门禁。
D-239 验证时曾发现 storage-only 超过 512 files、adopted assembly 漏收 `local-secret`,且
application 为 741 files、约 6.40 MiB、import RSS delta 约 20.2--20.35 MiB,因此本 ADR
当时没有把 Profile gate 标记为通过。后续 ADR-0257/D-240 已通过内部运行制品裁剪、精确 adopted
闭包和 eager import 收口修复该 blocker;十档门现已全部通过。D-239 没有自行放宽预算,完整
application 的 24 MiB import delta 分层也不改变 Edge 96 MiB 总物理进程预算。
## 后续约束
后续 ADR-0258/D-241 已完成 Trigger create/update/enable/disable/inspect/list 和
Task→Trigger→Run 的可操作 fresh 用户闭环,并在 Trigger 写入、scheduler candidate 与最终 Run
commit 三处执行 Task current-head fence。下一步为 Cluster 实现 PostgreSQL/RBAC 对等管理入口。
HTTP/UI 只能调用同一服务语义,不能复制 Task/Trigger semantic、Policy、current-head fence 或
replay 规则。非 command kind 仍须各自完成 semantic、权限、编译与执行评审后才能进入
production registry。