ADR-034: Remove the ExtensionConfiguration default-provider fallback
- Status
-
Accepted
- Date
-
2026-06-24
- Authors
-
Netresearch DTT GmbH
Context
Llm carried a session-level default provider: a
nullable defaultProvider string seeded from
ExtensionConfiguration['nr_llm']['defaultProvider'] and mutable at
runtime through set / get
(both on the public Llm). When a generic
chat / complete / stream call pinned no
provider, get fell back to that string.
This is a remnant of the original provider-centric design that predates
the database-backed three-tier model (ADR-013: Three-level configuration architecture (Provider-Model-Configuration),
ADR-001: Provider Abstraction Layer). Since ADR-021: Provider Fallback Chain / ADR-026: Provider Middleware Pipeline, the generic
entry points resolve the active default tx_nrllm_configuration
record first (isActive = 1 AND isDefault = 1, via
Llm); the
ExtensionConfiguration fallback was only ever reached when no such
record existed.
In practice the fallback was inert: the defaultProvider key was
never exposed in ext_conf_template.txt, so it was always null in
production unless an integrator set it by hand in additional.php. It
was also misleading — together with the orphaned plugin.tx_nrllm
TypoScript (removed in #255, answering
discussion #254) it
suggested a second, config-driven way to choose a provider that no code
path honoured as the source of truth.
Decision
Remove the default-provider concept from Llm
entirely. The database is the single source of truth for provider
selection.
- Drop the state and its seed. The
defaultProviderproperty and theExtensionConfiguration['nr_llm']['defaultProvider']read inloadare removed. The rest of the extension configuration (provider-specific settings consumed byConfiguration () register) is unaffected.Provider () - Remove the public accessors.
setandDefault Provider () getare removed fromDefault Provider () Llmand its implementation. This is a breaking change to the public service contract.Service Manager Interface - `getProvider(null)` throws. With no fallback,
getrequires an explicit identifier; called withProvider () nullit throwsProvider(codeException 4867297358) with guidance to configure a default Configuration in the backend module. The signature keeps the nullable parameter for callers that pass a possibly-null pinned provider.
Consequences
- ● One way to choose a provider: pin it per call (the
provideroption onChat/Options Embedding) or let the generic path resolve the active default Configuration. No silent, inert third path.Options - ● The
Llmshrinks by two methods that no production code consumed.Service Manager Interface - ◐ Breaking: integrators that called
set/Default Provider () get, or relied on theDefault Provider () defaultProviderextension-config key, must instead create an active+default Configuration record or pin the provider per call. No production deployment used the key (it was never exposed inext_conf_template.txt), so real-world impact is expected to be nil. - ● No production behaviour change in practice: the generic entry points already resolved the database default first, and the fallback was never populated in production.
- ◐ Supersedes the provider-default resolution steps of ADR-007: Multi-Provider Strategy ("Default provider from configuration" / "First configured provider by priority"): provider selection is now per-call or via the active default Configuration only, with no extension-config or priority fallback.