Files
qinglong/docs/adr/ADR-0273-local-ai-provider-credential-product-authority.md
T

87 lines
6.5 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-0273:本机 AI Provider Credential 产品 Authority
- 状态:Accepted
- 日期:2026-08-04
- 关联:D-156、D-159、D-166、D-167、D-207、D-243、D-254、ADR-0169、ADR-0177
## 上下文
QingLong 3.0 已有 Project-bound Provider credential contract、可清零 Secret material、Cluster
PostgreSQL catalog,以及完整 Prompt executor;但 Edge/Standalone 仍没有耐久的 Provider→SecretRef
binding、credential-use audit 或受支持管理命令。`ql3-local-app` 的 installed AI 只能由嵌入方注入
provider loader,通用产品入口继续失败关闭。因此直接开放 Prompt CLI/HTTP 会迫使用户把 token 放进
配置、请求或进程环境,或者用测试内存 adapter 冒充生产 authority。
这个缺口不能通过新建 package、常驻管理 daemon 或把 AI migration 塞进所有路由器数据库来解决。
非 AI Edge 必须继续不安装、不加载、不迁移该能力;只有显式安装并激活 AI 的部署承担成本。
## 决策
1. 在既有 `@qinglong/ai` optional migration stream 增加 SQLite `9013`,持久化 immutable
Provider credential binding、append-only transition 和 content-free use audit。它不进入 QL3 base
migration/capability,也不改变非 AI Profile 的表集合。
2. 新的 Local repository 留在 `@qinglong/ai/local-model-provider-credential-storage`,实现既有
catalog、administration、binding-source 与 credential-audit port;不让 `local-sqlite` 依赖 AI,也不
新建 workspace package。current state 由 `(Project, provider, generation)` append-only transition
推导,不维护可漂移的第二 head。
3. bind/revoke 必须由当前 strong User 通过 `secret.manage` Policy;同一个 SQLite `BEGIN IMMEDIATE`
内重新验证 credential/Identity/pepper、active Project 与 latest RoleBinding fence,检查目标
SecretRef 属于 Project 且 exact pinned/current envelope 存在,然后原子写 binding、transition 与
allowed security audit。相同 mutation exact replay;命令、audit、actor、fence 或 Secret 事实漂移
冲突并回滚。
4. 既有 `local-owner-cli` 增加短生命周期 `ql3-model-credential`,只从 deployment root 内当前 UID
private `0600` command file 接受 `model-credential.bind|revoke|inspect`。inspect 同样在事务内复验
authority、读取 current transition、写独立 allowed audit;不存在返回 absent,不形成枚举 oracle。
5. 产品输出只包含 Project/provider/generation/state、binding revision/digest 与 transition time/digest
禁止输出 SecretRef、Secret name/version、envelope/key/token、authentication ID、数据库路径或原始错误。
6. credential-use audit 固定 operation/Project/provider/request、binding revision/digest 与时间,不保存
SecretRef 或模型内容;相同 identity 的 exact replay允许,语义漂移失败关闭。每次 provider 请求仍
重新读取 current binding 和 Secret material,不增加 cache、watcher 或 timer。
7. 本切片只建立本机 provider authority,不提前声称 Prompt 产品入口完成。下一切片必须从这个 durable
catalog、EncryptedLocalSecretService 与 active AI head 组合 `ql3-prompt`,不得接受 caller-supplied
binding/publication/Policy fence。
## 被拒绝的方案
- **token 放环境变量或 Prompt command**:无法按 Project 隔离,容易进入日志、诊断和进程快照。
- **把 binding 写入 provider URL/policy manifest**:配置文件会成为无审计 mutation authority,无法
对 COMMIT response loss 或 revoke 收敛。
- **让 `local-sqlite` 依赖 `@qinglong/ai`**:会把 optional AI 反向带入最小路由器 storage closure。
- **新建 provider-credential package**:没有独立制品或进程价值,违反 19-package 收敛账本。
- **常驻管理 API/watcher**:增加低配设备空闲 RSS、文件描述符和攻击面;短生命周期 CLI 已足够。
- **先开放 Prompt,再补 credential authority**:会把测试 adapter 或静态 token 固化为产品安全边界。
## 接受门
- SQLite 9013 migration/history/readiness 和 fresh/upgrade/partial-schema 失败关闭;
- bind→inspect→rebind→revoke、并发 CAS、exact replay、response-loss convergence
- non-Owner/无 `secret.manage`、credential/Project/RoleBinding/Secret race 均零部分写入;
- command/output exact-shape 与 SecretRef/token/path/error 脱敏;
- AI、Owner CLI、Local application targeted tests,完整 19-package/back 门;
- dependency/package-boundary/edge-import/local-image 与十档 artifact/RSS 门证明非 AI 路由器零增量;
- PostgreSQL HA 基线保持通过;本机 optional-only 变更不冒充新的 Cluster HA 能力。
## 实施证据
- `@qinglong/ai` 的独立 SQLite AI migration stream 已加入
`9013-ai-model-provider-credential-catalog`migration plan digest 为
`2720c6e45f82adbb03641d1c19e8ff7e1875a763a0b53d4910a46ca308800aa0`
三张表只在显式 AI migration/activation 后存在,不进入本机 base schema。
- `LocalModelProviderCredentialRepository` 已实现 immutable binding、append-only transition、
current-state 推导、Secret envelope 复验、事务内 authorization guard 和 content-free use audit
bind/replay、missing Secret、stale CAS、授权重放、inspect、revoke 后使用拒绝均有真实 SQLite 门。
- `ql3-model-credential` 已提供 private command-file-only 的 bind/revoke/inspect。真实 Edge fixture
已通过 bind→exact replay→inspect→独立 CLI process→revoke;未激活 AI 在认证前失败关闭,无
`secret.manage` 的 strong User 零 transition。输出不含 SecretRef、token、credential/path 或
authentication identity。
- 定向完整包门:AI 198 pass/3 条件 skip、Owner CLI 96 pass、Local SQLite 192 pass;完整
19-package 门退出 0,后端 1,096 pass/2 条件 skip/0 fail。dependency/package-boundary/
edge-import/local-image audit 全绿,workspace 仍为 19 包。
- 十档本机制品均 `compatible=true`。最小 Edge 为 3,518,660 bytes/324 files/
10,813,440 bytes RSS;最大 Standalone Application AI 为 5,917,156 bytes/475 files/
20,480,000 bytes RSS。非 AI Edge 的 package closure 不含 `@qinglong/ai`
- PostgreSQL 18.4 arm64 physical HA 基线 `gates.passed=true`,完成 `remote_apply`、timeline
1→2、旧主 fencing、`pg_rewind` read-only 重入与同步复制恢复;本切片没有新增 PostgreSQL
migration、role、Pool、listener 或 Cluster authority。受保护 CloudNativePG 证据控制面前后保持
同一 container ID、restart count 0、running。