Files
qinglong/docs/adr/ADR-0100-private-streaming-legacy-adoption-review-cli.md
T

62 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-0100:私有流式 Legacy adoption review-file 与产品签发 CLI
- 状态:Acceptedreview-file、正式 Identity/POSIX 认证装配、`ql3-adoption decision.issue` 与逻辑/制品门禁已实现;commit 已由 ADR-0101 完成,物理写放大证据待完成)
- 日期:2026-07-22
- 关联 RFCQL-RFC-0001 D-04、D-08、D-16、D-17、D-23、D-61、D-62、D-78、D-84、D-85、D-86、D-95、D-96、D-97、D-98、D-99
- 关联 ADRADR-0085、ADR-0086、ADR-0087、ADR-0095、ADR-0096、ADR-0097、ADR-0098、ADR-0099
## 背景
ADR-0099 已关闭专用 HMAC keyring 和可信 issuer capability,但仍只接受调用者提供的 `Iterable`。产品若把最多 100,000 个决定先解析为数组,会使内存随迁移规模增长;若把 reviewer Principal 写进 command JSON,则 assurance 可以自报;若每遍按路径重开 review 文件,攻击者可在 receipt、HMAC 或公开 publication 之间替换输入。
本机部署已有稳定 Identity credential、SQLite pepper provenance catalog 和最多 8 key 的 POSIX pepper keyring。它们必须复用,但 Owner credential pepper 不能兼作 adoption HMAC key。该能力只服务本机短生命周期管理面,不满足新增 workspace package 的 D-85 门槛。
## 决策
### 1. review-file 是有界、私有、同 descriptor 的 NDJSON
`@qinglong/local-admin/decision-issuer` 新增 `withPrivateLegacyCrontabAdoptionDecisionReviewFile()`。格式固定为一个 exact header 和零至 100,000 个 exact decision rowheader 绑定 `decisionId/profile/planDigest/inventoryDigest`row 只含既有 decision contract。每行最多 64 KiB、全文件最多 32 MiB,读取 chunk 固定 64 KiB,不缓存 decision 数组。
父目录和文件必须是当前 real/effective UID 的精确 `0700/0600` real path。入口执行 `lstat→O_NOFOLLOW open→fstat`,首次顺序扫描完成格式校验、计数和 SHA-256;后续 iterable 始终使用同一 descriptor 和显式 offset,可重复多遍。最终 authorization hard-link 前再次验证 descriptor/path/parent identity 和全文件 digestconsumer 返回后再复核一次,替换、原地修改、宽权限和 symlink 均失败关闭。
### 2. 复用现有 Local Owner CLI importer
产品入口位于 `@qinglong/local-owner-cli/adoption`binary 为 `ql3-adoption`。没有新增第 28 个 package、timer、watcher、sidecar 或第三方依赖。原 `ql3-owner` command 与输出保持不变。
`ql3-adoption run --command-file <absolute path>` 的普通私有 command file 只包含路径、profile、plan/decision identity 和有界 lifetime。credential token 不允许成为 command 字段,也不进入 argv、stdout 或 stderr;它只存在独立、同 UID `0600` credential-presentation file,读取时使用 `O_NOFOLLOW`、既有 inode 和 1 KiB 上限,buffer 在解析后擦除。
dependency audit 只允许 `src/adoption.ts` 导入 `local-admin` 根与 `/decision-issuer``local-identity``local-owner-keyring``local-sqlite/bootstrap` 五个精确入口;其他 CLI source、runtime Profile 和 application composition 仍被拒绝。
### 3. 正式 Identity credential 与 POSIX proof 合成 strong User
CLI 先冻结 deployment root、数据库、legacy source、review、credential、issuer keyring、Owner pepper keyring 和 authorization parent 的当前 UID、inode、类型及 `0700/0600` 边界,并要求 authority files 不共享 inode、authorization target 尚不存在。
随后以 `openLocalSqliteBootstrapDatabase()` 取得正式 credential/pepper repositories,通过 `createLocalIdentityKeyringAuthenticator()` 精确验证 credential version、User 状态、record 指定的 pepper key、catalog active/retired 状态和 material digest。单因素 credential 的 User subject 被保留;credential authentication ID 与 POSIX proof digest 经 domain-separated SHA-256 合成新的 authentication IDassurance 固定为 `local_console`,expiry 取两种证明的较早值且最长 60 秒。
每次 issuer authority confirmation 都重验 POSIX identity;认证后还重读 credential version/state、pepper binding、catalog state/digest 与 keyring material digest。issuer 调整为先完成认证、再读取可信 clock 生成 `issuedAtMs`,防止真实 authenticator 在后几毫秒生成的 `authenticatedAtMs` 被错误判为未来。弱/无效 credential 仍在 adoption HMAC key access 和 authorization publication 前失败。
### 4. 当前产品范围
本切片只开放 `legacy-crontab.decision.issue`:它把已经人工生成的 review-file 签成 ADR-0097 carrier,不自动生成 approve、不修改 legacy/target 数据库,也不绕过 ADR-0098 Policy/fence/audit/transaction。后续 ADR-0101 已在同一 binary 中接入 mutation/project/request IDs、当前 reviewer 重新认证与原子 commit;该能力不回溯改变本 ADR 的签发边界。
## 被否决的替代方案
1. **新增 `ql3-adoption-cli` package**:单部署、单 consumer、无独立供应链责任,不满足 D-85。
2. **把 decisions 放进 command JSON**:会产生全数组内存和持久 intent 复制,拒绝。
3. **每次迭代重新按路径打开 review-file**:无法证明 receipt、HMAC 和 publication 消费同一 inode,拒绝。
4. **把 token 放进 argv、环境变量或普通 command JSON**:扩大 shell history、进程检查和持久日志暴露面,拒绝。
5. **只用 API credential 的 single-factor assurance**:不满足高风险人工 adoption 的强认证要求,拒绝。
6. **把 Owner pepper 复用为 carrier HMAC key**:合并认证与授权载体的泄露/轮换域,拒绝。
7. **为了最终复核在四次 authority check 中都重散列 32 MiB review**:造成不必要 I/Oissuer identity 复核与仅在 publication 前执行的 decision-stream digest 复核保持独立。
## 验收证据
1. local-admin 35 项测试通过;新增测试覆盖同 descriptor 重复迭代、digest confirmation、宽权限、symlink、处理中 replacement、widened record 和 header identity mismatch。
2. local-owner-cli 5 项测试通过;端到端使用真实 SQLite Identity、pepper catalog/POSIX keyring 和 adoption issuer keyring签发并重新验证 carrier,同时覆盖 token 不进入 command/output、widened intent、无效 credential 和原 `ql3-owner` 回归。
3. dependency boundary 23 项、backend 665 项及完整 dependency audit 通过:27 importer、local-admin 9 source files、local-owner-cli 4 source files、无 finding。
4. 六种 Profile 制品门禁通过。base edge/standalone 为 1,489,761/1,489,887 bytes、216 files、34 modulesadopted 为 1,722,866/1,723,037 bytes、240 files、37 modulesapplication 为 2,010,793/2,010,901 bytes、301 files、64 modules。最大 RSS delta 抽样为 11,829,248 bytes,均低于既有预算。
## 后续约束
ADR-0101 已为同一 `ql3-adoption` binary 增加显式 commit command,并复用 ADR-0098 publisher。下一切片应补 32 MiB/100,000-row review、carrier 和原子 publication 的物理 Edge 峰值 RSS、读取量、fsync/写放大证据。Scheduler/Run admission 仍是独立 Gatecluster 管理面必须使用远程强身份和独立 KMS/HSM adapter,不得复用本机 credential file、Owner pepper 或 issuer file keyring。