feat(ql3): add secret config completion evidence

This commit is contained in:
whyour
2026-08-24 11:54:25 +08:00
parent 8ad8ed96bd
commit d94ca02e0d
10 changed files with 1093 additions and 55 deletions
+13 -3
View File
@@ -43,15 +43,25 @@
和 receipt。item 使用 deferred parent FK 流式落库,最终 receipt 才关闭父引用,因此最多 100,000 Task/500,000 Trigger 不进入 JS 全集或 O(N×M) 扫描。
commit response-loss exact replay 会重验 Secret envelope、Task/Trigger durable head 与 scheduleSecret 占用、provenance 缺项和提交前 authority 漂移均回滚全部 DML。
第七切片在同一 Secret/Config application 子域补齐 Owner `prepared → apply → rollback`,仍不新增 package、dependency 或常驻进程。Owner 只持有私有
ciphertext-only `materials.ndjson`,单行上限 64 KiBEdge/Standalone 总量上限 4/16 MiB,且 keyring 必须位于 deployment root 之外;intent 之前的孤儿
ciphertext-only `materials.ndjson`,单行上限 64 KiBEdge/Standalone 总量上限 4/16 MiBkeyring、Owner Pepper 与 credential material 必须位于私有
deployment root 内,并与 apply authority root、target database 相互隔离;intent 之前的孤儿
material 丢弃并重新生成,intent 之后只重放同一 ciphertext。编排先复验 stopped proof、同一 reviewer 的 5 分钟内 `local_console` 强认证并完成 write-before
SQLite backup,随后单向推进 `reconciliation_secret_config_reviewed → reconciliation_secret_config_apply_prepared → reconciliation_secret_config_applied`
material、backup、prepared head、数据库 commit、receipt、applied head 与 seal 的 response-loss 均精确恢复;rollback 只从 applied 恢复 exact 写前 snapshot
再覆盖 restore、rollback receipt/head/seal 的 response-loss 并推进 `reconciliation_secret_config_rolled_back`。ENOSPC、权限错误或 backup 漂移发生在 head/DML 前,
适用于小型路由设备;该一次性 Owner authority 不进入常驻 Application 制品。
第八切片以 ADR-0492 增加兼容 v1/v2 的 completion schema v3:只有 `secret_config_application` evidence 才升级 receipt 版本,binding 只包含
SecretConfig/decision/apply digest 与四条非敏感 authority path`adapterCount` 由 Automation、Secret/Config、Run History 三类实际证明推导为
`0|1|2|3`。Completion 将 Application 中原本正确失败关闭的 `secret_and_config=manual_external` 经 ready signed decision、exact apply intent/receipt、
current target snapshot 和 applied head 收敛为 receipt 内的 `adapter_required`,但不会替 Identity/Policy/Audit、Unknown 或其他 manual 域背书。
Automation 与 Secret/Config 连续写同一 SQLite 时,不再错误要求当前 target 等于 Automation 的历史写后快照,而是证明
`Secret/Config backup.sha256 == Automation targetAfter.sha256`,再证明 current target 等于 Secret/Config `targetAfter`。lineage 只新增
`reconciliation_secret_config_applied → reconciliation_completed` 一条合法边;receipt seal 与 completed head durable 后,才幂等删除两类数据库等量
backup。Secret/Config 的 ciphertext material、intent 与 receipt 继续 `0400` 保留,backup/rollback root 封为 `0500`,不增加后台 GC、timer 或常驻内存。
rolled-back、target drift、提前丢失 backup 与其余 manual 域继续失败关闭;完整迁移库当前仍可能因 Identity/Unknown 保持 manual,这不是 v3 可绕过的限制。
全部 evidence 不含原 Env name/value、目标 ciphertext/key ID 或 row body。v52 Local SQLite 完整测试为 `247/247`publisher 定向回归 `6/6`fresh Edge
readiness 为 contract v52、104 migrations、89 required tables、SQLite 3.53.3、`DELETE` journal。Local Admin 为 `96/96`Local Owner 为
`297 total / 290 pass / 7 conditional skip / 0 fail`18-package clean build 与逐包顺序测试单次退出 0,完整 backend 为
`300 total / 293 pass / 7 conditional skip / 0 fail`18-package clean build 与逐包顺序测试单次退出 0,完整 backend 为
`1567 total / 1565 pass / 2 conditional skip / 0 fail`。package boundary、精确 Cluster dependency/legacy boundary、122-module Edge import、本地镜像与
`14/14` Local artifact audit 全部 compatible;基础 Edge/Standalone 为 `2,635,529 / 2,635,607 bytes`、323 files、58 loaded modules,距 4 MiB
上限仍分别保留 `1,558,775 / 1,558,697 bytes`,且闭包只有 Local SQLite、runtime-core 与 SemVer,没有 Cluster/PostgreSQL 依赖。
@@ -60,7 +70,7 @@
因而不重跑且不重新占有 PostgreSQL HA 证明;相邻已通过的 remote CI/HA 只作为基线。
D-385D-388 的 `config.sh`/Keyv/SSH data-directory lineage 与 SQLite `Envs` 保持分离;当前无稳定生产 schema 的历史 `Configs` 表继续 sealed+manual
不猜字段。后续切片必须完成 completion 下一 schema 与跨领域完成后的备份回收、真实 Edge 空间证据和 Cluster Secret provider live gate。D-397 apply
不猜字段。后续切片必须完成真实 Edge 空间证据和 Cluster Secret provider live gate。D-397 apply
只声明 sealed source retained 且 `physicalErasureGuaranteed=false`;明文销毁必须在 restart/
readiness、观察窗和 rollback retention 之后另行强认证。Cluster 必须使用 PostgreSQL SERIALIZABLE ledger、外部 KMS/Secret provider 与 HA evidence
不复用 Local SQLite/POSIX authority,也不得把明文写入 PostgreSQL、ConfigMap、Pod env 或 Job command。
@@ -1,6 +1,6 @@
# ADR-0491:有界 Secret/Config Reconciliation 与任务环境绑定
- 状态:ProposedD-397 已实现 Legacy Env inspection、私有有界 row plan、durable plan publication、独立 signed decision、逐项 Automation adoption provenance、Local SQLite 原子 application publisherOwner prepared/apply/rollback 编排;跨领域 completion schema、真实 Edge 空间证据和 Cluster Secret provider live gate 尚未完成)
- 状态:ProposedD-397 已实现 Legacy Env inspection、私有有界 row plan、durable plan publication、独立 signed decision、逐项 Automation adoption provenance、Local SQLite 原子 application publisherOwner prepared/apply/rollback 编排与 ADR-0492 completion v3真实 Edge 空间证据和 Cluster Secret provider live 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
@@ -85,7 +85,7 @@ D-397 application 已在一个 `BEGIN IMMEDIATE` 事务内完成:
任一 Secret、Task、Trigger、dispatch、audit、ledger 或 fence 冲突都回滚整个事务。禁止先提交 Secret 再逐任务修补,也禁止在现有 Task revision 上原地改 JSON。目标已有同名/同源 Secret、非 Legacy Task、Plugin-owned Task 或用户在 stopped window 中产生的 revision 都按冲突处理,不自动覆盖或重命名。
Owner 编排保留在既有 `local-owner-cli/deployment/reconciliation/application/secret-and-config/application/` 子域,不新增 package、常驻进程或依赖。它只把密文写入私有 `materials.ndjson`,单行不超过 64 KiBEdge/Standalone 文件分别不超过 4/16 MiBPOSIX keyring 必须位于 deployment root 之外。编排在推进 head 前重新证明 stopped state、同一 reviewer 的 `local_console` 强认证与最多 5 分钟认证年龄,并先创建、校验 write-before SQLite v52 backup。空间不足、权限错误或 backup 漂移均发生在 prepared head 与任何 DML 之前,不得在低配设备上边写边赌。
Owner 编排保留在既有 `local-owner-cli/deployment/reconciliation/application/secret-and-config/application/` 子域,不新增 package、常驻进程或依赖。它只把密文写入私有 `materials.ndjson`,单行不超过 64 KiBEdge/Standalone 文件分别不超过 4/16 MiBPOSIX keyring、Owner Pepper 与 credential material 必须位于私有 deployment root 内,且与 apply authority root、target database 相互隔离。编排在推进 head 前重新证明 stopped state、同一 reviewer 的 `local_console` 强认证与最多 5 分钟认证年龄,并先创建、校验 write-before SQLite v52 backup。空间不足、权限错误或 backup 漂移均发生在 prepared head 与任何 DML 之前,不得在低配设备上边写边赌。
lineage 单向推进 `reconciliation_secret_config_reviewed → reconciliation_secret_config_apply_prepared → reconciliation_secret_config_applied`;回滚只允许从 applied 精确恢复写前 SQLite snapshot,再推进到 `reconciliation_secret_config_rolled_back`。material、backup、prepared head、数据库 commit、receipt、applied head、seal,以及 restore、rollback receipt/head/seal 的每个 response-loss 窗口都通过 immutable digest 与 durable target state 精确重放:intent 之前的孤儿密文会丢弃并重新生成,intent 之后只复用同一 ciphertext;数据库 commit 丢失响应时由 v52 publisher receipt 复验,不重复 DML。回滚保持原 SQLite 文件 identity 证明,任何 receipt/head/seal 漂移都失败关闭。
@@ -141,8 +141,8 @@ Cluster 不得把 Legacy Env 明文写入 PostgreSQL、ConfigMap、Job command
## 当前验证与后续门禁
D-397 当前切片已经实现:absent、unsupported、Edge over-budget、2.x 顺序、同名连接、disabled preservation、保留前缀、异常状态、effective overflow、candidate digest、content-free diagnostics、私有有界 row plan、目标 Secret 冲突、Automation adoption projection、no-effect/manual outcome、durable no-replace publication、terminal seal、head CAS、逐候选独立 signed decision、同一强认证 reviewer、decision/authorization byte bound、`skip → manual_required`、prepare/commit response-loss exact replay、只读 terminal verify、v51 逐 Task/Trigger adoption provenance、v52 Local SQLite 原子 application publisher,以及 Owner prepared/apply/rollback orchestration。v52 在一个 `BEGIN IMMEDIATE` 内复验 Project/RoleBinding、外部 authority、逐 Task/Trigger provenance、当前 head、Plugin ownership 与 Trigger 数量,流式写入加密 Secret、content-free audit、Task rev2、dispatch、Trigger rev2、schedule 和四类 application ledgerdeferred parent FK 允许最多 100,000 Task/500,000 Trigger 逐项发布而不在 JS 堆保留全集。Owner 在写前固定 backup 与 stopped proof,以有界 ciphertext-only material 连接 reviewed decision 和 publisher,并覆盖 apply/rollback 全部 response-loss 窗口。commit response-loss 通过 durable receipt exact replay,并重新验证 Secret envelope、Task/Trigger head 与 schedule;目标占用、provenance 缺项、提交前 authority 漂移均回滚全部 DMLrollback 则恢复写前 snapshot。
D-397 当前切片已经实现:absent、unsupported、Edge over-budget、2.x 顺序、同名连接、disabled preservation、保留前缀、异常状态、effective overflow、candidate digest、content-free diagnostics、私有有界 row plan、目标 Secret 冲突、Automation adoption projection、no-effect/manual outcome、durable no-replace publication、terminal seal、head CAS、逐候选独立 signed decision、同一强认证 reviewer、decision/authorization byte bound、`skip → manual_required`、prepare/commit response-loss exact replay、只读 terminal verify、v51 逐 Task/Trigger adoption provenance、v52 Local SQLite 原子 application publisherOwner prepared/apply/rollback orchestration,以及 ADR-0492 completion v3。v52 在一个 `BEGIN IMMEDIATE` 内复验 Project/RoleBinding、外部 authority、逐 Task/Trigger provenance、当前 head、Plugin ownership 与 Trigger 数量,流式写入加密 Secret、content-free audit、Task rev2、dispatch、Trigger rev2、schedule 和四类 application ledgerdeferred parent FK 允许最多 100,000 Task/500,000 Trigger 逐项发布而不在 JS 堆保留全集。Owner 在写前固定 backup 与 stopped proof,以有界 ciphertext-only material 连接 reviewed decision 和 publisher,并覆盖 apply/rollback 全部 response-loss 窗口。completion v3 保留 v1/v2 exact shape,验证 signed decision/apply/current target/head,只有 completed head durable 后才幂等回收 Secret/Config backuprolled-back、target drift 与其余 manual 域继续失败关闭。commit response-loss 通过 durable receipt exact replay,并重新验证 Secret envelope、Task/Trigger head 与 schedule;目标占用、provenance 缺项、提交前 authority 漂移均回滚全部 DMLrollback 则恢复写前 snapshot。
本切片当前验证:Local SQLite `247/247`,其中 Secret/Config application publisher 定向回归 `6/6`fresh Edge readiness 为 contract v52、104 migrations、89 required tables、SQLite 3.53.3、`DELETE` journal。Local Admin 为 `96/96`Local Owner 为 `297 total / 290 pass / 7 conditional skip / 0 fail`18-package clean build 与逐包顺序测试单次退出 0,完整 backend 为 `1567 total / 1565 pass / 2 conditional skip / 0 fail`。package boundary、精确 Cluster dependency/legacy boundary、122-module Edge import、本地镜像与 `14/14` Local artifact audit 全部 compatibleLocal Admin 为 49 source / 48 nested / 1 root exportLocal Owner 为 188/187/1workspace 仍为 18 packages 且没有单文件或浅层 package。基础 Edge/Standalone 为 `2,635,529 / 2,635,607 bytes`、323 files、58 loaded modules,且没有 Cluster/PostgreSQL 闭包。本切片不改 PostgreSQL schema、连接、role、Pool、容器或 Kubernetes 拓扑,因此不重跑且不重新占有 PostgreSQL HA 证明。
本切片当前验证:Local SQLite `247/247`,其中 Secret/Config application publisher 定向回归 `6/6`fresh Edge readiness 为 contract v52、104 migrations、89 required tables、SQLite 3.53.3、`DELETE` journal。Local Admin 为 `96/96`Local Owner 为 `300 total / 293 pass / 7 conditional skip / 0 fail`18-package clean build 与逐包顺序测试单次退出 0,完整 backend 为 `1567 total / 1565 pass / 2 conditional skip / 0 fail`。package boundary、精确 Cluster dependency/legacy boundary、122-module Edge import、service-manager bridge import、本地镜像与 `14/14` Local artifact audit 全部 compatibleLocal Admin 为 49 source / 48 nested / 1 root exportLocal Owner 为 188/187/1workspace 仍为 18 packages 且没有单文件或浅层 package。基础 Edge/Standalone 为 `2,635,529 / 2,635,607 bytes`、323 files、58 loaded modules,且没有 Cluster/PostgreSQL 闭包。本切片不改 PostgreSQL schema、连接、role、Pool、容器或 Kubernetes 拓扑,因此不重跑且不重新占有 PostgreSQL HA 证明。
转为 Accepted 前仍必须完成:completion schema 演进 completion 后 rollback material 回收、真实 Edge 空间预算证据与 Cluster Secret provider live gate本切片的 Local Owner 编排或 PostgreSQL HA 证据不得冒充外部密钥托管跨领域 completion 已完成。
转为 Accepted 前仍必须完成:真实 Edge 空间预算证据与 Cluster Secret provider live gateADR-0492 已完成本机 completion schema 演进 completed-head 后 rollback material 回收,但本切片的 Local Owner 编排或 PostgreSQL HA 证据不得冒充外部密钥托管,也不得把仍含 Identity/Unknown manual 域的迁移冒充跨领域 completion 已完成。
@@ -0,0 +1,90 @@
# ADR-0492:兼容 Secret/Config 的 Reconciliation Completion v3
- 状态:Accepted
- 日期:2026-08-24
- 决策:D-397
- 关联:ADR-0487、ADR-0488、ADR-0490、ADR-0491
## 背景
ADR-0488 的 completion v1 只识别 Application 与 AutomationADR-0490 的 v2 再加入 Run History。ADR-0491 已经让 Secret/Config 形成 signed decision、原子 application receipt、写后 target snapshot、applied head 与可恢复 backup,但旧 completion 无法消费这些证明,也不能在全局完成后回收 Secret/Config 的数据库等量 rollback material。
Application plan 中 `secret_and_config` 的历史 action 是 `manual_external`。这是专用 adapter 获得授权前的正确失败关闭状态,不能改写 sealed plan 为 `adapter_required`。Completion 必须验证后续 plan、signed decision 和 apply 全链路,再在自己的 receipt 中把该域收敛为已证明的 adapter;它仍不能替其他 `manual_external` 域背书。
## 决策
### 1. 保持 v1/v2 精确兼容,新增 v3
`local.deployment.reconciliation.complete|complete.verify` 新增 schema v3。v1/v2 的输入 shape、receipt 语义和验证路径保持不变;只有 receipt 包含 `secret_config_application` 时版本才为 v3。v3 可同时携带 Automation、Secret/Config 与 Run History authority`adapterCount` 由八域证据实际推导并扩大为 `0|1|2|3`,调用方不能自报。
Secret/Config completion binding 只包含 `secretConfigId``decisionId``expectedApplyDigest`。options 只携带 plan/decision/apply authority roots 和 target SQLite 路径,不重新携带 keyring、credential 或明文 material。所有 authority roots 必须互不重叠;Automation 与 Secret/Config 同时存在时必须指向同一个 target SQLite。
### 2. 证明链必须闭合
Completion 重新验证:
1. sealed Application plan 的 `secret_and_config=manual_external`
2. 同一 Application 上 ready、无 skip 的 signed Secret/Config decision
3. exact apply intent、receipt、decision/SecretConfig identity、preparation digest 与 apply digest
4. 当前 target snapshot 等于 Secret/Config `targetAfter`
5. apply storage 是合法的 `applied` 或 completion 后 `completed` layout,且不存在 rollback receipt
6. source head 是 `reconciliation_secret_config_applied` 且绑定 apply digest。
若 Automation 也先写入同一数据库,当前 target 不再等于 Automation 的旧 `targetAfter`。此时链式证明固定为 `Secret/Config backup.sha256 == Automation targetAfter.sha256`,然后再验证当前 target 等于 Secret/Config `targetAfter`;不得把合法的后续写入误判为 Automation drift,也不得跳过两阶段之间的 digest 连续性。
Rolled-back state、target drift、decision/apply 脱离、提前丢失 backup、unknown `Configs`、Identity/Policy/Audit、Unknown 或任意其他未终态域都继续拒绝全局 completion。Secret/Config 已 applied 不代表整个 reconciliation 已完成。
### 3. durable head 先于 rollback material 回收
Instance lineage 新增唯一合法边:
```text
reconciliation_secret_config_applied → reconciliation_completed
```
既有边、generation、source digest 和 CAS 规则不变。Receipt 必须先 no-replace 发布并封存,随后 completed head durable,最后才可删除 Automation 与 Secret/Config backup。两类 storage 都接受 `applied|completed` 重放:head 尚未 completed 时 backup 缺失立即失败;head 已 completed 后允许任一 backup 已回收,并幂等收敛剩余 backup。
Secret/Config completed layout 删除的只有 `backup/before.sqlite`。加密 `materials.ndjson`、intent 与 apply receipt 保留为 `0400` audit evidenceroot、backup root 与空 rollback work root 封为 `0500`。该操作不扫描数据库、不创建数据库等量副本、不引入 timer/GC,适合低容量 Edge;真正销毁 ciphertext 或 sealed Legacy source 仍是后续独立 retention ceremony。
### 4. 部署边界不变
实现全部位于既有 `@qinglong/local-owner-cli` 的 cutover、completion 与 Secret/Config application 子域,没有新增 workspace package、production dependency、SQL migration、daemon、listener、watcher、timer、Pool、容器或 Kubernetes workload。Edge/Standalone 常驻闭包不加载该一次性 Owner authority。
Cluster 不复用本机 receipt、POSIX storage 或 instance head。Cluster completion 仍需要 PostgreSQL SERIALIZABLE ledger、外部 Secret provider/KMS、HA timeline 与 promotion 后验证。
## 影响
- completion receipt 的消费者必须按 `schemaVersion` 解析,未知版本继续失败关闭。
- `advanceLocalCutoverInstanceHead` 是 CRITICAL 共享状态机;本 ADR 只增加一条 source-state 边,不改任何旧 transition。
- 完整迁移库当前仍可能因 `identity_policy_audit``unknown` 保持 manual;这是正确的全局围栏,不应为了演示 v3 成功而放宽。
- v3 verify 要求 completed storage,不能在 head durable 之前充当修复命令。
## 被拒绝的替代方案
### 改写 sealed Application plan
拒绝。历史 `manual_external` 是 adapter 授权前的事实;事后把它改成 `adapter_required` 会破坏签名、digest 与审计语义。
### 只检查 Secret/Config apply receipt
拒绝。孤立 receipt 不能证明 signed decision、当前 target、source head、Automation 前序写入或 rollback 状态。
### completion 前删除 backup
拒绝。receipt/head crash window 仍可能需要显式 rollback;提前删除会让响应丢失不可恢复。
### 为 Edge 增加后台 GC
拒绝。一次性 completion 已能固定内存、幂等回收;常驻 timer 会扩大路由设备资源与生命周期表面。
## 验证
- completion v3 定向:`3/3`,覆盖 exact Secret/Config evidence、其他 manual 域失败关闭、rolled-back、target drift、v3 receipt、lineage 边和 completed-storage 幂等回收;
- completion v1/v2 兼容:no-effect v1、Automation rollback retention 与 Run History v2 均通过;
- Local Owner:受限沙箱 `300 total / 290 pass / 7 skip / 3 loopback EPERM`,对应两个 loopback 文件在沙箱外 `15/15`,有效结果 `300/293/7/0`
- TypeScript package closure8 个 Local 依赖包与 Local Owner 全部通过;
- 完整 backend`1567 total / 1565 pass / 2 conditional skip / 0 fail`
- 18-package clean build 与逐包顺序测试单次退出 0package boundary、Cluster dependency、122-module Edge import、service-manager bridge import、本地镜像与 `14/14` Local artifact audit 全部 compatible
- workspace 保持 18 packages`singleSourcePackages=[]``shallowSourcePackages=[]`;基础 Edge/Standalone 为 `2,635,529 / 2,635,607 bytes`、323 files、58 loaded modules。
阶段提交后的远程 CI 仍需重新验证;D-397 的真实 Edge 空间证据和 Cluster Secret provider live gate 仍属于 ADR-0491 后续工作。
+2 -1
View File
@@ -494,7 +494,8 @@
| [ADR-0488](./ADR-0488-cross-domain-reconciliation-completion-fence.md) | 跨领域 Reconciliation 完成围栏与目标重启授权 | Accepted |
| [ADR-0489](./ADR-0489-service-manager-completion-restart-lineage.md) | Service Manager 完成围栏重启谱系 | Accepted |
| [ADR-0490](./ADR-0490-run-history-terminal-preservation.md) | Run History 终态保全与跨领域完成证明 | Accepted |
| [ADR-0491](./ADR-0491-bounded-secret-config-reconciliation-and-task-binding.md) | 有界 Secret/Config Reconciliation 与任务环境绑定 | ProposedD-397 local apply/rollback completecompletion/Cluster gate pending |
| [ADR-0491](./ADR-0491-bounded-secret-config-reconciliation-and-task-binding.md) | 有界 Secret/Config Reconciliation 与任务环境绑定 | ProposedD-397 local apply/rollback/completion completeEdge/Cluster gate pending |
| [ADR-0492](./ADR-0492-compatible-secret-config-completion-v3.md) | 兼容 Secret/Config 的 Reconciliation Completion v3 | Accepted |
## 规则