mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
Rebuild of the region machinery (PR3) on the post-#904 Typert projection: renderPageRegion/renderInheritedPage live in dsh-typert-generator beside the projection; scripts/gen-cordis-catalog.ts owns the curated SERVICE_PAGE / EVENT_SCOPE_PAGE / SERVICE_WALK_EXEMPTIONS / LINK_MAP partition (fail-loud in both directions, with the independent Context-merge scan backstopping the projection's blind spot), spliceRegion, and the guarded pair auto-record. docs/cordis-catalog/ is deleted: the flat events/services catalogs dissolve into per-page regions and docs/cordis-catalog/core moves to docs/cordis-api/ with the inherited tier as its own generated page. The partition absorbs the post-regrouping surface: ctx.typert → invariants.md, ctx.directoryPicker → workspace.md, skills/* events → skills.md, and the four launcher-provided tui accessor values join the named exemptions.
134 lines
7.0 KiB
Markdown
134 lines
7.0 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`, `file`, `project-env`, and `user-env`). */
|
|
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.
|
|
|
|
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
|
|
<a id="cordis-surface"></a>
|
|
|
|
## Cordis surface
|
|
|
|
Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — this section is byte-identical in both language sides of the page. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` surface lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
|
|
|
|
<a id="ctxcredentials--credentials-abstract-seam"></a>
|
|
|
|
### `ctx.credentials` — `Credentials` (abstract seam)
|
|
|
|
Abstract credential service. Providers implement the four operations over their source layers; one seam-wide rule binds them all: an empty stored value is absent everywhere — `resolve` skips it, `describe` reports it unconfigured — so a blank never masquerades as a configured secret.
|
|
|
|
```ts cordis-catalog
|
|
/**
|
|
* Resolve one reference to its current value. Resolution is per call:
|
|
* consumers re-resolve at each operation and must not cache across
|
|
* operations — that per-operation read is what makes a changed credential
|
|
* reach the next operation without a restart.
|
|
* @param ref - the reference to resolve.
|
|
* @returns the value and its source, or `undefined` while unconfigured.
|
|
*/
|
|
abstract resolve(ref: CredentialRef): Promise<ResolvedCredential | undefined>
|
|
|
|
/**
|
|
* Describe one reference for configuration surfaces without exposing the
|
|
* value.
|
|
* @param ref - the reference to describe.
|
|
* @returns configured state, supplying source, and writability.
|
|
*/
|
|
abstract describe(ref: CredentialRef): Promise<CredentialInfo>
|
|
|
|
/**
|
|
* Durably store one value in the provider-managed writable source. Rejects
|
|
* while a read-only source shadows the reference — the write would appear
|
|
* to succeed while resolution keeps returning the shadowing value — and
|
|
* rejects an empty value (use {@link unset}).
|
|
* @param ref - the reference to store.
|
|
* @param value - the non-empty secret value.
|
|
*/
|
|
abstract set(ref: CredentialRef, value: string): Promise<void>
|
|
|
|
/**
|
|
* Remove one reference from the provider-managed writable source; removing
|
|
* an absent reference is a no-op. Rejects while a read-only source shadows
|
|
* the reference, like {@link set}.
|
|
* @param ref - the reference to remove.
|
|
*/
|
|
abstract unset(ref: CredentialRef): Promise<void>
|
|
```
|
|
|
|
Source: [`packages/credentials/credentials/src/index.ts:77`](../../packages/credentials/credentials/src/index.ts)
|
|
|
|
<a id="credentials-events"></a>
|
|
|
|
### `credentials/*` events
|
|
|
|
<a id="credentialsupdated--emit"></a>
|
|
|
|
#### `credentials/updated` — emit
|
|
|
|
Committed change to a provider-managed credential source: a `set`, an `unset`, or an external edit observed in storage. Ambient process-environment changes are not observable and never emit. Listener failures are contained and logged — a sync throw and an async rejection alike — without changing the committed operation's outcome, except `INVARIANT`-coded failures, which rethrow after every listener ran; that rethrow reaches the emitter only from synchronous listeners, so invariant checks on this event must not be async functions.
|
|
|
|
```ts cordis-catalog
|
|
/**
|
|
* Committed change to a provider-managed credential source: a `set`, an
|
|
* `unset`, or an external edit observed in storage. Ambient
|
|
* process-environment changes are not observable and never emit. Listener
|
|
* failures are contained and logged — a sync throw and an async rejection
|
|
* alike — without changing the committed operation's outcome, except
|
|
* `INVARIANT`-coded failures, which rethrow after every listener ran;
|
|
* that rethrow reaches the emitter only from synchronous listeners, so
|
|
* invariant checks on this event must not be async functions.
|
|
* @param ref - the reference whose stored value changed.
|
|
* @mode emit
|
|
*/
|
|
'credentials/updated'(ref: CredentialRef): void
|
|
```
|
|
|
|
Source: [`packages/credentials/credentials/src/index.ts:67`](../../packages/credentials/credentials/src/index.ts)
|
|
<!-- END GENERATED cordis-surface -->
|