Migrations and Enrichment

Migration walkthrough

The migration example registers v1 → v2 and renames old_endpoint on the unresolved AST. Then enrichment adds a default and docs:

# Before (v1)
section service
    # Operator choice
    old_endpoint https://private.example.test
    extension retain
end

# After explicit migration and enrichment (v2)
section service
    # Operator choice
    extension retain
    ## Current endpoint documentation.
    endpoint https://private.example.test
    retries 3
end

Each real document also carries its root config_version. Register one step per consecutive version with Migrations.Register(from, func(*Document) error) and call Apply(doc, target). Each successful step commits its cloned document and version; a failed step leaves that step’s input untouched. Earlier successful steps remain committed. Wrap the whole operation in your own document clone if you require all-or-nothing across several steps. Migrations never need resolution; application migration functions must not perform source I/O. Enrichment does not guess renames or removals, and neither operation silently writes a file.

Defaults, examples, comments, and evolution

For example, a credential field can have no Default but have an Example from_file(from_env(CREDENTIAL_FILE)). Seed() leaves the field absent; Sample() emits an inactive ## credential from_file(...) illustration. Enrich() does not activate that example. Conversely, Default: Literal{"3"} for retries inserts an active value when missing. Explicit values always win over a changed schema default. Managed documentation is associated with fields and section blocks; user comments never become schema property merely because their prose resembles documentation.

Schema declares Version and ordered Sections. SectionDefinition gives Name, GoName/GoType, Documentation, Fields, Repeated and ExampleNames. Field carries Key, GoName/GoType, Default, Examples, Documentation, Required, Sensitive, InputOnly, RuntimeOnly, Deprecated, Policy and legacy Environment fallback metadata. Deprecated suppresses new sample/enrichment entries; InputOnly additionally blocks normal editing/runtime targets. Required checks missing declarations, not arbitrary application-specific value validation. Sensitive is inspection/error policy, not encryption at rest. Applications must validate their domain constraints after binding.