Files
deepseek-harness/.agents/notes/implemented/architecture/2026-09-19-profile-owned-live-configuration.md
T
Magolor 5249d9a4ce fix: prefer saved credentials and use environment keys in headless (#5483)
* ui: show locked API key environment reference

* fix(ui-settings-models): skip unused pi-ai credential reference

* fix(ui-settings-models): show active provider auth source

* test(llm): cover provider auth check failures

* docs(ui-settings-models): clarify active provider authentication

* test(web): update model key copy snapshots

* fix(ui-settings-models): clarify native authentication source hint

* fix: address PR 5483 review feedback

* docs(llm): state empty auth lookup behavior

* fix: refresh auth hints with credential snapshots

* fix: require credential refresh revision

* test: cover auth status projection

* fix: refresh catalog and browser expectations after rebase

* fix: keep auth status projection internal and explicit

* fix: preserve credential source checks with signed-in account rows

* test: pin Models authentication instead of inheriting host keys

* fix: prioritize stored credentials across providers

* fix: use one environment fallback hint

* docs: refresh credential contract

* docs: refresh config catalog

* test: align provider hint verification

* fix: use provider-native auth hints and endpoints

* fix: cover oauth-capable provider auth hints

* fix: show canonical endpoint defaults

* fix: avoid misleading endpoint fallback

* fix: label catalog endpoint defaults

* fix: shorten auth hints with hover details

* fix: clarify native auth resolution

* test: align DeepSeek endpoint hint

* fix: pair help button corner shape

* fix: address credential precedence review

Record the stored-credential precedence in a superseding Agent Note and
an upgrade guide, and align the credentials subsystem page, package
READMEs, and JSDoc with the order file > launch env > $cwd/.env >
$DSH_HOME/.env.

Report each pi-ai route's catalog endpoint and native-auth environment
names through the provider directory, check the names against the
installed pi-ai resolvers, and remove the llm/checkAuth and credential
describe operations that no Models page code calls.

Restore the route-derived key reference and the home expansion that
reads the home directory only for a leading ~.

* fix: clarify model authentication guidance

* fix: explain native provider OAuth requirements

* fix: keep authentication guidance method neutral

* fix: show credential reference source in model editor

* fix: use environment authentication in headless profile

* fix: validate headless authentication and current provider metadata

* test: retain authentication guidance coverage with account catalog updates

* test: retain writable Models credentials with the pinned environment
2026-10-13 10:10:06 +08:00

3.8 KiB

Agent Note: Keep live configuration in the owning profile

Status: implemented

English | 中文

Problem

Separate settings registrations duplicated schemas, defaults, persistence, and notifications. They also placed stored user settings above deployment overlays without preserving which composition source supplied a value. Using the Loader's resolved Config gives validation and consumers one owner and preserves its lifecycle decisions.

Decision

A plugin declares every configurable value in its Cordis Config. Fields that can change without remounting use .volatile(); consumers read their references during operations. Settings enumerates those fields for forms and never supplies business configuration. The profile editor writes cordis.patch.yml and applies the ordinary Loader reconciliation path.

Form writes target the active profile. Home patches and command-line overlays remain higher-priority deployment inputs; an edit they would shadow fails before persistence. Two plugin instances are addressed by their distinct profile entry ids. Nested Includes retain independent ownership and are not writable through the profile form.

Cordis config patches replace complete entry configs. An edit preserves ordinary fields and unedited secrets, including raw configuration expressions. A field reset restores the currently inherited value; resetting the complete entry removes its config overrides so later bundle changes are inherited. Other edits store the entry's complete config in the profile row: the ordinary fields as composed at write time plus every volatile field. Later bundle changes to those fields do not reach that profile until the entry's config override is removed. In the shipped bundles this pins permission.presets after a default-preset change, agent-presets after a preset choice, agent-loop.agents after a parallelism edit, and web-search-deepseek.apiKeyEnv after a Web Search edit, and the client marks every volatile field of such a row as overridden, not only the edited one. Narrowing a write to the edited fields needs merge semantics for patch config, which Include does not provide.

The removed $DSH_HOME/settings.yaml is imported once into the active profile when the Loader has settled every entry after Settings starts: section ids are entry ids, with ui-developer-tools → ui-settings, ui-onboarding → ui-settings-general, and shell → the platform's shell executor entry. The file is renamed to settings.yaml.imported before the first write, so the import never repeats; a rejected section is logged and stays in the renamed file.

Alternatives considered

The rejected alternative is retaining settings as a second store behind a configuration adapter: that still requires reconciling two durable documents and deciding which wins after concurrent edits or restart. The removed global settings document offered cross-profile preferences; this design deliberately makes persisted form values profile-specific. Reintroducing shared preferences requires an explicit shared Cordis layer and a defined write destination.

Consequences

This supersedes only the non-secret settings tier in configuration source ownership; its environment restrictions remain applicable, and stored credential precedence supersedes its credential ordering. Volatile references own reference lifetime and ordinary update behavior.

Real profile tests cover multiple instances, persisted restart, invalid edits, stale revisions, higher-layer rejection, secret redaction, and configuration expressions. Browser tests exercise form writes and reset through the assembled application. Runtime reference identity is checked across live edits.