mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
feat(ql3): add cluster legacy env migration plan ledger
This commit is contained in:
@@ -93,6 +93,33 @@
|
||||
readiness、观察窗和 rollback retention 之后另行强认证。Cluster 必须使用 PostgreSQL SERIALIZABLE ledger、外部 KMS/Secret provider 与 HA evidence,
|
||||
不复用 Local SQLite/POSIX authority,也不得把明文写入 PostgreSQL、ConfigMap、Pod env 或 Job command。
|
||||
|
||||
- D-400/ADR-0495(已验收):第十一个 Secret/Config 切片补上 Cluster Legacy Env migration 的
|
||||
**content-free plan ledger baseline**,但没有把计划冒充实际迁移。profile-neutral
|
||||
`qinglong/cluster-legacy-env-migration-plan@v1` 只保存 reconciliation bundle、reviewed
|
||||
decision、candidate set、Task/Trigger revision set 和 plan 的 SHA-256 摘要,外加守恒计数、
|
||||
同 Project 且固定 version 的 canonical SecretRef、effective bytes 与数据库时间;不保存源
|
||||
Env name/value、row body、plaintext/ciphertext、key ID、Task/Trigger spec 或 credential。
|
||||
上限固定为 100,000 source rows、100,000 Tasks、500,000 Triggers、64 KiB effective
|
||||
Secret 和 8 KiB JSON。
|
||||
|
||||
PostgreSQL `pg-0070-cluster-legacy-env-migration-plans` 将 control contract 推进到 v69,
|
||||
以 Project FK、plan/mutation/digest 唯一性和六组 named constraints 创建 append-only 表;
|
||||
`plan_json` 必须与列值重建的 canonical JSONB 精确相等,因此额外 Env 字段不能藏入 durable
|
||||
JSON。只有 `ql3_automation_manager` 拥有 `SELECT, INSERT`,无 UPDATE/DELETE;runtime、
|
||||
admin 和其余角色均无权限。repository 只从显式
|
||||
`cluster-legacy-env-migration-plan` subpath 导出,以数据库时间和短 SERIALIZABLE transaction
|
||||
完成 exact mutation replay、active Project snapshot、三次有界 serialization retry 与可选同事务
|
||||
hook;普通 SERIALIZABLE read 避免 `FOR SHARE` 隐含的 Project UPDATE 权限扩张。
|
||||
|
||||
runtime contract 4/4、repository 5/5、migration/schema/readiness/entrypoint 92/92 通过,两包
|
||||
完整测试零失败。真实 PostgreSQL 18.4 已成功应用 70 条 migration,并证明 create/replay/read、
|
||||
automation UPDATE `42501`、runtime/admin SELECT `42501`,以及 widened `envName` JSON 被精确
|
||||
constraint 以 `23514` 拒绝。该切片复用既有两个 package,未增加 dependency、daemon 或
|
||||
Edge/Standalone import。它只关闭 plan ledger baseline;Cluster source scan/signed decision
|
||||
装配、逐项 Task/Trigger current-head revalidation 与 revision mutation、Secret material custody、
|
||||
migration receipt、HA promotion replay 和固定低性能设备证据仍是后续门禁。ADR-0491 因此继续
|
||||
Proposed。
|
||||
|
||||
- D-396/ADR-0490(已验收):Run History 不再只有永久 `manual_external`,但也没有被错误实现为 Legacy 日志到 3.0 Run ledger 的回灌。
|
||||
新的 Local adapter 以 ADR-0482 sealed capture bundle 作为 append-only 保全资产:Legacy history 必须逐事实选择 `retain_both`,Target history
|
||||
必须选择 `retain_target`;receipt 只绑定 signed review、application、bundle fingerprint、领域 inventory 与有界 fact counts,不保存表名、Run ID、
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# ADR-0491:有界 Secret/Config Reconciliation 与任务环境绑定
|
||||
|
||||
- 状态:Proposed(D-397 已实现 Legacy Env inspection、私有有界 row plan、durable plan publication、独立 signed decision、逐项 Automation adoption provenance、Local SQLite 原子 application publisher、Owner prepared/apply/rollback 编排、ADR-0492 completion v3,并由 ADR-0494 完成 Cluster mounted-files provider live 子门;真实 Edge 空间证据、Cluster migration ledger 与直接外部 custody gate 尚未完成)
|
||||
- 状态:Proposed(D-397 已实现 Legacy Env inspection、私有有界 row plan、durable plan publication、独立 signed decision、逐项 Automation adoption provenance、Local SQLite 原子 application publisher、Owner prepared/apply/rollback 编排、ADR-0492 completion v3;ADR-0494 完成 Cluster mounted-files provider live 子门,ADR-0495 完成 content-free Cluster plan ledger baseline;真实 Edge 空间证据、Cluster Task/Trigger mutation/receipt、HA replay 与直接外部 custody gate 尚未完成)
|
||||
- 日期:2026-08-23
|
||||
- 决策:D-397
|
||||
- 关联:ADR-0073、ADR-0074、ADR-0092、ADR-0094、ADR-0480、ADR-0482、ADR-0483、ADR-0484、ADR-0485、ADR-0486、ADR-0487、ADR-0488、ADR-0490
|
||||
@@ -147,4 +147,4 @@ D-397 当前八切片已经实现:absent、unsupported、Edge over-budget、2.
|
||||
|
||||
ADR-0494 已完成 Cluster `mounted-files` provider live 子门:真实三节点 K3s 中两个 management replica、direct exact-key executor 和两个跨节点 provider observer 完成 PostgreSQL durable approval/binding、Kubernetes atomic projection rotation、无 Secret API 权限/ServiceAccount token、只读 `0440`、内容脱敏及删除后 fail-closed;v2 私有报告 24/24 gates 为 true,并保持 v1 verifier 兼容。该门不增加 Edge 闭包,也不等于直接 Vault/KMS/HSM custody。
|
||||
|
||||
转为 Accepted 前仍必须完成:固定低性能 Edge 设备的真实空间/写放大/断电恢复证据,以及 Cluster Legacy Env migration 的专用 PostgreSQL SERIALIZABLE ledger、Task/Trigger revision mutation、外部 custody adapter 和 HA promotion 后 receipt replay。ADR-0492 已完成本机 completion schema 演进和 completed-head 后 rollback material 回收,ADR-0493 又让没有 Legacy 身份输入的 fresh v52 目标身份经 signed `retain_target` 正确形成 no-effect,并精确消除六张已知目标表的 `unknown` 误判。Legacy `Auths/Users` 或真正未知表仍保持 manual;本切片的 Local Owner 编排、ADR-0494 的 mounted-files gate 或 PostgreSQL HA 证据都不得冒充完整 Cluster migration 与外部密钥托管。
|
||||
转为 Accepted 前仍必须完成:固定低性能 Edge 设备的真实空间/写放大/断电恢复证据,以及 Cluster Legacy Env migration 的逐项 Task/Trigger current-head revalidation、revision mutation/receipt、外部 custody adapter 和 HA promotion 后 receipt replay。ADR-0495 已完成专用 PostgreSQL SERIALIZABLE plan ledger baseline,但它只保存摘要、计数和 pinned SecretRef,不执行 Task/Trigger DML,也不接触 Secret material。ADR-0492 已完成本机 completion schema 演进和 completed-head 后 rollback material 回收,ADR-0493 又让没有 Legacy 身份输入的 fresh v52 目标身份经 signed `retain_target` 正确形成 no-effect,并精确消除六张已知目标表的 `unknown` 误判。Legacy `Auths/Users` 或真正未知表仍保持 manual;本切片的 Local Owner 编排、ADR-0494 的 mounted-files gate、ADR-0495 的 plan ledger 或 PostgreSQL HA 证据都不得冒充完整 Cluster migration 与外部密钥托管。
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
# ADR-0495:无敏感内容的 Cluster Legacy Env 迁移计划账本
|
||||
|
||||
- 状态:Accepted
|
||||
- 日期:2026-08-24
|
||||
- 决策:D-400
|
||||
- 关联:ADR-0104、ADR-0233、ADR-0259、ADR-0491、ADR-0494
|
||||
|
||||
## 背景
|
||||
|
||||
ADR-0491 已完成 Local SQLite 上的 Legacy Env 检查、人工裁决、Secret application、
|
||||
Task/Trigger revision mutation、回滚和 completion;ADR-0494 又证明了 Cluster
|
||||
`mounted-files` provider 的在线轮换。Cluster 仍缺少一个独立于 Local SQLite/POSIX
|
||||
authority 的持久计划边界,无法在真正写 Secret、Task 或 Trigger 之前冻结源证据、目标
|
||||
revision 集合和幂等 mutation 身份。
|
||||
|
||||
该边界不能把 2.x `Envs` 的名称、值、行内容搬进 PostgreSQL,也不能为了“先跑起来”
|
||||
让 runtime、admin 或通用 root export 取得迁移写权限。小型路由设备不应安装或加载本
|
||||
Cluster 能力;集群侧也必须有明确的行数、Task、Trigger 和有效载荷预算。
|
||||
|
||||
## 决策
|
||||
|
||||
### 1. 账本只保存不可逆摘要、计数和目标引用
|
||||
|
||||
新增 profile-neutral `qinglong/cluster-legacy-env-migration-plan@v1`。计划只包含:
|
||||
|
||||
- plan、mutation、Project 身份;
|
||||
- reconciliation bundle、reviewed decision、candidate set 三个 SHA-256 摘要;
|
||||
- source/active/disabled/effective binding 计数;
|
||||
- 同 Project、精确固定 version 的 canonical `SecretRef`;
|
||||
- Task 与 Trigger revision set 摘要和计数;
|
||||
- effective Secret 总字节数、数据库计划时间和 plan digest。
|
||||
|
||||
它不得包含源 Env 名称/值、row body、目标 plaintext/ciphertext、key ID、credential、
|
||||
Task spec、Trigger spec 或迁移日志。`SecretRef` 是既有目标路由引用,不是源 Env 名称;
|
||||
其 payload 仍受 canonical encoding、同 Project 和固定 version 校验。
|
||||
|
||||
硬上限为 100,000 个源行、100,000 个 Task、500,000 个 Trigger、64 KiB effective
|
||||
Secret 和 8 KiB plan JSON。active/disabled/source 计数必须守恒,至少存在一个 active
|
||||
行、effective binding 和 Task。
|
||||
|
||||
### 2. PostgreSQL 只提供 append-only v69 计划表
|
||||
|
||||
`pg-0070-cluster-legacy-env-migration-plans` 将 control contract 推进到 v69,并新增
|
||||
`cluster_legacy_env_migration_plans`:
|
||||
|
||||
- `plan_id` 为主键,`mutation_id` 与 `plan_digest` 各自唯一;
|
||||
- Project 外键使用 `ON DELETE/UPDATE RESTRICT`;
|
||||
- identity、digest、source、target、time、JSON 六组 named constraints;
|
||||
- `plan_json` 必须与列值构造出的完整 canonical JSONB **精确相等**,不是包含关系,
|
||||
因而任何额外 Env 字段也会被数据库拒绝;
|
||||
- 不提供 UPDATE、DELETE、TRUNCATE 或后台 GC。
|
||||
|
||||
迁移能力值新增 `cluster_legacy_env_migration_plan: 1`。Drizzle schema、readiness
|
||||
contract、固定 migration checksum 和实际 SQL stream 必须保持同锁步。
|
||||
|
||||
### 3. 只有 Automation Manager 可以读取和追加
|
||||
|
||||
新表从 PUBLIC 撤销全部权限,只向 `ql3_automation_manager` 授予 `SELECT, INSERT`。
|
||||
runtime、admin、Worker ingress、Approval/Run/Package/Worker Credential 等其他角色均为
|
||||
零权限;migration owner 只用于 schema 管理与集成验证。
|
||||
|
||||
具体 repository 只由
|
||||
`@qinglong/cluster-postgres/cluster-legacy-env-migration-plan` 显式子路径发布,不进入
|
||||
package root、runtime 或 admin entrypoint。runtime-core 也只通过
|
||||
`@qinglong/runtime-core/cluster-legacy-env-migration-plan` 发布数据契约。
|
||||
|
||||
### 4. 发布使用数据库时间、SERIALIZABLE 和精确重放
|
||||
|
||||
repository 每次使用一个短 `SERIALIZABLE` transaction,设置 statement、lock 和 idle
|
||||
transaction timeout;先按 `mutation_id` 查 exact replay,再验证 Project 在该可序列化
|
||||
快照中为 active,使用 `transaction_timestamp()` 生成 `plannedAtMs`,最后追加计划。
|
||||
|
||||
相同 mutation 与相同 intent 返回 durable `existing`;mutation drift、plan identity
|
||||
占用、inactive Project 和 named constraint 冲突失败关闭。`40001`、`40P01`、`55P03`
|
||||
最多重试三次。可选 transaction hook 只用于后续在**同一 Automation Manager 事务**中
|
||||
追加 Task/Trigger revision mutation;本 ADR 不调用它来声称那些 mutation 已实现。
|
||||
|
||||
Project 检查使用普通 SERIALIZABLE read,而不是 `FOR SHARE`。后者在 PostgreSQL 中还
|
||||
要求 UPDATE privilege,会错误扩大 Automation Manager 权限;可序列化顺序与外键已足以
|
||||
表达“计划发生在并发归档之前”的合法历史。
|
||||
|
||||
### 5. 不扩大 Edge/Standalone 闭包
|
||||
|
||||
实现复用既有 `runtime-core` 与 `cluster-postgres` package,不新增 workspace package、
|
||||
生产依赖、daemon、timer、watcher、controller 或缓存全集。Edge/Standalone 不导入
|
||||
PostgreSQL repository 或 migration;计数上限是 Cluster 计划输入预算,不是把集群表或
|
||||
Task 集合加载进小型设备。
|
||||
|
||||
## 被拒绝的替代方案
|
||||
|
||||
### 在 PostgreSQL 保存 Env 名称、值、密文或 key ID
|
||||
|
||||
拒绝。密文仍会扩大 custody、rotation、backup 和 HA 泄漏面;计划账本只需要摘要和目标
|
||||
引用即可证明后续 mutation 的输入身份。
|
||||
|
||||
### 在同一切片直接改写全部 Task/Trigger head
|
||||
|
||||
拒绝。计划发布和实际 DML 是两个可独立审计的 authority 阶段。没有 current-head
|
||||
revalidation、逐项 mutation receipt 与完整 response-loss 测试前,不得把 plan 冒充迁移。
|
||||
|
||||
### 复用 Local SQLite 或 Plugin Package Secret Binding 表
|
||||
|
||||
拒绝。Local authority 不属于 Cluster;Plugin Package binding 的 installation/generation
|
||||
身份也不能表达 Legacy Env reconciliation bundle、disabled preservation 和 Task/Trigger
|
||||
revision set。
|
||||
|
||||
### 为一个 contract 和一个 repository 新建 package
|
||||
|
||||
拒绝。它们分别属于既有 runtime migration contract 与 Cluster reconciliation storage
|
||||
能力,新增微包会再次制造用户已经指出的单文件 package 问题。
|
||||
|
||||
## 当前验证
|
||||
|
||||
2026-08-24 已完成:
|
||||
|
||||
- runtime contract 定向测试 4/4;
|
||||
- PostgreSQL repository 定向测试 5/5;
|
||||
- `@qinglong/runtime-core` 与 `@qinglong/cluster-postgres` 完整 package 测试零失败;
|
||||
- PostgreSQL migration/schema/readiness/entrypoint 定向门 92/92;
|
||||
- 真实 PostgreSQL 18.4 应用 70 条 migration 成功;
|
||||
- 实际 automation-manager create/replay/read 成功,UPDATE 被 `42501` 拒绝;
|
||||
- 实际 runtime/admin SELECT 被 `42501` 拒绝;
|
||||
- 带源 `envName` 的 widened JSON 被
|
||||
`ql3_cluster_legacy_env_plan_json_check` 以 `23514` 拒绝。
|
||||
|
||||
## 边界与后续门禁
|
||||
|
||||
本 ADR 关闭 ADR-0491 的 **Cluster plan ledger baseline**,但不把 ADR-0491 整体转为
|
||||
Accepted,也不声明:
|
||||
|
||||
1. Legacy source scan、sealed bundle 或 signed decision 已在 Cluster 中生产装配;
|
||||
2. Task/Trigger current head 已逐项复验或 revision mutation 已提交;
|
||||
3. Secret material 已写入 Kubernetes/Vault/KMS/HSM;
|
||||
4. migration Job、短期身份、receipt 与 promotion 后 exact replay 已完成;
|
||||
5. PostgreSQL physical failover、CloudNativePG promotion 或多架构结果已由本切片重新证明;
|
||||
6. 固定低性能路由设备的空间、写放大、断电和恢复证据已完成。
|
||||
|
||||
下一切片应在 Automation Manager 同一事务内绑定 current Task/Trigger revision set、逐项
|
||||
mutation 与 receipt,同时保持计划表 append-only;随后再接入外部 custody 和 HA promotion
|
||||
后的 exact replay。任何一步都不能回写源 Env 明文或放宽其他数据库角色。
|
||||
@@ -498,6 +498,7 @@
|
||||
| [ADR-0492](./ADR-0492-compatible-secret-config-completion-v3.md) | 兼容 Secret/Config 的 Reconciliation Completion v3 | Accepted |
|
||||
| [ADR-0493](./ADR-0493-target-native-reconciliation-domain-preservation.md) | 目标原生 Reconciliation 域分类与身份保留 | Accepted |
|
||||
| [ADR-0494](./ADR-0494-postgresql-secret-binding-and-mounted-provider-live-rotation.md) | PostgreSQL Secret Binding 与 Mounted Provider 在线轮换门 | Accepted |
|
||||
| [ADR-0495](./ADR-0495-content-free-cluster-legacy-env-migration-plan-ledger.md) | 无敏感内容的 Cluster Legacy Env 迁移计划账本 | Accepted |
|
||||
|
||||
## 规则
|
||||
|
||||
|
||||
Reference in New Issue
Block a user