New credentials data-structure page (type-equiv manifested), group README, rewritten llm-deepseek/llm-pi-ai READMEs (dynamic configuration, dict profiles, credential chain), capability-seams/service-role registration, Agent Note (bilingual), demo compositions mounting settings-local + credentials-local with no inline key plumbing, installSettingsSection consumer helper on the settings seam (deduplicating both adapters' wiring), jscpd symmetry markers for the provider twins, runtime-closure additions for python/sdk-runtime, and doc-budget ceilings AGENTS.md 1750→1755 / packages/README.md 850→865 for the structural one-line group rows.
51 lines
2.9 KiB
Markdown
51 lines
2.9 KiB
Markdown
# User Credentials
|
|
|
|
English | [中文](credentials.zh.md)
|
|
|
|
The credential seam of [dsh-credentials](../../packages/credentials/credentials) keeps secrets out of configuration: settings sections and `cordis.yml` entries carry *references* (environment-variable names), providers such as [dsh-credentials-local](../../packages/credentials/credentials-local) own the values, and consumers resolve a reference once per operation — the LLM adapters resolve once per model request, so a rotated credential reaches the very next request without any restart. One seam-wide rule binds every provider: an empty stored value is absent everywhere.
|
|
|
|
Source: [`packages/credentials/credentials/src/index.ts`](../../packages/credentials/credentials/src/index.ts)
|
|
|
|
## Identity
|
|
|
|
A reference names one credential as a POSIX-style environment-variable name. The brand keeps references from mixing with other cross-boundary strings; construction validates the shell-identifier shape.
|
|
|
|
```ts type-equiv
|
|
/** Nominal reference to one credential: a POSIX-style environment-variable name. */
|
|
type CredentialRef = Branded<'CredentialRef'>
|
|
```
|
|
|
|
## Resolution
|
|
|
|
`resolve(ref)` returns the value with the provider-defined source layer that supplied it, or `undefined` while unconfigured. Consumers re-resolve at each operation and never cache across operations — that per-operation read is the hot-update mechanism.
|
|
|
|
```ts type-equiv
|
|
/** One resolved credential value and the source layer that supplied it. */
|
|
interface ResolvedCredential {
|
|
/** The non-empty secret value. */
|
|
value: string
|
|
/** Provider-defined source layer id (the local provider uses `env` and `file`). */
|
|
source: string
|
|
}
|
|
```
|
|
|
|
## Description
|
|
|
|
`describe(ref)` answers configuration surfaces without ever exposing a value: whether the reference resolves, from which layer, and whether `set` would currently succeed. The local provider reports a reference supplied by the live process environment as `writable: false` — a write would appear to succeed while resolution kept returning the shadowing value, so the seam rejects it and the UI can render the reference read-only up front.
|
|
|
|
```ts type-equiv
|
|
/** Source and writability facts for one reference, safe for configuration UIs — never the value. */
|
|
interface CredentialInfo {
|
|
/** Whether {@link Credentials.resolve} would currently return a value. */
|
|
configured: boolean
|
|
/** Source layer currently supplying the value; absent while unconfigured. */
|
|
source?: string
|
|
/** Whether {@link Credentials.set} would currently succeed for this reference. */
|
|
writable: boolean
|
|
}
|
|
```
|
|
|
|
## Change commits
|
|
|
|
`credentials/updated (ref)` fires after a committed change to a provider-managed source — a `set`, an `unset`, or an external edit observed in storage. Ambient process-environment changes are not observable and never emit. Consumers do not need the event (they re-resolve per operation); it exists for configuration surfaces refreshing a "configured" badge.
|