密钥管理
SecretRef 三源机制、inline AES-256-GCM 封套、exec 环境隔离与降级态保护。
SecretRef 三源
| Source | 说明 | 换机恢复代价 |
|---|---|---|
inline | 明文经 AES-256-GCM 封套后落盘 | 密文与 spec.key 同机 |
env | 环境变量引用 | 重放注入方 |
live | 运行时回调(ProviderLiveKeyFn) | 重放注入方 |
vault 已删除
vault 源已删——它是一个无实现方注入的 Resolver 接口,且 master key 文件坐在 Export 默认包含面里。
inline 封套
明文 API Key
↓ config.MapSecretValues(spec, box.Seal)
AES-256-GCM 密文 → hypervisor.db
密钥 → {DataDir}/secrets/spec.key (0600, 目录 0700)
inline 不再是服务端禁忌——之前那条约束只存在于文档里,代码从不拒绝。
选型按换机恢复代价
| Source | 威胁模型 |
|---|---|
inline | 拷走 DB 不带 key → 全部 provider 失效(正是要的) |
env / live | 值不落盘 |
exec 环境净化
四层防护
| 层 | 机制 |
|---|---|
| 1 | 静态模式表(*_KEY、*_SECRET 等,INV-SEC-04) |
| 2 | SecretRef{source:env} 变量名登记(INV-SEC-03) |
| 3 | 出网脱敏 config.RedactSecrets 单点(INV-SEC-02) |
| 4 | 进程环境 SanitizeEnv |
INV-SEC-02:出网脱敏
SecretRef.MarshalJSON 吐含明文的 storage view(落盘要值)。
脱敏只有一个执行点 config.RedactSecrets。
降级态保护(INV-PERSIST-07)
缺陷链
丢 spec.key
↓ decodeSpec 清空打不开的 inline key
↓ Cell 挂上(降级)
↓ 任何一次落 spec 的写(改名、加 MCP、编辑渠道)
↓ 已成空串的字段重新封密
↓ Seal("") == "",omitempty 丢字段
↓ 磁盘上的密文没了
三扇写门
| 门 | 答案 |
|---|---|
persistCellSpec | 查台账拒绝(ErrDegradedSecretOverwrite,409) |
Cells().Create | 纯 INSERT(够不到已存在的行) |
convergePersistedSpec | 原样保留(SealedOriginals 放回) |
台账
h.degradedSecrets / h.degradedSharedProviders 两侧台账。
写成功后必须按写入内容重算台账——漏了这步,重填凭据后下一次编辑仍被拒。
共享 Provider 池
合并而非拒绝:池是按名字的数组,拒绝会让改 A 被 B 的坏 key 扣为人质。
判据放在 SharedProviderStore.Save 内部(两个调用方自动受保护)。
相关文档
- Provider 系统 →
provider-system.md - CellSpec 总览 →
cellspec-overview.md - 数据韧性 →
data-resilience.md