你在桌面端「添加自定义模型服务」时填的 API 密钥,今天是以明文写进一份普通配置文件 的,任何能读你用户目录的程序、备份或同步工具都能看到;而目录里自带的那几家服务的密钥已经加密存进系统钥匙串。这件事要让自定义服务的密钥也进 Mac 的钥匙串,配置文件里只留一个引用,以前明文存下的密钥提示你重填一次。只有你一个用户、密钥只在你自己的 Mac 上,所以不是紧急的线上问题,但密钥一旦随备份或误传外泄,损失是真金白银的调用费。owner 2026-09-17 裁决把这件事收窄到只做 macOS:Windows 版、崩溃报告与导出的全面脱敏、增删改的原子性、双系统验证矩阵都删掉,今天没有 Windows 用户,需要时可以重开。
范围收窄(owner 2026-09-17 裁决)
保留(仅 macOS):自定义服务密钥进钥匙串、配置只留引用、发现旧明文值提示重填 —— 由 jinjunnn/alpha-code#1343 承载;AC2 改写为 macOS、AC4 改写为咽喉点形态;AC1、AC3、AC6、AC7 原文不变。
删去:Windows(AC2 原文的 Windows 半边)—— 无 Windows 用户与测试机,证据手段不存在;崩溃报告/诊断/备份/导出的全面脱敏(AC4 原文)—— 全称否定、无唯一通路;增删改轮换的原子性(AC5);双系统打包矩阵与产物扫描(AC8)—— AC1–AC4 的重述且 Windows 半边不可执行。均可随时重开。
alpha-code#1343 合并后按证据验收本需求;AC2 的打包版证据随下一次 Release Candidate 冒烟采集。
简明目的
自定义模型的 API Key 不能再写进普通配置文件;应用只保存一个引用,真正的密钥交给 macOS/Windows 的安全存储。
Outcome(专业定义)
自定义 provider credential 由 Electron main 通过 OS-protected vault 创建、解析、轮换和删除;alpha.jsonc 及环境 mutable roots 只保存 opaque secret reference。renderer、extension、日志、诊断、备份与导出均不能获得或持久化原始 secret,且 vault 不可用时 fail closed。
Complexity
L — 凭据生命周期、跨 OS 安全存储和 packaged 验证属于高风险安全面。
Context
当前自定义 provider key 可能明文存在 alpha.jsonc,某些 vault fallback 也可能落成明文文件。原需求包含“迁移既有 inline credential”;当前没有既有用户,迁移会增加读取旧明文和回滚泄漏面,应直接 hard cut。
Scope
(2026-09-17 范围已收窄,以上方「范围收窄」一节为准。)
定义 opaque credential reference 与 main-owned vault broker。
macOS 使用系统保护能力;Windows 使用当前用户/应用边界的 OS-protected storage。
provider 调用链按引用短时解析 secret,不通过 renderer config/IPC 返回原值。
支持 create/update/delete/rotate 与不可用、损坏、锁定状态。
日志、错误、diagnostics、backup、export 和 crash report 统一脱敏。
Settings([REQ-090] Settings、Model、Permission、Dialog 与 Recovery 使用 Alpha 自有交互 #205 )只编辑/替换 credential,不读取已有 secret。
Non-goals
不迁移、导入或兼容旧 alpha.jsonc inline credential;发现旧值时拒绝并要求重新录入。
不提供 plaintext file fallback、可逆“显示原密钥”、通用密码管理器或云端同步。
不改变平台/API token policy;本票只处理本地自定义 provider secret。
不把 secret value 写入 [REQ-098] prod、beta 与 dev 的可变扩展状态严格隔离 #209 环境 roots;只写 reference。
Acceptance criteria
AC1. 普通配置、receipt、grant 与环境文件中只存在 opaque reference,不存在 provider credential value。
AC2. macOS 打包版的自定义服务密钥由系统钥匙串保护。 (2026-09-17 按 owner 裁决改写,原文见编辑历史)
AC3. renderer、extension 和普通 IPC 不能读取 secret;只有 main-owned provider 调用链可按引用使用。
AC4. 自定义服务密钥原值离开钥匙串的唯一通路是后台进程按引用解析后注入模型调用;配置文件、界面与日志只见引用或末四位。 (2026-09-17 按 owner 裁决改写,原文见编辑历史)
AC5. create/update/delete/rotate 具有原子结果;崩溃或重试不会留下可用旧明文或引用错配。 —— 2026-09-17 删除(owner 裁决):增删改轮换的原子性与崩溃恢复在只有 owner 一个用户时收益很小。
AC6. vault 锁定、损坏、引用缺失或 OS 能力不可用时 provider 调用 fail closed,并提示重新录入/修复。
AC7. 旧 inline credential 不被自动读取/迁移;配置发现旧值时明确拒绝且不会把值写入日志。
AC8. macOS/Windows packaged secret matrix 与仓库/产物 secret scan 均无泄漏。 —— 2026-09-17 删除(owner 裁决):双系统矩阵与产物扫描是 AC1–AC4 的重述,且 Windows 半边不可执行。
Evidence map
AC
Evidence surface
AC1
config schema + secret-reference persistence tests
AC2
macOS 打包版上添加一次自定义服务、读回配置文件只见引用(随 Release Candidate 冒烟采集,见 jinjunnn/alpha-code#1343 退出条件)
AC3
main-broker production wiring + IPC denial tests
AC4
jinjunnn/alpha-code#1343 的测试:配置文件、界面与日志只见引用或末四位;原值只在后台进程按引用解析后注入模型调用
AC5
—(2026-09-17 已删除)
AC6
vault unavailable/corrupt reference negative tests
AC7
legacy-inline rejection fixture
AC8
—(2026-09-17 已删除)
Acceptance owner
待指定;未指定前不得进入 Ready,也不得关闭。
设计要点
reference 不包含 secret 衍生片段或可预测文件路径。
main broker 返回“已配置/缺失/需重录”等状态,不返回 secret。
所有 fallback 必须仍由 OS 保护;无保护能力时宁可禁用 provider。
轮换和删除保留事务/崩溃恢复,这是正确性而非旧用户兼容。
潜在问题与风险
plaintext fallback 会让“使用 vault”的表面实现失去意义。
renderer 可读 secret 会被 XSS/extension compromise 直接利用。
diagnostics/export 常被主调用链遗漏,是高概率泄漏点。
自动迁移旧明文会扩大可读旧格式的攻击窗口。
过时性与兼容性结论
需求有效且未实现。旧 inline credential migration、plaintext fallback 和回滚导出均不需要;发现旧值直接拒绝并要求重新录入。保留轮换、删除、事务、崩溃恢复和 vault future-version fail-closed。
关联与职责边界
Delivery plan / 建议子票
建议 CODE:OS vault abstraction 与 macOS/Windows backend。 —— 2026-09-17 不再建票(owner 裁决收窄;剩余工作见下方子票)
建议 CODE:provider/config/Settings 生产调用链改为 opaque reference,并删除 plaintext fallback。 —— 2026-09-17 不再建票(owner 裁决收窄;剩余工作见下方子票)
建议 VERIFY:双 OS packaged、日志/导出/崩溃与 secret scan 矩阵。 —— 2026-09-17 不再建票(owner 裁决收窄;剩余工作见下方子票)
jinjunnn/alpha-code#1343 自定义模型服务的密钥存进 macOS 钥匙串,配置文件只留引用(AC1、AC2、AC3、AC4、AC6、AC7)
方案基线(owner 2026-09-17 批准,升 Ready 的门;#1343 的 Boundary 按其 §4.1 改写):docs/design/2026-09-17-req226-custom-provider-keychain-baseline.md 。
Dependencies
你在桌面端「添加自定义模型服务」时填的 API 密钥,今天是以明文写进一份普通配置文件的,任何能读你用户目录的程序、备份或同步工具都能看到;而目录里自带的那几家服务的密钥已经加密存进系统钥匙串。这件事要让自定义服务的密钥也进 Mac 的钥匙串,配置文件里只留一个引用,以前明文存下的密钥提示你重填一次。只有你一个用户、密钥只在你自己的 Mac 上,所以不是紧急的线上问题,但密钥一旦随备份或误传外泄,损失是真金白银的调用费。owner 2026-09-17 裁决把这件事收窄到只做 macOS:Windows 版、崩溃报告与导出的全面脱敏、增删改的原子性、双系统验证矩阵都删掉,今天没有 Windows 用户,需要时可以重开。
范围收窄(owner 2026-09-17 裁决)
jinjunnn/alpha-code#1343承载;AC2 改写为 macOS、AC4 改写为咽喉点形态;AC1、AC3、AC6、AC7 原文不变。alpha-code#1343合并后按证据验收本需求;AC2 的打包版证据随下一次 Release Candidate 冒烟采集。简明目的
自定义模型的 API Key 不能再写进普通配置文件;应用只保存一个引用,真正的密钥交给 macOS/Windows 的安全存储。
Outcome(专业定义)
自定义 provider credential 由 Electron main 通过 OS-protected vault 创建、解析、轮换和删除;
alpha.jsonc及环境 mutable roots 只保存 opaque secret reference。renderer、extension、日志、诊断、备份与导出均不能获得或持久化原始 secret,且 vault 不可用时 fail closed。Complexity
L — 凭据生命周期、跨 OS 安全存储和 packaged 验证属于高风险安全面。
Context
当前自定义 provider key 可能明文存在
alpha.jsonc,某些 vault fallback 也可能落成明文文件。原需求包含“迁移既有 inline credential”;当前没有既有用户,迁移会增加读取旧明文和回滚泄漏面,应直接 hard cut。Scope
(2026-09-17 范围已收窄,以上方「范围收窄」一节为准。)
Non-goals
alpha.jsoncinline credential;发现旧值时拒绝并要求重新录入。Acceptance criteria
AC1. 普通配置、receipt、grant 与环境文件中只存在 opaque reference,不存在 provider credential value。
AC2. macOS 打包版的自定义服务密钥由系统钥匙串保护。 (2026-09-17 按 owner 裁决改写,原文见编辑历史)
AC3. renderer、extension 和普通 IPC 不能读取 secret;只有 main-owned provider 调用链可按引用使用。
AC4. 自定义服务密钥原值离开钥匙串的唯一通路是后台进程按引用解析后注入模型调用;配置文件、界面与日志只见引用或末四位。 (2026-09-17 按 owner 裁决改写,原文见编辑历史)
AC5.
create/update/delete/rotate 具有原子结果;崩溃或重试不会留下可用旧明文或引用错配。—— 2026-09-17 删除(owner 裁决):增删改轮换的原子性与崩溃恢复在只有 owner 一个用户时收益很小。AC6. vault 锁定、损坏、引用缺失或 OS 能力不可用时 provider 调用 fail closed,并提示重新录入/修复。
AC7. 旧 inline credential 不被自动读取/迁移;配置发现旧值时明确拒绝且不会把值写入日志。
AC8.
macOS/Windows packaged secret matrix 与仓库/产物 secret scan 均无泄漏。—— 2026-09-17 删除(owner 裁决):双系统矩阵与产物扫描是 AC1–AC4 的重述,且 Windows 半边不可执行。Evidence map
jinjunnn/alpha-code#1343退出条件)jinjunnn/alpha-code#1343的测试:配置文件、界面与日志只见引用或末四位;原值只在后台进程按引用解析后注入模型调用Acceptance owner
待指定;未指定前不得进入 Ready,也不得关闭。
设计要点
潜在问题与风险
过时性与兼容性结论
需求有效且未实现。旧 inline credential migration、plaintext fallback 和回滚导出均不需要;发现旧值直接拒绝并要求重新录入。保留轮换、删除、事务、崩溃恢复和 vault future-version fail-closed。
关联与职责边界
alpha-work#8:跨仓 purpose-token/action policy;不由本票实现。Delivery plan / 建议子票
建议 CODE:OS vault abstraction 与 macOS/Windows backend。—— 2026-09-17 不再建票(owner 裁决收窄;剩余工作见下方子票)建议 CODE:provider/config/Settings 生产调用链改为 opaque reference,并删除 plaintext fallback。—— 2026-09-17 不再建票(owner 裁决收窄;剩余工作见下方子票)建议 VERIFY:双 OS packaged、日志/导出/崩溃与 secret scan 矩阵。—— 2026-09-17 不再建票(owner 裁决收窄;剩余工作见下方子票)jinjunnn/alpha-code#1343自定义模型服务的密钥存进 macOS 钥匙串,配置文件只留引用(AC1、AC2、AC3、AC4、AC6、AC7)方案基线(owner 2026-09-17 批准,升 Ready 的门;
#1343的 Boundary 按其 §4.1 改写):docs/design/2026-09-17-req226-custom-provider-keychain-baseline.md。Dependencies