Files
qinglong/docs/adr/ADR-0225-postgresql-serializable-plugin-package-workflow-admission.md
T

89 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-0225PostgreSQL Serializable Plugin Package Workflow 准入
- 状态:Proposed
- 日期:2026-07-30
- 关联 RFCQL-RFC-0001 D-03、D-12、D-144、D-207、D-212
- 关联 ADRADR-0156、ADR-0158、ADR-0222、ADR-0223、ADR-0224
## 背景
SQLite v41 已证明 generation-bound Workflow plan 可以在一个 `BEGIN IMMEDIATE`
事务中原子展开。Cluster 不能简单把这个实现翻译成若干 PostgreSQL autocommit
automation start guard 中的 publisher signer advisory lock、publication/install/
lifecycle 行锁、quarantine/revocation absence 判断,以及 Run/StepRun 写入必须属于同一
transaction。否则安全事实仍可能穿越检查与提交。
跨方言审计还发现 runtime admission 原先生成约 64 字节 RunEvent ID,而 PostgreSQL
`run_events.id``varchar(36)`plan 的 Run ID 也曾允许 128 字节。公共契约现已
收紧为最多 36 字节 Run ID,并生成最多 36 字节 admission/Step RunEvent ID
StepRun/mutation identity 继续允许 128 字节。这样无需扩大既有 Run 外键闭包。
## 决策
### 1. 使用同一 SERIALIZABLE transaction
Cluster adapter 必须在一个专用 connection 上执行:
1. `BEGIN ISOLATION LEVEL SERIALIZABLE`
2. durable exact replay lookup
3. 调用既有 `plugin_package_automation_start_allowed`
4. 在事务内复验 exact publication Workflow 与 materialized Task source digest
5. 原子写 Run、全部 StepRun、RunEvent、StepRunMutation、admission/step ledger
6. `COMMIT`serialization failure 作为可安全重试的 unavailable,不在内部无界重试。
现有 start guard 取得的 `pg_advisory_xact_lock``FOR SHARE` 锁会一直保持到该
transaction 结束。`SERIALIZABLE` 的 predicate conflict 负责拒绝 guard 后插入的
quarantine/revocation 等 phantom;不能降为默认 Read Committed。
### 2. runtime 只获得窄表权限
`pg-0045` 只向 `ql3_runtime` 授予 admission 两表的 `SELECT, INSERT`,以及既有
Run/StepRun execution 写权限;不向 runtime 开放 quarantine、publisher receipt 或
lifecycle mutation。manager、package-manager、package-executor、worker-ingress 不得
写 admission ledger。
### 3. exact replay 先于 current guard
与 SQLite 相同,已提交 exact plan 必须返回原 receipt,即使 Package 后来 withdrawn
或 quarantined。新的 plan 才检查 current guard。相同 planId/runId/receipt/StepRun/
event/mutation identity 绑定不同内容时 conflictCOMMIT response loss 只能 inspect
durable winner。
admission ledger 对 runtime 是 append-only(仅 `SELECT, INSERT`);重放读取不得使用
`FOR UPDATE/FOR SHARE`,否则 PostgreSQL 会要求 `UPDATE` 权限。并发竞争由
`SERIALIZABLE`、唯一约束和事务级 start guard fence 收敛,不为不可变行扩大权限。
### 4. 不在事务内执行外部副作用
admission 只展开 durable DAG,不创建 Attempt、不 claim Worker、不调用 Executor。
后续 caller-driven frontier 在新事务中推进 ready Step,避免长事务、连接占用和锁
等待随 Task 执行时间增长。
## 接受门
1. `pg-0045` schema、capability、checksum、权限与 readiness
2. mocked repository contract 与真实 PostgreSQL exact replay/collision/guard/
serialization rollback
3. runtime 角色可准入但不能直接读取安全 receipt 或调用管理 mutation
4. PostgreSQL 18 physical streaming HA 下 admission ledger、Run/StepRun 和 receipt
`remote_apply`、promotion、旧主 fencing、`pg_rewind`、fresh replicas 保持;
5. 无 image pull 的 HA 重跑,且不新增 package、依赖、daemon/timer/watcher。
## 当前验证
1. `pg-0045` 已把 control-core 推进至 v44,并增加两张 admission ledger、受审
snapshot function、显式约束/索引、Drizzle schema、manifest/checksum 与六角色
readiness
2. PostgreSQL repository 使用同一 connection 的 `SERIALIZABLE` transaction,完整
durable evidence exact replay 优先于 mutable guardmock 与 package 全量为
217 pass、1 条无测试 URL 条件 skip
3. runtime 对新表只有 `SELECT, INSERT`,真实故障注入进一步证明 replay 读取不能使用
`FOR SHARE`manager/admin/package-executor/worker-ingress 无该 authority
4. PostgreSQL 18.4 arm64 physical HA 在
`QL3_HA_SKIP_IMAGE_PULL=true` 下完整通过:admission、2 个 StepRun、Event/mutation
与 receipt 经 `remote_apply`、timeline 1→2、旧主 fencing、promotion、
`pg_rewind` 和 fresh replicas 保持;
5. Workflow admission 的 atomic、exact replay、publisher revocation fence、
runtime-only 与 survives-promotion 五项 gate 以及总 `passed` 均为 true
6. 后续 frontier 边界见 ADR-0226。