84 lines
4.1 KiB
Markdown
84 lines
4.1 KiB
Markdown
|
|
# ADR 0008: Synchronous, Complete-on-Return Configuration Loading
|
||
|
|
|
||
|
|
## Status
|
||
|
|
|
||
|
|
Proposed draft for review. The
|
||
|
|
[configuration contract](../config.md#completion-and-resource-lifetime) describes
|
||
|
|
the implemented loading lifecycle. The
|
||
|
|
[source-backed underlays roadmap](../roadmap/sources-and-layering.md) owns its
|
||
|
|
application to the planned source and resource-context APIs.
|
||
|
|
|
||
|
|
## Date
|
||
|
|
|
||
|
|
2026-09-29
|
||
|
|
|
||
|
|
## Context
|
||
|
|
|
||
|
|
Applications need a clear point at which configuration is ready for use.
|
||
|
|
Completing configuration processing and inspection metadata together gives
|
||
|
|
applications a coherent result whose values and origins agree. A bounded loading
|
||
|
|
lifecycle also makes resource ownership and startup failures straightforward to
|
||
|
|
reason about.
|
||
|
|
|
||
|
|
ConfigKit's [architecture goals](../policy/architecture.md#success-criteria)
|
||
|
|
emphasize complete configuration, inspectable provenance, predictable behavior,
|
||
|
|
and minimal consumer bookkeeping. Applications own their execution lifecycle and
|
||
|
|
the timing of configuration acquisition.
|
||
|
|
|
||
|
|
## Decision
|
||
|
|
|
||
|
|
Make loading a synchronous, complete-on-return operation. Within each load,
|
||
|
|
ConfigKit completes input assembly, defaulting, typed decoding, configured
|
||
|
|
application resolution, secret lookup, validation, and snapshotting before
|
||
|
|
returning the final configuration and metadata. Reported failures return
|
||
|
|
diagnostics and a nil result.
|
||
|
|
|
||
|
|
Release all library-owned loading handles before returning on success or failure.
|
||
|
|
The resulting configuration and metadata are independently usable, caller-owned
|
||
|
|
data with a retained inspection snapshot. Caller-supplied readers and filesystems
|
||
|
|
remain under caller ownership and lifetime control.
|
||
|
|
|
||
|
|
After the call completes, ConfigKit remains inactive until explicitly invoked
|
||
|
|
again. Applications normally load once at or near startup and may initiate
|
||
|
|
additional loads when needed. Each load follows the same lifecycle and source
|
||
|
|
reuse contracts. Inspection, rendering, and separately requested operations run
|
||
|
|
in response to explicit application calls.
|
||
|
|
|
||
|
|
For the planned resource-context capability, retain source context as passive
|
||
|
|
information or a borrowed caller-supplied filesystem. Subsequent resource access
|
||
|
|
acquires its own handles with explicit ownership. This preserves a clear boundary
|
||
|
|
between configuration completion and application resource use.
|
||
|
|
|
||
|
|
These choices give consumers one completion boundary for configuration and
|
||
|
|
provenance, predictable resource lifetimes, and control over when ConfigKit runs.
|
||
|
|
Application callbacks remain responsible for their own effects and resources.
|
||
|
|
|
||
|
|
## Alternatives considered
|
||
|
|
|
||
|
|
- **Background watching or refresh.** Can automate responses to source changes,
|
||
|
|
but adds scheduling, shutdown, publication, and resource-lifetime concerns to
|
||
|
|
the library. Explicit calls keep those responsibilities with the application.
|
||
|
|
- **Lazy completion after return.** Can defer work until particular values are
|
||
|
|
used, but moves configuration failures into application execution and makes
|
||
|
|
the readiness of values and metadata harder to establish.
|
||
|
|
- **Transactional atomic loading.** Could imply simultaneous observation of all
|
||
|
|
external inputs and rollback of callback effects. Filesystems, environment
|
||
|
|
variables, and application callbacks do not share a transaction mechanism.
|
||
|
|
Synchronous completion provides the required usable-result boundary without
|
||
|
|
promising those external guarantees.
|
||
|
|
- **Retain loading handles in results.** Can preserve open filesystem access,
|
||
|
|
but gives configuration results an ongoing resource lifecycle and cleanup
|
||
|
|
obligation. Passive source context supports later explicit resource access
|
||
|
|
while keeping loading resources scoped to the load call.
|
||
|
|
|
||
|
|
## Consequences
|
||
|
|
|
||
|
|
Applications can treat successful return as the point at which the final
|
||
|
|
configuration and its metadata are ready for use. Startup loading remains simple,
|
||
|
|
and additional loads have an explicit application-owned trigger.
|
||
|
|
|
||
|
|
Configuration inspection operates on retained data. Resource access observes the
|
||
|
|
backing resource when explicitly requested and has its own failure and ownership
|
||
|
|
boundary. Implementations of new source kinds and layering features preserve the
|
||
|
|
same completion boundary, including cleanup on reported load failures.
|