mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
98 lines
5.1 KiB
Markdown
98 lines
5.1 KiB
Markdown
# ADR-0182:有 signer 影响证明的本机 Publisher Key 退休
|
||
|
||
- 状态:Accepted
|
||
- 日期:2026-07-28
|
||
- 关联:RFC D-133、D-169、D-170、D-171、D-172;ADR-0135、ADR-0179、
|
||
ADR-0180、ADR-0181
|
||
|
||
## 背景
|
||
|
||
ADR-0181 只允许 addition-only overlap rotation。直接删除旧 key 不安全:catalog
|
||
可能仍保留由它签名的 recovery entry;即使一次扫描结果为零,也可能有并发 publish
|
||
正在验证 bundle、尚未写出 entry。SQLite audit、catalog/bundle 文件和 trust root
|
||
又不共享事务介质,不能把一次目录扫描伪装成原子证明。
|
||
|
||
## 决策
|
||
|
||
### 1. 正常退休使用 intent → proof → receipt → generation
|
||
|
||
authenticated Owner 执行 `plugin-package.publisher-trust.retire`。命令绑定 publisher、
|
||
key ID、expected generation、mutation ID 和首次 durable audit 时间,不接受调用方
|
||
提供的新 trust JSON。
|
||
|
||
管理器先在 `0700` trust root 以 hard-link no-replace 发布 `0600` immutable
|
||
retirement intent。intent 永久阻止该 signer 的新 catalog publication。随后分析全部
|
||
retained catalog entry;只有目标 signer 引用为零,且 catalog/bundle transaction
|
||
marker 总数为零,才发布 immutable receipt。receipt 绑定 intent、generation、
|
||
mutation、审计时间和低敏计数。
|
||
|
||
最后生成显式 `retire` snapshot。新 trust 必须精确等于前代删除一个目标 key,不得
|
||
改写其他 key,并至少保留一个在审计时间有效的 key。snapshot durable 后才原子提升
|
||
`current.json`。
|
||
|
||
### 2. Catalog publication 先暴露事务,再检查 intent
|
||
|
||
publish 在验证 bundle 前先创建可识别的 catalog transaction marker,并保持到 entry
|
||
发布完成。它在 marker 创建后以及 Owner audit/fence 后、任何 final bundle/entry
|
||
可见前各检查一次受管 trust root。
|
||
|
||
因此:
|
||
|
||
- intent 先赢:publisher 两次 guard 都拒绝旧 signer;
|
||
- publisher 先赢:retirement proof 看见 marker,拒绝生成 receipt;
|
||
- 任一进程崩溃:marker 保持为未决事实,由显式 collect 处理,退休继续失败关闭。
|
||
|
||
catalog Owner command 不再接受任意 `publisherTrustFilePath`,只从 options 中受管
|
||
`trustRoot/current.json` 读取,避免 stale trust 文件绕过 intent。
|
||
|
||
### 3. 恢复、容量与低配约束
|
||
|
||
intent、receipt、snapshot 或 current 提升后的崩溃都只允许同一认证 command 精确
|
||
重放。已发布 receipt 不重复扫描,已发布 snapshot 不重复生成;inspect 只返回
|
||
generation、key/snapshot/retirement 数量和 pending 状态,不返回 publisher/key ID。
|
||
|
||
trust root 最多 64 代 snapshot、32 个 intent、32 个 receipt 和 64 个临时文件;
|
||
未知或超限 entry 失败关闭。实现复用现有 local-admin/local-owner-cli,不新增
|
||
workspace package、第三方依赖、timer、watcher、listener、网络访问或 application
|
||
常驻 import。
|
||
|
||
### 4. 紧急撤销保持独立
|
||
|
||
本 ADR 只适用于计划内、已完成替代发布和旧 entry 回收的正常退休。key 疑似泄露时,
|
||
是否立即使历史 durable lock 失效、如何 quarantine、谁可 break-glass、如何恢复,
|
||
由 D-173/ADR-0183 的 durable proposal、双人或 break-glass confirmation 与 immutable
|
||
quarantine receipt 定义;不得用正常退休暗示 compromise 已得到处置。ADR-0183
|
||
先阻断新 publication/queued stage,但不把 receipt 冒充 active resource 热停止。
|
||
|
||
## 拒绝方案
|
||
|
||
1. **扫描为零后直接删除**:并发 publish 可在扫描后写入旧 signer entry。
|
||
2. **只分析 current SQLite head**:遗漏仍用于恢复或尚未 collect 的历史 entry。
|
||
3. **短暂内存锁**:不能跨进程、崩溃或设备重启提供证据。
|
||
4. **从请求读取任意 trust JSON**:stale 文件可绕过受管 intent。
|
||
5. **删除 intent/receipt 节省空间**:破坏 exact replay 与审计链。
|
||
6. **新增 watcher/reconciler**:给低配路由器增加 idle authority 和资源成本。
|
||
|
||
## 当前证据
|
||
|
||
- 有 signer 引用或任一未决 transaction 时拒绝退休;
|
||
- intent durable 后旧 signer publication guard 失败,新 signer 不受影响;
|
||
- receipt 后和 snapshot 后崩溃均可由 exact command 收敛;
|
||
- retire 精确删除一个 key,保留其他定义与至少一个当前有效 key;
|
||
- 非 Owner 在 intent 可见前被拒绝;成功和失败均使用既有低敏 SecurityAudit;
|
||
- trust root 的未知文件、超限 retirement evidence、宽权限和 identity 漂移失败关闭;
|
||
- local-admin 62/62、local-application 31/31、local-owner-cli 22/22、
|
||
dependency/source boundary 30/30;
|
||
- workspace 仍为 22 package,未增加生产依赖或常驻资源。
|
||
|
||
Cluster 代码、migration、ACL 与部署 manifest 未变化,本切片不重新声明 Cluster
|
||
publisher trust 能力,也不要求重复 PostgreSQL HA Docker 门。
|
||
|
||
## 后续门禁
|
||
|
||
1. D-174 active/staged/activating Package 与 Task/Tool resource 撤出;
|
||
2. 被隔离 lock 的替代发布、恢复或永久 tombstone ceremony;
|
||
3. 在线 OCI fetch authority 与 publisher metadata/update channel;
|
||
4. 固定低配 Linux 路由器断电、ENOSPC、闪存写放大与容量证据;
|
||
5. Cluster 对等 trust lifecycle。
|