# Agent Note: 可恢复的提供方凭据生命周期

Status: implemented
Archived: 2026-09-04

[English](2026-08-06-provider-credential-lifecycle.md) | 中文

## 问题

Models 编辑器横跨互相独立的 settings 与凭据 RPC 领域。之前它先提交提供方 settings，再存储 API 密钥，却一直保留卡片打开时的 revision 和原始子树。如果凭据写入失败，重试会用陈旧 revision 重放已提交的 settings 变更，并产生冲突，导致用户无法从同一张卡片完成第二个阶段。空的 pi-ai 密钥还会写入派生的 `apiKeyEnv`，却不写入凭据，从而阻止 pi-ai 使用提供方原生凭据发现。删除时则存在相反的残留问题：profile 消失了，页面存储的密钥却保留在 `.env` 中，并在重新添加提供方时静默地恢复作用。笼统的行操作与确认文案也没有标明要更改哪个提供方。

## 决策

提供方保存仍在现有 wire 领域上按先 settings、后凭据的两阶段顺序执行，但卡片会把成功的 settings 响应视为提交检查点。它会在尝试 `credentials.set` 之前，用返回的脱敏 descriptor 替换比较基准子树与预期 revision；如果第二阶段失败，草稿密钥与卡片会继续显示，重试不会产生 settings op，只会再次写入凭据。首次 settings 提交之前发生的真实并发变更仍会以 `settings-conflict` 失败。UI 与 DeepSeek 直连 resolver 边界均会去除所输密钥的首尾空白，且只有标准化密钥非空时，pi-ai 才会记录派生引用；留空密钥会具化一个空的、不带引用的 profile，以便使用提供方原生凭据发现。

只有当联接所得的行识别出该页面派生的精确 `<ROUTE>_API_KEY` 引用，并将其报告为已配置且可写时，删除操作才会清除该凭据。它会先取消设置该凭据，再取消设置用户层 profile；如果 settings 阶段失败，该行及其已冻结的目标仍可见，便于重试。两项 unset 都具备幂等性。自定义引用、环境凭据、缺失的凭据，以及联接无法识别目标的凭据均会保留。行的无障碍 Edit/Delete 名称以及破坏性对话框的标题、说明和最终操作都使用同一个稳定的 `Display Name (route-id)` 标识；当两个字符串相同时，标识会简化为路由 id。对话框会说明是否一并删除已存密钥，并在自身内显示操作失败，而不是用加载错误横幅替换整个页面。行只根据不含值的联接结果展示 API 密钥状态：确认已配置的引用凭据显示为绿色实心点，确认缺失的具名引用显示为红色实心点，无引用的提供方原生认证或无法取得凭据补充信息时则不显示状态点。每个状态点都有无障碍文案和工具提示；「应用」成功后的本地状态消息会使用同一个提供方标识，且绝不回显任何机密内容。

## 曾考虑的替代方案

**添加跨领域事务 RPC。**settings 与凭据分属不同的主管服务与持久存储；引入新的 Host 事务会扩大公开 wire 面，而且仍需要补偿提供方特定的持久化失败。UI 检查点让当前的有序阶段变得可恢复，无需添加第四项配置约定。

**删除被移除 profile 所指定的每一个凭据引用。**自定义引用可能被共享、由外部管理，或有意在 profile 反复增删时存留。与该页面派生目标精确相等，再加上已配置且可写的状态，是页面所能获得的最小范围证据；比这更弱的判定都有可能删除不属于它的凭据。

**先删除 settings，再重建 profile 以作补偿。**浏览器只持有脱敏后的子树，无法忠实重建并发编辑。先删除凭据可以让权威 profile 在部分失败时仍然可见，并且无需合成配置就能安全重试。

## 后果

Models 页可以从任一第二阶段失败中恢复，无需重新加载，也不会泄露机密或产生虚假的并发冲突；空密钥的 pi-ai profile 会保留 Bedrock、Vertex 与其他提供方原生认证。已确认的状态清晰可见，同时不会把路由存活状态、原生认证或凭据查询失败误报为错误；即使该行继续显示绿色，密钥替换成功也仍然可观察。删除由页面管理的提供方不再遗留可重用的本地密钥，而存在歧义的凭据会有意保留，交由手动管理。保存与删除在跨持久存储时仍非原子操作：进程可能在两个阶段之间崩溃，但它们的顺序与幂等性会留下可观察、可重试的状态。组件测试固定了部分成功后的重试、空密钥原生认证、密钥首尾空白处理、状态可见性、目标标识、清理所有权，以及凭据／settings 拒绝顺序；无密钥的浏览器场景固定了双语无障碍文案，并验证确认删除会同时清除 `settings.yaml` profile 与 `.credentials.yaml` 条目。此决策细化了 [web 配置平面 note](../architecture/2026-07-30-web-config-plane.zh.md) 中记录的 Models 应用语义。
