mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 08:05:22 +08:00
7.6 KiB
7.6 KiB
ADR-0286:有界且受认证的 Package-bound Workflow Run 历史列表
- 状态:Accepted
- 日期:2026-08-07
- 关联:D-85、D-87、D-213、D-257、ADR-0046、ADR-0047、ADR-0048、ADR-0049、ADR-0267、ADR-0270、ADR-0271、ADR-0276、ADR-0282、ADR-0283、ADR-0284、ADR-0285
上下文
ADR-0282 已能按已知 Run ID 查询单个 Package-bound Workflow Run,ADR-0284/0285 能继续读取其 StepRun 与 RunEvent,但产品调用者仍无法回答“这个 Package 的这个 Workflow 最近运行过哪些 Run”。要求调用者预先保存 Run ID 会让 Run 详情能力不可发现;复用通用 Run 列表又无法证明 Package/Workflow admission 归属,并可能暴露 Task、Attempt、plan、错误、Artifact、Secret、lease 或 executor 信息。
Local 路由设备与 Cluster 节点必须共享同一低敏、稳定、有界的发现协议。列表不能执行无界 count,不能引入缓存、 轮询、后台索引器或新服务;授权、目标绑定、读取与 allowed audit 必须保持一个数据库事务。并发 admission 要求 分页在相同排序键下不重复、不回退。
决策
- 新增共享 schema
qinglong/plugin-package-workflow-run-list@v1,产品操作固定为workflow.run.list,权限 固定为run.read。Local Owner CLI 在既有ql3-workflow协议增加该操作;Cluster 增加GET /api/v3/projects/{projectId}/packages/{packageName}/workflows/{workflowId}/runs。 - 默认页大小 32、最大 64。排序固定为
(admittedAtMs DESC, runId DESC);cursor 必须同时包含 canonical non-negativeafter_admitted_at_ms与after_run_id,两半缺一、非 canonical 数字或无效 ID 都在存储前拒绝。 adapter 只读取limit + 1,不执行COUNT(*)。 - item 只允许
runId、status、version、eventSequence、stepCount、admittedAtMs、queuedAtMs、startedAtMs、finishedAtMs、cancelRequestedAtMs与cancelReason。plan/receipt/definition digest、Task、 StepRun、Attempt、payload、input/output、错误、Secret、Artifact、lease 与 executor 全部排除。 - 结果必须严格 newest-first、Run ID 唯一;
truncated=true时next必须精确等于本页末项位置,terminal page 必须为next=null。cursor 后每一项都必须严格更旧,禁止客户端重排、offset 或隐式时间窗口。 - SQLite 在同一
BEGIN IMMEDIATE内重验 credential、active Project exact version 与 latest active RoleBinding exact version,以 admission/Run join 精确绑定 Project、Package、Workflow,执行有界查询并提交 allowed audit;相同 audit ID 只允许语义完全相同的 replay。 - PostgreSQL adapter 使用同一 serializable transaction 重验 current credential/identity、Project 与最新 RoleBinding,执行相同 join/keyset 查询,再用 runtime role 的 INSERT-only authority 追加 audit。HTTP 每次请求 生成新的 UUID v4 audit ID;任何冲突或非 canonical 输入 fail-closed。
- 空集合始终返回成功空页,Cluster HTTP 为 200;这包括真实无运行记录和 cross-target Package/Workflow,避免用 列表响应枚举目标存在性。授权 fence 漂移返回 409,非法 query/GET body 返回 400,其余数据库或一致性失败 返回 503。
- SQLite migration
0085-plugin-package-workflow-run-list-index与 PostgreSQL migrationpg-0053-plugin-package-workflow-run-list-index都增加(project_id, package_name, workflow_id, admitted_at_ms, run_id)索引。Local capability 升至 v43/86 migrations, PostgreSQLcontrol-core升至 v52/53 migrations;旧 schema 必须由 readiness 拒绝,不能退化为全表扫描。 - 本增量不增加 workspace package、生产 dependency、表、Pool、timer、listener、watcher、cache、状态机或部署 单元。能力进入既有 runtime-core、local-sqlite/local-admin/local-owner-cli 与 cluster-postgres/ cluster-control owner。
- package 内部源码布局与 package 边界分别治理:workspace 保持 19 个 package;共享协议实现不得再借
shared_protocol全平铺,根层只保留公开入口。全 workspace 当前无 single-source package,只有local-profile与local-adopted-profile两组纯公开 Profile entrypoint 浅层例外。
被拒绝的方案
- 要求调用者保存 Run ID:详情可读但不可发现,不构成可用产品面。
- 复用通用 Run 列表或返回完整 Run aggregate:无法证明 Package/Workflow admission 归属,并扩大低敏读取权限。
- 把 StepRun、RunEvent 或错误摘要嵌入列表:页面成本随执行规模增长,破坏列表的固定字段与资源上限。
- offset、单独时间戳 cursor 或客户端排序:并发 admission 下会重复、遗漏或产生不确定同时间排序。
- 先查目标存在性再查列表:增加竞态和目标枚举侧信道;空集合统一 200 更安全。
- 依赖旧索引或允许 readiness 降级:Package/Workflow 数量增长后会扫描不相关 admissions,不适合路由设备或 多租户 Cluster。
- 为列表新建 package、projection 表、缓存或服务:当前 admission 表和精确复合索引已经满足 bounded read, 没有新的部署、权限或依赖隔离价值。
接受证据
- Runtime Core、Local SQLite/Admin/Owner CLI、Cluster PostgreSQL/Control 覆盖严格输入、字段白名单、newest-first keyset、空页 anti-enumeration、cross-target 遮蔽、授权 fence、同事务 audit 与 HTTP 400/409/503 映射。
- 完整 19-package clean build/test 退出 0;Cluster PostgreSQL 285 pass/1 条件 skip、Local Owner CLI 101/101。 backend 1,110 tests 为 1,108 pass/2 skip/0 fail。
- Edge import、cluster dependency、package boundary schema v2、cluster deployment、CloudNativePG 与 local image
六项审计全部 compatible;package ledger 为 19/19、
singleSourcePackages=[]、两个纯入口 shallow package、findings=[]。 - 十档本机制品全部 compatible。最小 Edge/Standalone 为 3,614,826/3,614,874 bytes;最大 Standalone Application AI 为 6,049,841 bytes,距 6 MiB 上限 241,615 bytes,RSS 在对应 16/24 MiB 门内。
- PostgreSQL 18.4 arm64 physical-streaming HA
gates.passed=true;pluginPackageWorkflowRunListCommitsAtomically、MasksCrossTarget、SurvivesPromotion三项 gate 全绿。 promotion 后同一有界页面验证严格 newest-first 并定位目标 succeeded Run;timeline 1→2,旧主先 fencing,pg_rewind后只读同步 rejoin,两个 fresh control replica ready,结束后ql3-ha-*container/network/volume 零残留。 - 强制刷新后的 GitNexus 为 42,809 nodes/97,469 edges/1,674 clusters/261 flows。共享两个 Run-list
normalizer 为 LOW/0 impacted,SQLite/PostgreSQL repository 各为 LOW、1 direct/0 affected process;HA 主库与
promotion 验证函数均为 LOW、1 direct,只命中受审 Docker HA 流程。
detect_changesall/comparedevelop分别为 12 files/31 symbols 与 14/34,均 low/0 affected process;QL3 孵化树仍大部分 untracked,因此该 统计只作补充,不能替代逐符号 impact、完整测试、制品和真实 HA 证据。
后续边界
- Run 详情、StepRun、RunEvent、Artifact、错误诊断和日志继续使用独立 schema/permission,不能扩宽本列表。
- 若需要时间范围、状态筛选或实时订阅,必须分别证明索引、cursor、anti-enumeration、连接/背压和 Edge 资源预算; 本 ADR 只授权一次性 Package/Workflow 精确目标下的 newest-first 有界查询。
- 新增列表类能力优先使用既有 owner 的领域 subpath;文件数或概念名不能成为第 20 个 workspace package 的理由。