Configuration storage
Configuration storage boundary
ConfigStore retains its public configuration types, general defaults and validators.
The provider codec in src/store/config/brainProviders.ts owns
DEFAULT_OPENAI_COMPATIBILITY; callers use sanitizeBrainProviders(input)
without supplying defaults. ConfigStore reads and brainProviders(input) use
this same normalizer, while src/brain/providers.ts imports the baseline directly
for openAiCompatibilityFor(entry) during Chat Completions registration.
Missing or malformed compatibility fields resolve independently to the unchanged
conservative baseline; non-OpenAI entries retain no compatibility block.
Omitted API keys retain the current key on provider edits, and stored keys never
enter the public provider view: get() maps each provider to
apiKeySet and drops the key (src/store/configStore.ts:893). The codec performs no database or network
operations and adds only per-entry validation; its stored type comes from its
existing membership list without importing ConfigStore.
The web compatibility parity test reads the codec owner to pin the browser defaults.
src/store/config/limits.ts owns the private brain/runtime bound
tables and runtime defaults. The brain table is initialized once from the store's canonical public
defaults, avoiding a runtime import cycle or a second copy (src/store/configStore.ts:352). Web parity tests read both owners and
keep the existing browser tables pinned to the same bounds, including the stream heartbeat floor.
They compare source text, because the web may not import the daemon: web/tests/modules/settings/brainLimitsParity.test.ts
and runtimeLimitsParity.test.ts read src/store/configStore.ts and src/store/config/limits.ts, and the floor is
mirrored in web/lib/streamWatchdog.ts.
update checks problem-reporting consent and the expected revision under the write lock before
calling private validatePatch and prepareStoredPatch (src/store/configStore.ts:1412-1423). Preparation keeps the existing field merge
and validation order. A provider patch then cascades account/settings references before writing the
settings row, records changed consent and clears the outbox when disabled, all inside the same locked SQLite
transaction. The provider catalog prune (retainProviderModels) runs in that locked callback too, but it only
edits the in-memory /models snapshot and requests a background pass, so it is not rolled back with the write
(src/store/configStore.ts:1426-1436, src/brain/providerModelCatalog.ts:357-366). The problem-reporting callback runs only after commit. An omitted
provider patch performs no cascade/catalog effect; an unchanged reporting flag emits no consent event
or callback. The settings API remains the real consumer of this boundary.
The existing retired-config, live-call and key-account raw cleanups share private migrateRaw
(src/store/configStore.ts:1086, :1119-1120, :1133-1134).
Each mutator explicitly returns whether it changed the document. Missing, malformed, non-object
and unchanged rows receive no write and keep their original bytes/revision; changed rows retain
unrelated keys and advance the revision once (src/store/configStore.ts:1069-1081). Historical matching conditions are unchanged. This
helper is local to ConfigStore and adds no migration registry, boot hook or database access cost.