4.2 KiB
ADR-0147:PostgreSQL 持久 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 连接池的短事务:
INSERT ... ON CONFLICT DO NOTHING竞争首次建账;SELECT ... FOR UPDATE串行化同一 authority;- 同 generation 只接受 digest、trust domain、active/revoked 集合完全一致的重放;
- 新 generation 必须保持 issuer/audience 不变;
- 历史 revoked key 必须全部保留;
- 历史 active key 必须仍 active,或显式进入 revoked;
- 通过后才以数据库时钟更新并提交。
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/UPDATEledger; - 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;它不把“审计器存在”当作真实报告已经取得。