description: "面向用户与维护者的凭据 seam:在不把机密值写进配置的前提下解析、描述或存储凭据——引用值与持久化记录。"
English | 中文
dsh-credentials 通过让 settings 与 cordis.yml 引用 DEEPSEEK_API_KEY 等密钥名称,使机密值留在配置之外。它还存储持久化的按插件组织的凭据记录,包括授权 grant 与提供方环境值。轮换后的已存储密钥会作用于下一次请求,无需重启或修改配置。配置界面可以报告密钥或记录是否已设置、来自哪里及能否写入,而不会暴露值。空密钥值视为不存在,而空记录仍表示一项有意存储的凭据。
本包是产品中负责存储与查询机密值的部分:密钥只存一次、处处按名引用,并可在任意时刻读取、检查或移除。它还保存持久化的凭据记录,让插件可以为自身 id 存储、更新或移除它持有的凭据。产品的默认组合已包含凭据存储;自定义组合只需加载本地存储包并给出文件路径。
只要配置需要与机密值绝缘,就使用凭据存储:需要同步、共享或渲染进配置界面的设置文件,或希望在不改配置的情况下轮换密钥的团队。当插件必须保存没有单一环境变量的凭据——登录流程产生的授权 grant,或提供方环境值——并希望配置界面能列出用户已授权什么时,请使用记录。配置界面能显示某个密钥或记录是否已设置、来自哪里、能否修改——但绝不显示值本身。如果只需要一个固定的环境变量,直接读该变量即可,无需存储。
加载本地存储包并给出文档路径:
- name: '@deepseek-ai/dsh-credentials-local'
config:
path: /absolute/path/to/.credentials.yaml
本地存储 README 拥有完整配置面;生成的配置目录是穷尽式字段清单。
import type { Context } from '@deepseek-ai/cordis'
import { credentialRef } from '@deepseek-ai/dsh-credentials'
declare const ctx: Context
const ref = credentialRef('DEEPSEEK_API_KEY') // POSIX shell identifier, branded
const hit = await ctx.credentials.resolve(ref) // { value, source } | undefined
const info = await ctx.credentials.describe(ref) // { configured, source?, writable } — never the value
await ctx.credentials.set(ref, 'sk-…') // rejects while a read-only source shadows the ref
await ctx.credentials.unset(ref) // no-op when absent; same shadowing rule
用 set 存储密钥、用 unset 移除、用 describe 检查状态、在操作需要时用 resolve 读取当前值。describe 报告密钥是否已设置、来自哪里、能否写入——它绝不返回值。
插件按 <scope>/<id> 寻址每条记录——自身注册名加一个自选 id,例如提供方路由键——并读取、修改或移除它所持有的内容:
import type { Context } from '@deepseek-ai/cordis'
import { credentialKey } from '@deepseek-ai/dsh-credentials'
declare const ctx: Context
const key = credentialKey('llm-pi-ai', 'openai-codex') // <owner>/<id>, branded
const hit = await ctx.credentials.readRecord(key) // CredentialRecord | undefined
await ctx.credentials.describeRecord(key) // { configured, kind?, writable } — never the value
await ctx.credentials.listRecords() // [{ key, kind }] — never values
await ctx.credentials.modifyRecord(key, async () => ({ kind: 'grant', payload: { token: '…' } }))
await ctx.credentials.deleteRecord(key) // no-op when absent
modifyRecord 是唯一写路径:它让你的变更函数看到写入取得独占那一刻的记录,返回 undefined 则保持原状。记录没有空值规则——一条既无 key 也无环境值的记录,陈述的是其拥有者确认了 ambient 认证——配置界面还可以枚举每条记录,显示你已授权什么,并找出已卸载插件留下的记录。
settings 分节或 cordis.yml 条目按名引用密钥,而不是包含密钥本身——例如 LLM(大语言模型)适配器接受 apiKeyEnv:
apiKeyEnv: DEEPSEEK_API_KEY
需要该密钥的请求使用它当前存储的值,因此轮换密钥会作用于紧随其后的下一次请求——无需重启,无需改配置。
DEEPSEEK_API_KEY=… dsh(或 CI 机密、容器 -e)在本轮运行中优先,并被报告为只读;请先在启动 shell 中清除该变量,再存储其他值。当包级约定不够用时阅读以下页面。它们从共享子系统词汇逐步进入随附存储与能力架构。
CredentialRef/CredentialKey、按操作解析、对 UI 安全的信息、提供方层与生成的 cordis 接口面。经由消费方适配器间接生效:适配器解析每个凭据引用,并拥有值所授权的全部模型可见用途。
无直接失效;解析出的值绝不进入请求前缀。
这些限制说明本包何时不合适或需要特别注意。它们是当前包约束,不是任务积压。
list() 没有当前消费方。记录出于无 schema 可发现的原因则可枚举。<owner>/<id> 寻址。describe()。listRecords() 与拥有该 scope 的注册表之间做的连接,seam 自身没有可供核对的注册表。