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,91 @@
# ADR-0147PostgreSQL 持久 Plugin Package 身份 keyset ledger
- 状态:Accepted
- 日期:2026-07-25
- 关联:ADR-0144、ADR-0145、ADR-0146、QL-RFC-0001 D-142/D-143
## 背景
ADR-0145 的文件式 keyset 已能在单进程生命周期内拒绝 generation 回退、同代
rewrite、隐式 key 移除和 revocation 撤销。但全部管理 Pod 同时重启后,进程内
monotonic state 会丢失;若部署投影回退到旧 Secret,旧签名 key 可能重新被接受。
不能用 watcher、timer、Redis 或 Pod 本地持久卷补这个缺口:它们分别引入额外常驻
资源、第二事实源或副本不一致,并不能与现有 PostgreSQL HA 故障域共同收敛。
## 决策
### 1. 单一持久 trust ledger
`pg-0024-plugin-package-identity-keyset-ledger` 新增
`ql3.plugin_package_identity_keyset_ledger`,固定只有
`plugin-package-management` 一个 authority。行内保存:
- generation 与完整 keyset SHA-256 base64url digest
- immutable issuer/audience
- 最多 8 个 active key ID
- 最多 64 个 append-only revoked key ID
- 数据库时钟更新时间。
migration stream 推进至 24 条、`control-core` capability v23、37 张表,并新增
`plugin_package_identity_keyset_ledger:1`
### 2. 原子单调推进
`PostgresPluginPackageIdentityKeysetLedgerRepository.observe()` 使用同一
package-manager 连接池的短事务:
1. `INSERT ... ON CONFLICT DO NOTHING` 竞争首次建账;
2. `SELECT ... FOR UPDATE` 串行化同一 authority
3. 同 generation 只接受 digest、trust domain、active/revoked 集合完全一致的重放;
4. 新 generation 必须保持 issuer/audience 不变;
5. 历史 revoked key 必须全部保留;
6. 历史 active key 必须仍 active,或显式进入 revoked
7. 通过后才以数据库时钟更新并提交。
COMMIT 响应丢失统一返回 unavailable;调用方以同一 snapshot 重试会读取已提交行并
精确收敛,不产生新 generation。
### 3. 认证路径复核
生产 management process 先完成 package-manager schema/role readiness,再创建带
PostgreSQL ledger 的 keyset file provider。首次启动、文件发生变化和文件 digest
未变化的每次认证 reload 都必须调用 ledger
- 新副本拿到旧文件时在监听前失败关闭;
- 已运行副本在 ledger 被另一副本推进后,不得继续把旧进程内 verifier 当持久事实;
- 文件损坏、数据库不可用、ledger conflict 均映射为 keyset unavailable,不使用
stale fallback。
基础 file provider 保留可选 ledger port,供纯单元测试或非生产组合使用;正式
cluster process 永远注入 PostgreSQL 实现。
### 4. 权限和资源边界
- 只有 `ql3_package_manager``SELECT/INSERT/UPDATE` ledger
- runtime、admin、package-executor、worker-ingress 与 PUBLIC 均无权限;
- 不新增 workspace package、第三方依赖、Redis、timer、watcher 或后台清理;
- edge/standalone 不导入该 repository,仍保持零额外常驻成本;
- 表恒定一行,revocation 列表与 JSON 字节数均有硬上限。
## 验证
- cluster-postgres 全量 141/141
- cluster-admin 全量 97 通过、1 个真实 Kubernetes API 条件跳过;
- PostgreSQL 18.4 arm64 physical HA 报告新增
`durableIdentityKeysetLedgerSurvivesReplicaRestart`
- 两个独立 package-manager 实例并发观察同一 generation
- 新 repository 实例模拟全副本重启,旧 generation 被拒绝;
- 同代 rewrite、隐式移除和 trust-domain 漂移被拒绝;
- driver 已确认 COMMIT 后注入响应丢失,再次观察精确收敛到 generation 3
- ledger 与既有 quota、physical promotion、`remote_apply`、旧主 fencing/rewind
一起通过 24 个具体 gate 和总 `passed`
## 后续非本 ADR 范围
本 ADR 关闭“全副本重启后的 durable keyset anti-rollback”阻断项,但不自动开放公网
管理入口。真实 IdP 两名 User 四眼、双 Pod live NetworkPolicy/ingress、Secret 投影
传播窗口、TLS/keyset 自动轮换和真实 Kubernetes control-plane HA 证据仍是生产前置。
ADR-0148 已冻结这些真实环境事实的低敏 evidence schema,并默认拒绝 management
公网 egress;它不把“审计器存在”当作真实报告已经取得。