143 lines
7.8 KiB
Markdown
143 lines
7.8 KiB
Markdown
# Architecture Policy
|
|
|
|
**Base Policy Version:** 1.0
|
|
|
|
**Last Updated:** 2026-09-06
|
|
|
|
## Purpose and applicability
|
|
|
|
ConfigKit is an opinionated Go library for consistent YAML configuration loading
|
|
and resolution across consuming applications. This policy governs contributions.
|
|
The [component overview](../internal/overview.md) owns implementation inventory, the
|
|
[configuration contract](../config.md) owns implemented behavior, and the
|
|
[deferred scope](../roadmap/deferred.md) preserves deferred scope.
|
|
|
|
## Success criteria
|
|
|
|
1. **Reduce application infrastructure:** Can applications delete substantial
|
|
configuration infrastructure while retaining clear ownership of their domain
|
|
rules?
|
|
2. **Unify configuration conventions:** Do consumers adopt one consistent
|
|
configuration model, with only the flexibility needed to express genuine
|
|
application requirements?
|
|
|
|
Both criteria must hold. ConfigKit should not preserve divergent consumer
|
|
conventions merely for compatibility, nor impose restrictions that prevent useful
|
|
domain information from being expressed. Prefer a canonical representation using
|
|
existing primitives before adding another mechanism. Extend the model when a
|
|
concrete requirement cannot be accommodated cleanly, not simply because a
|
|
consumer already implements a different convention.
|
|
|
|
Use both criteria to evaluate public API changes and consumer adoption. Shared
|
|
loading, presence tracking, source attribution, and diagnostic plumbing should
|
|
move out of applications; application types, defaults, normalization, and semantic
|
|
validation should remain recognizable application code. Replacing that plumbing
|
|
with equally repetitive callback bookkeeping does not meet the first criterion.
|
|
Offering alternate parsing, precedence, or composition conventions through escape
|
|
hatches does not meet the second.
|
|
|
|
Consumer migrations are expected and may intentionally change configuration
|
|
syntax. Existing consumer code supplies implementation foundations and evidence
|
|
of needs; it does not define ConfigKit's compatibility obligations. Once ConfigKit
|
|
publishes its own contracts, changes to those contracts remain governed by the
|
|
[release policy](release.md).
|
|
|
|
Require representative simple and complex consumer examples to substantiate API
|
|
designs. Proposed extensions must identify the domain requirement, explain why
|
|
existing primitives cannot accommodate it cleanly, and show how the extension
|
|
preserves a coherent model. Application-specific interpretation and validation
|
|
remain appropriate. Reuse Narratio's applicable infrastructure under these
|
|
boundaries, and keep simple consumers independent of optional composition
|
|
features. The [consumer adoption guide](../consumers/README.md) demonstrates the
|
|
implemented surface against representative simple and complex shapes.
|
|
|
|
## Responsibility boundaries
|
|
|
|
ConfigKit owns configuration input processing and the coordination of decoding,
|
|
resolution, validation, and inspection. Applications own their configuration
|
|
types, field meanings, defaults, normalization, semantic validation, and schema
|
|
version policy. Applications also own main-file search conventions, CLI wiring,
|
|
remote acquisition, runtime initialization, and resource checks.
|
|
|
|
Library code must not depend on consuming applications or initialize their
|
|
runtime resources. It must not perform implicit network access, discover
|
|
application-specific paths, or change process-global state during ordinary `Load`.
|
|
The explicit secrets-directory bootstrap is a narrow, opt-in exception: applications
|
|
invoke it during startup, and it reports writes, skips and partial failures. It
|
|
must never run implicitly as part of configuration loading.
|
|
Remote data can enter through application-supplied input without introducing a
|
|
network provider into the library.
|
|
|
|
## Public API and dependency direction
|
|
|
|
Keep one small, coherent public surface for the supported lifecycle. Simple
|
|
single-document consumers must not need import, profile, or provider machinery.
|
|
Do not expose parser-specific nodes, errors, or extension hooks through the
|
|
public API. Parser integration belongs behind a private boundary, as recorded
|
|
in [ADR 0002](../adr/0002-own-yaml-semantics.md).
|
|
|
|
Separate input access, document processing, composition, decoding, metadata, and
|
|
rendering responsibilities without prescribing an interface or package for each.
|
|
Dependencies must preserve those boundaries; package splits and abstractions
|
|
must earn their complexity. Do not impose a full application or hexagonal
|
|
framework on this library.
|
|
|
|
## Configuration integrity
|
|
|
|
Composition and intentional overlay are distinct operations. Composition must
|
|
not silently become last-wins override through file ordering. The decision and
|
|
alternatives are recorded in [ADR 0001](../adr/0001-separate-composition-and-overlay.md).
|
|
|
|
ConfigKit must define supported YAML semantics explicitly rather than inherit
|
|
parser defaults. Processing order and diagnostics must be deterministic for the
|
|
same inputs and options. Invalid input must not produce a successful usable
|
|
configuration. Do not run application hooks on invalid typed configuration.
|
|
|
|
User-controlled precedence is application defaults, composed base, selected
|
|
profile, then explicitly supplied CLI overrides. Applications own flag parsing;
|
|
ConfigKit owns overlay semantics and provenance. Domain resolution follows these
|
|
inputs and must remain recorded, not become a hidden override channel.
|
|
|
|
Preserve node-based composition until the effective input is ready for typed
|
|
decoding. Preserve presence and source information through processing. Ordinary Go zero
|
|
values must not be used to infer whether input was absent. Final configuration,
|
|
metadata, and effective inspection must agree, including application resolution
|
|
changes; see [ADR 0003](../adr/0003-preserve-presence-and-resolution-history.md).
|
|
Safe historical values and an explanation renderer are part of the implemented contract,
|
|
including superseded/deleted paths and effective source attribution. Inspection
|
|
must agree with the final typed snapshot and apply historical sensitivity rules.
|
|
See [ADR 0005](../adr/0005-explicit-overrides-and-safe-explanation.md).
|
|
Detailed syntax and operation tables belong to the
|
|
[current configuration contract](../config.md).
|
|
|
|
## Ownership and confidentiality
|
|
|
|
Returned configuration and metadata must not share mutable state across loads.
|
|
ConfigKit must not mutate a result after returning it. Ordinary exported Go
|
|
values are not language-enforced immutable objects; document caller ownership
|
|
and the lifetime of captured metadata without promising otherwise.
|
|
|
|
Secret values enter configuration through typed environment-name references;
|
|
literal credentials are not a supported configuration convention. Only an explicit
|
|
accessor exposes a resolved credential to application code. Credential bytes must
|
|
never enter composition trees, history, or inspection. General environment-variable
|
|
configuration overlays are an explicit non-goal. Bootstrap must preserve already
|
|
set variables, including empty ones, and report blocked files without contents.
|
|
See [ADR 0004](../adr/0004-secret-references-and-explicit-bootstrap.md).
|
|
|
|
Secrets must be considered throughout error handling and inspection. Library
|
|
renderers must apply secret classification, and parser errors must not be
|
|
forwarded blindly when they can include raw input. Do not log configuration
|
|
implicitly. Applications remain responsible for classifying their secrets and
|
|
for safe messages supplied by their hooks.
|
|
|
|
## Scope boundaries
|
|
|
|
Do not introduce automatic directory discovery, network providers, arbitrary
|
|
merge strategies, additional configuration languages, or application runtime
|
|
management without concrete consumer evidence and an explicit design decision.
|
|
The [deferred scope](../roadmap/deferred.md#explicit-non-goals-and-deferred-scope)
|
|
owns the deferred-feature inventory. Significant boundary
|
|
changes require an ADR and corresponding policy/contract updates; implementation
|
|
convenience alone is not a reason to broaden the public API.
|