Remove completed roadmap documents

This commit is contained in:
2026-11-01 19:05:56 +00:00
parent 6db441893d
commit d211537873
3 changed files with 0 additions and 857 deletions

View File

@@ -1,457 +0,0 @@
# User and Operator Documentation Readability Review
Reviewed revision: `08bb3a20c6a565646d98f68688d268c7bae39573`.
Status: complete. All D01–D18 revisions have been applied and reviewed together
for consistency. The catalog below preserves the proposals that guided the
work; the completion record identifies their implemented locations. The previous
consistency audit remains in Git history; its two findings were corrected in
`94d1e33`.
## Completion record
| Proposal | Implemented result |
| --- | --- |
| D01 | [README](../../README.md) leads with the loading outcome and minimal example, followed by optional tasks and platform/licensing links. |
| D02 | [Consumer guide](../consumers/README.md) starts with task routes, defaults, validation, and inspection; example background and the test inventory follow usage. |
| D03 | [Reference introduction](../config.md) supplies topic routes, YAML illustrations, path definitions, and common-versus-detailed subheadings. |
| D04 | [Sources](../config.md#sources), [results](../config.md#results-and-failures), and [resource lifetime](../config.md#completion-and-resource-lifetime) explain copying, reuse, saved inspection, and caller-owned resources. |
| D05 | [Priority](../config.md#priority-and-processing-order), [strict combination](../config.md#combining-mappings), and [defaults](../config.md#defaults-and-typed-decoding) have visible examples and retain collection exceptions. |
| D06 | [Discovery](../config.md#configuration-discovery) shows the four attempted paths and distinguishes optional absence, required absence, and selected-file failure. |
| D07 | [Imports](../config.md#explicit-imports) introduce the three selectors, option applicability, requiredness, ordering, and earlier syntax separately. |
| D08 | [Placement](../config.md#input-destinations) illustrates files and assembled YAML; [contexts](../config.md#source-resource-contexts) explain later resource access and ownership. |
| D09 | [Identified lists](../config.md#identified-lists-a-worked-example) show replace, append, and whole-record upsert before registration and policy-lifetime details. |
| D10 | [Inheritance](../config.md#sibling-inheritance) starts with parent/child settings, then cancellation and identified records before exact scheduling rules. |
| D11 | [Versions](../config.md#application-schema-versions) introduce application acceptance, a mode table, mounted headers, and the limits of observed evidence. |
| D12 | [Callbacks](../config.md#recorded-application-resolution) have task and helper tables, a derived-default example, and entry-state/lifetime guidance. |
| D13 | [Secrets](../config.md#typed-secret-references) separate lookup, hiding, and bootstrap; [bootstrap](../config.md#explicit-secrets-directory-bootstrap) explains empty existing variables and partial reports. |
| D14 | [Inspection](../config.md#layered-metadata) starts with reader needs and a default/main/overlay example; [diffs](../config.md#effective-configuration-diffs) explain snapshot flags and hidden changes. |
| D15 | [YAML](../config.md#yaml-documents), [defaults](../config.md#defaults-and-typed-decoding), [projection](../config.md#typed-projection-and-ownership), and [failures](../config.md#safe-failures) have practical examples; descriptor caching moved to the [internal overview](../internal/overview.md). |
| D16 | [Package documentation](../../doc.go) and the targeted public declarations explain purpose, paths, returned copies, and saved state while retaining precise contracts. |
| D17 | [Migration guidance](../consumers/README.md#intentional-migration-changes) leads with numbered consumer actions and explains package type identity alongside the retained old/new table. |
| D18 | [Release procedure](../release.md) defines operational terms and explains Go selection, publication statuses, and tag-object recovery without changing command blocks or gates. |
## Audience and Scope
ConfigKit is a library. Developers integrating its public API are its users;
they need different documentation from contributors maintaining the engine.
Configuration authors may know YAML without knowing Go reflection or graph
algorithms. Release maintainers are the audience for its operational runbook.
ConfigKit has no standalone application CLI or application deployment procedure
to explain.
| Material | Primary readers | Treatment in this review |
| --- | --- | --- |
| [Root README](../../README.md) | People evaluating or starting with ConfigKit | Explain outcomes and direct readers to a useful next page. |
| [Consumer guide](../consumers/README.md) | Application developers adopting or upgrading ConfigKit | Explain tasks and examples before advanced terminology. |
| [Configuration reference](../config.md) | Configuration authors and API users checking exact rules | Add context while keeping precise contracts available. |
| [Package documentation](../../doc.go) and public declaration comments | Users browsing the Go API | Explain practical effects alongside symbol names and conditions. |
| [Release procedure](../release.md) | Maintainers publishing or recovering a release | Clarify operational language while preserving the workflow. |
| [Release history](../releases) | Users considering an upgrade | Preserve historical records. Future notes can lead with user impact and required action. |
| [Attribution](../oss/attribution.md), `COPYRIGHT`, and license texts | Users checking rights and notices | Preserve formal notices and license language; no rewrite proposed. |
| Development guide, internal docs, ADRs, policies, and roadmaps | Repository contributors and decision reviewers | Outside the main rewrite scope; retain links for implementation and rationale. |
The adopted policies should not acquire local wording changes solely for this
exercise. Accepted ADR decisions and historical release records retain their
established treatment under the [documentation policy](../policy/documentation.md).
## Editorial Direction
Introduce each topic through the reader's task or the observable result.
Explain unfamiliar terms where they become useful. More words are appropriate
when they supply the background needed to understand a rule.
Follow introductory explanations with precise reference material. Retain names
readers will encounter in Go and YAML, and explain them rather than inventing
new API terminology. Use small illustrations beside the explanation and link
to maintained files for complete runnable examples. Initially, improve the
existing pages rather than introducing a new documentation tree.
These are contextual explanations, not global replacement instructions:
| Existing term | Useful explanation on first use |
| --- | --- |
| Mapping / sequence / scalar | A YAML group of named values / a list / a single value such as a string or number. |
| Precedence | Which input takes priority when different layers supply a setting. |
| Provenance / origin | Where a value came from, including application processing that changed it. |
| Explicit presence | Whether input supplied a setting, even when its value is `false`, `0`, empty, or null. |
| Detached record | A returned copy whose mutation cannot change ConfigKit's stored record. Explain borrowed filesystem ownership separately. |
| Frozen snapshot | The saved configuration state that inspection continues to describe after loading. |
| Source-local coordinates | Paths within one input document, before its destination is added. |
| Canonical projection | A consistent representation of typed values used for comparison or inspection; introduce its relevant effect before the internal term. |
| Dependency-ready order | Process a contribution after its dependencies are ready, using the documented tie-break rule when several are ready. |
## Catalog of Proposed Revisions
The identifiers below name proposals, not implementation stages. High priority
means a proposal helps readers understand a common or foundational task. Medium
priority addresses a specialized task or reference detail.
### D01 — Introduce ConfigKit through its useful outcomes
**Target:** [README introduction](../../README.md). **Priority:** High.
The feature inventory precedes the minimal example and introduces "snapshotted
mappings," "detached metadata," "audited defaulting," and "source/derivation
history" in quick succession.
Lead with what the application receives and what its author supplies. Suggested
direction: "ConfigKit loads YAML into your application's Go configuration type,
combines the inputs you choose, and lets you inspect where the final values came
from." Bring the existing minimal example forward. Follow it with short
capability summaries and links, introducing optional features when readers
select them. Keep platform and licensing navigation easy to find. Detailed
scheduling and ADR links can follow the consumer-oriented navigation.
### D02 — Make the consumer guide a route through common tasks
**Target:** [Consumer introduction and entry-point selection](../consumers/README.md#choosing-a-loading-entry-point),
the example-shape table, and Happy path. **Priority:** High.
The guide begins with a long responsibility inventory and examples named after
other applications. Its happy-path snippet immediately presents imports,
overlays, overrides, and a predeclared rules value.
Offer a short task index: load one file, supply defaults and validation, add
bundled lower-priority settings, select an overlay, and inspect a result. Point
the simplest case to the README example, then introduce additional options as
needed. Describe examples by their demonstrated task before their original
application names. Move extraction background and test-owner inventories below
usage guidance. Preserve links to maintained examples.
### D03 — Give the reference useful starting points
**Target:** [Configuration reference introduction](../config.md). **Priority:** High.
The opening says the document "owns" contracts and describes private parser
boundaries. The page mixes basic input selection with advanced lifecycle and
inspection details across a long reference.
Introduce it as the reference for accepted YAML, input combination, and loading
behavior. Add a compact topic index with routes for configuration authors and
Go API users. Introduce mappings, lists, layers, and configuration paths with
small illustrations. Separate common behavior, advanced interactions, and limits
through subheadings within the existing document. Keep detailed rules available
after their introductions; a separate general-purpose glossary is unnecessary
initially.
### D04 — Explain source selection and ownership in practical terms
**Target:** [Sources](../config.md#sources),
[single-source loading](../config.md#single-source-loading), and
[resource lifetime](../config.md#completion-and-resource-lifetime).
**Priority:** High.
"Opaque source," "consumption," "claimed once," "defensive source list," and
"publication copy" put implementation vocabulary ahead of caller actions.
Introduce sources as inputs passed to `Load`. Explain which are copied
immediately, which are read again on each load, and why a `Reader` source is
single-use. Keep the constructor table and explain who closes each resource.
Introduce the result before explaining copying mechanics. Suggested wording:
"You can change `Result.Config` after loading. Inspection methods continue to
describe the configuration as it was when the load finished." Preserve the
separate rule that borrowed filesystems remain under caller control and later
resource reads observe those filesystems.
### D05 — Teach combination rules with visible input and output
**Target:** [README philosophy](../../README.md#design-philosophy),
[layered loading](../config.md#layered-loading),
[strict composition](../config.md#strict-document-composition), and
[defaults](../config.md#defaults-and-typed-decoding). **Priority:** High.
Readers encounter "tier," "strict peers," "recursive precedence," and "typed
baseline" before seeing a combined configuration. Priority order and processing
order are also easy to confuse.
Use a small mapping example to show independent same-tier contributions and an
intentional higher-layer change. Explain same-tier conflicts. Show a priority
diagram separately from the processing timeline, explaining why defaults have
low priority while being applied during decoding. Keep the README summary brief
and link to full reference rules. Add a defaults example distinguishing omission,
explicit false/zero, an empty list, and null where the Go field permits it.
Keep collection exceptions visible; avoid a blanket "last file wins" explanation.
### D06 — Describe discovery as an ordered search
**Target:** [Configuration discovery](../config.md#configuration-discovery) and
[consumer discovery guidance](../consumers/README.md#explicit-main-file-discovery).
**Priority:** High.
"Directory-first Cartesian product," "ordered concatenation," and "optional
exhaustion" require translation into actual attempted filenames.
Show two directories and two filenames as an ordered list of candidates.
Explain that ConfigKit finishes the filenames for one directory before moving
to the next. Explain no-match behavior, required searches, and selected-file
failure. Keep the terminal selected-file error rule prominent so readers
understand why a bad selected file does not cause another search. Follow with
the existing preset table and specialized filesystem-context rules.
### D07 — Introduce imports through the three selection tasks
**Target:** [Explicit imports](../config.md#explicit-imports) and
[import defaults guidance](../consumers/README.md#import-defaults-and-selection-inspection).
**Priority:** High.
The opening combines enablement, structural controls, selector shapes,
requiredness, destinations, removed syntax, and diagnostic codes. Later passages
refer to "namespace-path lexical order" and "scoped assembly order."
Start with including a named file, searching a directory, and matching a path
pattern. Use small YAML illustrations and link to complete examples. Explain
shared options in a selector-applicability table. Separate optional missing
inputs from unreadable or invalid inputs. Explain that required path lists check
each named target, while required directory/glob searches need a selected file;
retain the empty `path: []` case. Explain observed ordering with a short dependency
example before its exact reference rules. Move legacy migration notes below the
first explanation of current syntax.
### D08 — Separate configuration placement from filesystem paths
**Target:** [Input destinations](../config.md#input-destinations),
[resource contexts](../config.md#source-resource-contexts), and
[mounted collection guidance](../consumers/README.md#input-destinations-and-mounted-collections).
**Priority:** High.
"Effective destination," "projected through that item," "nearest resolved
enclosing collection container," and "passive resource context" are difficult
without a picture of the configuration and the files on disk.
Show a tiny file tree beside a resulting YAML shape. Explain that a destination
chooses where settings appear, while an import filename resolves from its
declaring file. Walk through opening one resource: follow its value's source ID
to `SourceContext`, join `BaseDir`, and close the file the application opens.
Introduce fallback destination evidence after exact placement. Preserve
composite-origin ambiguity, caller-owned resource lifetimes, and the distinction
between saved configuration and later resource I/O.
### D09 — Explain collection identity and operations before policy lifetime
**Target:** [Collection rules](../config.md#strict-document-composition) and
[identified sequence guidance](../consumers/README.md#identified-prompt-sequences).
**Priority:** High.
Selectors, normalized field sets, type-tagged tuples, registrations, and retained
policy appear before the operation table. Readers who want to combine a list of
named records need substantial background first.
Start with a record list and an `id` field. Show before/after results for replace,
append, and upsert, including an upsert whose omitted lower fields disappear
during source assembly. Explain duplicate rejection within a strict tier. Next
introduce YAML declarations and Go registrations, including their different
final-validation guarantees. Label compound identity, exact numeric equality,
wildcard selectors, pending declarations, and record-owned policy as advanced
reference material. Preserve the existing operation and presence tables.
### D10 — Introduce inheritance with a parent and child
**Target:** [Sibling inheritance](../config.md#sibling-inheritance) and
[consumer inheritance guidance](../consumers/README.md#named-sibling-inheritance).
**Priority:** Medium.
The opening quickly moves from named siblings to identified records, root
restrictions, cancellation, and dependency scheduling.
Begin with a small `base`/`custom` mapping example and show the resulting child.
Explain "sibling" as another entry in the same enclosing mapping. Explain that
inheritance uses the settings remaining after source combination. Add
cancellation and identified-record examples next, followed by exact ordering.
Retain destination-local nested resolution, identity-field ownership,
cycle/missing-parent errors, and ordinary validation of parent records.
### D11 — Explain version checking as application-defined acceptance
**Target:** [Application versions](../config.md#application-schema-versions),
[shared checks](../config.md#shared-source-version-checks), and
[consumer version guidance](../consumers/README.md#shared-source-version-checks).
**Priority:** Medium.
"Accepted non-main declarations are consumed from their owned payload" and
"destination-prefixed application path" combine several concepts in one sentence.
Explain first that the application chooses the version field and supported
identifiers. Add a behavior table for the three modes, distinguishing missing
main headers, missing other headers, explicit null, and `NoSource`. Use a mounted
document example to separate checking a header inside a file from protecting its
assembled path. Explain that accepted non-main headers are removed before
combination. Preserve the distinctions between observing a declaration, running
a checker, and acceptance, including disclosure limits on `VersionEvidence`.
### D12 — Explain callbacks through the application's work
**Target:** [Recorded resolution](../config.md#recorded-application-resolution),
[semantic validation](../config.md#semantic-validation), and consumer task guidance.
**Priority:** High.
"Audited net resolution operations," "helper-assigned values," "covering record,"
and "post-decode entry state" obscure when to use each callback.
Introduce fixed defaults, deriving or normalizing values in `Resolve`, and
checking rules in `Validate` as separate tasks. Compare `Default`, `Normalize`,
and the two `Record*` methods, identifying which assign values. Explain that
`EntryInfo` describes callback-entry state even after the resolver changes
values. Use a small derived-value example to explain recording and dependencies.
State callback lifetime and read-only validation rules directly. Retain panic,
error-reporting, and helper-writeback behavior in the detailed reference.
### D13 — Separate secret references, hiding output, and file bootstrap
**Target:** [Typed references](../config.md#typed-secret-references),
[classification/rendering](../config.md#secret-classification-and-effective-rendering),
and [file bootstrap](../config.md#explicit-secrets-directory-bootstrap).
**Priority:** High.
"Credential-bearing fields," "sensitivity closure," "preflight/apply," and
"existing empty winner" demand familiarity with several different mechanisms.
Explain the YAML environment-variable name, the credential read during loading,
and the separate choice to hide a configuration field in inspection. Make clear
that reference names are visible unless separately classified. Explain the
optional helper as reading files into environment variables before a later load,
with a filename/name/value illustration using dummy data. Explain
`skipped_existing` with the already-set-but-empty case, then show how to read a
partial report. Preserve partial writes, lack of rollback, lookup timing,
application-owned safe messages, and visibility limits. Keep exact byte/name
limits in their reference paragraphs or tables.
### D14 — Explain inspection through the information readers need
**Target:** [Metadata](../config.md#layered-metadata),
[explanations](../config.md#historical-value-explanation),
[diffs](../config.md#effective-configuration-diffs), and their consumer examples.
**Priority:** High.
"Canonical typed projection," "decoding reconciliation," and "cross-protected
context" are demanding introductions to inspecting a setting.
Organize the introduction around the final value, its source, its earlier
definitions, and changes between two loads. Walk through a setting with a
default, supplied value, and later override. Distinguish metadata history from
value explanations. Explain `Present`, `Redacted`, and `HiddenChanged` with a
small table and hidden-change example. Keep source-versus-typed representation
details, atomic list comparisons, combined sensitivity, and unchanged-reference
credential rotation. Clarify which outputs contain values and which contain
attribution only.
### D15 — Lead YAML and Go type rules with authoring examples
**Target:** [YAML documents](../config.md#yaml-documents),
[scalars](../config.md#scalars), [schema binding](../config.md#application-schema-binding),
[decoding](../config.md#defaults-and-typed-decoding),
[projection/ownership](../config.md#typed-projection-and-ownership), and
[safe failures](../config.md#safe-failures). **Priority:** Medium.
"Private reflection descriptor graph," "paired text scalars," and "recursive
acyclic objects" precede common authoring needs. Safe failures explains
classifications before showing how to use a report.
Start with a YAML/Go field pairing and everyday examples: quote `yes` to use it
as text, write durations as strings, and use supported lowercase booleans.
Retain the scalar/defaults tables. Explain nil versus empty containers, ignored
fields, and `omitempty` through visible results. Put codec method sets and
recursive-type rules in advanced reference material. Explain diagnostic code,
configuration path, and source location with a small safe report and a link to
maintained error handling. Retain exact limits and error behavior. Move purely
internal caching or tree-storage explanations to existing internal docs where
useful, preserving all observable ownership guarantees.
### D16 — Make Go API comments understandable on their own
**Target:** [doc.go](../../doc.go), public declarations in
[lifecycle.go](../../lifecycle.go), [path.go](../../path.go),
[records.go](../../records.go), [inspection.go](../../inspection.go), and
[diff.go](../../diff.go). **Priority:** Medium.
The package comment is chiefly a feature inventory. `Resolution` introduces
"entry-state input provenance"; `Difference` introduces a "canonical changed
region"; several result comments rely on "detached" without explaining its effect.
Give major types an action-oriented first sentence followed by their precise
contracts. Illustrate configuration paths with a key/index example, and explain
returned-copy and saved-state behavior where relevant. Keep symbol-specific
errors, nil/zero behavior, ownership, and lifetime rules beside declarations.
Link to shared YAML semantics and maintained examples rather than repeating the
full configuration reference. Preserve public names and Go doc conventions.
### D17 — Turn migration prose into recognizable consumer actions
**Target:** [Migration changes](../consumers/README.md#intentional-migration-changes),
[module-path migration](../consumers/README.md#vanity-module-path-migration), and
[API cleanup](../consumers/README.md#pre-v1-public-api-cleanup).
**Priority:** Medium.
The old/new symbol table is useful, but "serialized diagnostic/provenance
expectations" and "migration evidence" assume repository history and advanced
Go package knowledge.
Lead with actions: update requirements and imports together, replace listed old
symbols, and review any stored or compared layer/code strings. Explain distinct
Go type identity through another dependency passing ConfigKit values to the
application. Retain the old/new table, historical-tag limitations, and the
difference between API and YAML changes. Keep downstream migration-status caveats
in a short background note. Do not choose a release version or claim that another
application has migrated.
### D18 — Make the release runbook easier to follow and recover from
**Target:** [Release procedure](../release.md), especially Go selection,
publication status, and recovery. **Priority:** Medium.
"Module-selected native executable," "consumer minimum," "bounded authoritative
reconciliation," and "peeled commit" require substantial release-tool knowledge.
Explain a candidate as the committed revision intended for release, the consumer
minimum as the oldest supported Go version, and the selected tool as the
ReleaseKit version recorded in `go.mod`. Use the existing Go patch example to
distinguish validation toolchain from consumer minimum. Keep command blocks
intact unless a separately verified wording change needs an accompanying
adjustment. Put exit statuses and next actions in a compact table. Explain why
the tag-object ID matters before asking the operator to compare it. Keep
recovery's exact URL, candidate, and tag identity conditions together.
Preserve pushing the candidate before publishing the tag, publication
authorization, immutable published tags, a single publication command,
and optional consumer verification. Keep CI waiting and macOS validation outside
the release gates. Plain language must not turn uncertain publication into
permission to retry, delete a published tag, or declare success.
## Priorities and Review Boundaries
The highest-impact starting points are the README and consumer entry routes
(D01–D03), combination/presence explanations (D05), and secret/inspection guidance
(D13–D14). The other proposals develop a selected task or reference topic. These
priorities are editorial recommendations, not additional release gates.
These revisions preserve existing contracts, diagnostic identifiers,
defaults, limits, security boundaries, and exceptions. Keep precise material
available after its plain-language introduction. A simpler explanation must not
imply universal last-value replacement, universal null support, transactional
loading, refreshed inspection after caller mutation, or stronger filesystem
isolation.
Implementation changes consumer-facing prose and Go declaration comments, with
the relocated descriptor-caching explanation in the existing internal overview.
Policies, accepted ADRs, release history, license notices, dependencies, and
production behavior remain unchanged. Validation includes exercising the revised
illustrations against the library, checking local links and Markdown tables,
comparing Go tokens to confirm comment-only edits, and verifying that release
command blocks remain identical to the implementation baseline `e74c26a`.
Completed validation with Go 1.26.10 and dependency downloads disabled:
- `./scripts/check.sh` passed formatting, whitespace, all tests (including local
links and executable examples), vet, and build.
- Temporary programs outside the repository exercised the revised README,
callbacks, YAML, discovery, imports, collection operations, placement,
inheritance, version modes, inspection, secret bootstrap, defaults, and
projection illustrations against the current library; all passed.
- A Go scanner comparison confirmed identical non-comment tokens in all six
changed Go files. All 12 release command blocks are byte-for-byte unchanged.
- The six affected Markdown pages rendered successfully with the project's
Markdown parser; all 27 tables have consistent column counts. Existing
navigation anchors remain available.
The final consistency pass checked terminology, worked results, public comments,
cross-page links, documentation ownership, and the preserved release workflow.

View File

@@ -1,132 +0,0 @@
# Behavioral Equivalence and Shared Abstraction Audit
Reviewed revision: `94d1e333d422d742eb59726ad90201f4c7db9205`.
This audit examined explicit cross-path comparisons and complementary behavioral
tests, then inspected their production implementations. One focused maintenance
opportunity warrants consideration. It is not a demonstrated correctness defect
or a requirement to refactor before release.
## 1. Share typed-secret slot traversal between resolution and mutation auditing
**Status:** Complete. [secret_walk.go](../../internal/engine/secret_walk.go)
now owns traversal for both operations, with explicit writable and read-only map
handling. Resolution and mutation auditing retain separate leaf operations and
lifecycle passes. The [container regression](../../internal/engine/secret_walk_test.go)
checks resolved state, mutation paths, nil containers, and lookup counts through
both passes without deriving expectations from the walker.
Completion validation: the new container cases passed before and after the
refactor. Focused secret/validation tests, `go test -race ./... -count=1`, and
`./scripts/check.sh` passed.
### Evidence
The tests in [secret_reference_test.go](../../internal/engine/secret_reference_test.go)
establish complementary requirements:
- `TestSecretReferencesResolveTypedShapesOncePerName` (line 31) exercises typed
fields, optional pointers, maps of values and pointers, nil pointers, and
sequences. It verifies resolved credentials are available before validation
and each environment name is looked up once.
- `TestSecretReferenceErrorsAreSafeAndPathSpecific` (line 78) verifies secret
paths, absent/null/invalid references, optional-pointer behavior, and cached
failed lookups.
- `TestValidationCannotReplaceResolvedSecretWithSameName` (line 297) verifies
that validation cannot replace private resolved state while preserving the
projected reference name. It expects `validate.mutation` at the secret's path.
- `TestDynamicValuesDoNotEstablishSecretReferences` (line 415) verifies that
dynamic values do not acquire typed-secret semantics.
`TestSecretBindingsRemainExactAndIndependent` in
[secret_binding_test.go](../../internal/engine/secret_binding_test.go), line 123,
also verifies that the selected exact secret type belongs to the load's schema
binding. The [typed-secret contract](../config.md#typed-secret-references)
establishes both supported typed containers and the private-state validation
audit.
These tests do not compare the two walkers directly, and the private-state
mutation regression exercises a direct field rather than every container shape.
The shared responsibility is identifying schema-bound secret slots at their
semantic paths. Resolution and validation auditing intentionally perform
different operations at those slots.
### Implementation
Both walks are in
[secret_reference.go](../../internal/engine/secret_reference.go):
- `resolveSecretValue` (line 57) descends pointers, physical struct members,
string-keyed maps, slices, and arrays. It resolves names, reports failures,
assigns resolved state, and records reference names.
- `collectChangedSecretStates` (line 139), called by `changedSecretStates`,
independently implements the same container dispatch, nil handling, inline
field path handling, sorted map-key traversal, and sequence-index paths. Its
leaf operation compares private state with the earlier lookup results.
Both already share schema descriptors and `SecretBinding`, but their recursive
navigation remains duplicated. Resolution additionally copies map entries into
writable values and writes them back; auditing reads map entries directly.
[runValidation](../../internal/engine/validation.go) runs the latter after
ordinary projection/mutation checks, so the two traversals occur at different
lifecycle points.
### Opportunity and potential remediation
Consider a small engine-private walker dedicated to schema-bound secret slots.
It could own container navigation and semantic path construction, with separate
leaf operations for resolving a reference and checking its private state. This
would give changes to supported secret-container traversal one owner and reduce
the chance that resolution visits a slot that mutation auditing later misses.
Keep the existing operation-specific entry points, diagnostics, lookup cache,
optional-reference rules, and state comparisons recognizable. Make writable
versus read-only map handling explicit. Keep the two lifecycle passes separate;
sharing traversal does not mean reusing a pre-validation snapshot of slots or
combining resolution and validation into one pass.
This belongs within `internal/engine`. It needs no new public API, cross-package
reflection framework, global cache, or generic walker for cloning and projection.
### Tradeoffs
- A visitor adds indirection. Keep it specific to secrets and small enough that
the container rules and two leaf operations remain easy to read. If doing so
requires a broad configurable traversal framework, retaining the two explicit
walks is preferable.
- Map-entry addressability is an intentional difference. A common walker must
preserve resolution's copy/writeback behavior without making the audit mutate
configuration or perform unnecessary writable copies.
- Auditing must use the original per-load lookup results, without looking up
credentials again or resetting resolved references. Preserve existing nil,
inline-field, path, and exact-type semantics; do not widen dynamic-secret
support or add new rejection rules as part of consolidation.
- Sharing implementation must not make the tests depend on the walker to
discover their expected paths or values. Keep independently authored shape,
mutation, lookup-count, and non-disclosure assertions. The existing tests
establish the motivation, but do not by themselves exhaustively verify a new
shared walker across every supported shape.
## Scope and validation
The review covered source and load-entry equivalence, discovery integration,
strict composition and precedence, collection operations and history replay,
inheritance scheduling/application, schema projection/cloning, semantic paths,
metadata/explanation, secret handling, and the facade/internal boundaries.
The existing architecture already shares substantial implementation logic.
Independent reference scans in tests remain useful oracles; replacing them with
the optimized production helpers would weaken the evidence rather than improve
the architecture. Root-owned facade conversions and parser adaptation also
preserve deliberate boundaries. No additional package extraction is recommended
from this audit, and no new correctness issue was established.
Codebase graph searches, call traces, source inspection, and the existing suite
were used. No standalone duplicate-code analyzer was available on `PATH`.
With Go 1.26.10 and dependency downloads disabled, this passed:
```sh
GOTOOLCHAIN=local GOPROXY=off go test ./... -count=1
```
No production code or tests were changed, and no benchmarks were collected.

View File

@@ -1,268 +0,0 @@
# Vanity Module Path Migration
Status: repository implementation and exact-revision remote consumer verification
complete.
Planning baseline: `21c9bc0ad0315c4ac96268b487a52376558a18d7`.
This roadmap defines the target and work needed to adopt
`go.maximumdirect.net/configkit` before ConfigKit's initial v1.0.0 release.
It is not a staged implementation plan or authorization to push or publish.
The [configuration contract](../config.md), public declaration comments, and
[release policy](../policy/release.md) continue to own behavior outside the
module-identity migration.
## Purpose And Scope
Give ConfigKit a stable, project-owned Go module identifier independent of its
repository host, while retaining its existing package name, public facade,
configuration behavior, and implementation boundaries.
The migration changes the module path and therefore Go package/type identities.
It also brings ConfigKit's release endpoint references into agreement with its
current Forge hosting. These are related identity updates, not changes to the
loading lifecycle, YAML syntax, composition, provenance, history, or secrets.
No runtime API redesign or compatibility-shim system is needed for this scope.
## Current Baseline
| Area | Baseline | Target |
| --- | --- | --- |
| Module declaration | `gitea.maximumdirect.net/eric/ConfigKit` in [go.mod](../../go.mod) | `go.maximumdirect.net/configkit` |
| Self-imports | Old module prefix throughout production packages, tests, benchmarks, and examples | New module prefix with the same package layout |
| Public package | Root-owned `configkit` facade over private internal packages | Same name and ownership under the new module identifier |
| Vanity discovery | Root and nested requests already advertise the Forge repository | Existing discovery continues to locate the migrated module |
| Git remote | `origin` uses `ssh://git@forge.maximumdirect.net:22222/base-layer/configkit.git` | Retain this SSH endpoint and align release configuration with it |
| Release configuration | [releasekit.json](../../releasekit.json), its test, and [runbook](../release.md) still name the old Gitea HTTPS endpoint | Consistent Forge publication references and vanity-path consumer commands |
Path-sensitive test expectations include
[import_boundary_test.go](../../import_boundary_test.go),
[facade_candidate_test.go](../../facade_candidate_test.go), and
[releasekit_profile_test.go](../../releasekit_profile_test.go). Compilation alone
will not identify every stale literal: a boundary test using the old prefix can
silently stop checking the intended imports.
### Preliminary External Verification
Checks against the baseline, using Go 1.26.10 and disposable modules/caches
outside the repository, established:
- HTTPS discovery at the module root and a nested package path returns a
`go-import` mapping from `go.maximumdirect.net/configkit` to
`https://forge.maximumdirect.net/base-layer/configkit`.
- Anonymous HTTPS Git access returns the expected `main` revision and release
tags, including v0.10.2.
- Go resolves and downloads v0.10.2 through direct retrieval and the standard
public-proxy/fallback configuration, with checksum verification enabled.
- A disposable consumer's `go get go.maximumdirect.net/configkit@v0.10.2`
reaches the repository but rejects its old module declaration. That is the
expected remaining mismatch, not a discovery failure.
These observations demonstrate that discovery and retrieval infrastructure work;
they do not establish that the migrated module builds or can be installed yet,
nor promise continuing external-service availability. No vanity-service change
was identified as necessary by these checks.
## Targeted End State
### Canonical Go Identity
The module declares `go.maximumdirect.net/configkit`. Production imports,
external-package tests, maintained examples, and path-sensitive expectations use
that prefix consistently. The package name remains `configkit`, and the root
remains the sole supported consumer import surface. Existing internal packages
stay internal; the migration does not expose them or change dependency direction.
The v1 module uses the unsuffixed path, with ordinary root-level release tags such
as `v1.0.0`. There is no `/v1` import suffix or module subdirectory to introduce.
The [Go module reference](https://go.dev/ref/mod#major-version-suffixes) owns the
language/toolchain conventions behind that choice.
Existing dependency and tool module identities are separate from ConfigKit's
identity. In particular, this work does not automatically rename or upgrade the
ReleaseKit requirement/tool declaration because the vanity service also advertises
a ReleaseKit path. Any dependency-path change should be assessed separately
against that upstream module's declared identity and available versions. The
current Go minimum and dependency versions are not selected for change here.
### Consumer Migration
Current installation/import examples identify the vanity path. The consumer guide
explains updating the module requirement and Go imports together, including
transitive libraries that exchange ConfigKit types with an application. Packages
loaded under the old and new prefixes have different Go identities; changing a
requirement alone does not make those types interchangeable.
This is a coordinated pre-v1 identity change. Old tags keep their original module
declarations and contents. The migration does not rewrite them to make historical
versions installable under the new path. Requesting an older tag through the
vanity identifier can still produce the observed module-declaration mismatch
even after this migration; consumers need a revision declaring the new path.
Maintained examples in this repository migrate with the library. Updating other
applications or maintaining a separate old-path compatibility module is outside
this effort; neither is required to declare the repository changes complete.
### Repository And Publication Identity
The vanity path identifies Go packages. Forge URLs identify the source repository,
browser pages, and publication transport. They remain distinct: Go HTTPS discovery
can use the public Forge HTTPS repository while maintainers push through SSH.
The authoritative publication endpoint remains
`ssh://git@forge.maximumdirect.net:22222/base-layer/configkit.git`. Retaining the
existing SSH `origin` avoids an unnecessary transport/credential change.
ReleaseKit's exact `expected_push_url`, its existing profile test, and the
runbook's literal publication/recovery commands agree with that endpoint.
Browser/tag links in current release guidance refer to the Forge HTTPS project,
not to the SSH transport or vanity import path. Public Go retrieval continues
using the verified Forge HTTPS repository independently. Authenticated write
capability still belongs to ordinary authorized release preparation; anonymous
HTTPS read success does not prove push access.
The existing release sequence, validation profile, permissions, immutable tags,
and successful-publication completion point are unchanged. This migration does
not introduce CI waiting, proxy-propagation waiting, native macOS checks, or
consumer installation as permanent release gates.
## Work Needed From The Baseline
### Module Declaration, Imports, And Tests
Update the module directive and all ConfigKit self-imports as one coordinated
change across root wrappers, engine/document/YAML packages, tests, benchmarks,
and maintained examples. Preserve the existing package layout and public symbol
names. Do not mechanically replace every old-host URL: dependency identities,
upstream attribution, and historical references have different owners.
Review import-boundary predicates, reflection package-path assertions, and any
other literal module checks alongside imports. Retain their existing protection
with the new identity rather than removing assertions to make the migration pass.
Review module metadata/tidiness as appropriate after changing the module path,
without using that review to bundle unrelated upgrades or tool migrations.
### Release Configuration And Current Guidance
Align `releasekit.json`, its test, and the runbook's publication/recovery commands
with the retained SSH endpoint. Update the runbook's module identity, HTTPS source
links, and consumer verification examples accordingly. Reflect only necessary
endpoint wording changes in the adopted release policy if its current text
requires them; its release guarantees and gates remain the same.
Review README, declaration documentation, the consumer guide, and applicable
development/internal documentation for current identity references. Describe the
consumer import/type-identity migration in the existing consumer migration
guidance. New release documentation, when prepared through the normal procedure,
should explain the change and use version-matched Forge source/license links.
Preserve historical release records, accepted ADR decision content, revision-pinned
audit evidence, upstream provenance links, and third-party module paths where
they describe their original material. A historical old-host reference is not an
unmigrated self-import. This roadmap does not authorize rewriting that history or
changing licensing arrangements.
### Proportionate Verification
Use the existing [development checks](../development.md#baseline-validation)
and [testing policy](../policy/testing.md). Verify the migrated module builds,
the default suite and maintained examples pass, and public/dependency boundary
checks still enforce the root/internal separation under the new prefix. The
eventual release retains its existing validation, rather than acquiring a second
validation framework or an expanded platform matrix.
When the migrated commit is available remotely, a one-time disposable consumer
check should retrieve that exact revision through the vanity path, without a
local replacement or workspace override, and compile a small public-API use.
An exact revision before tagging can exercise the migration without creating a
test release. Report direct retrieval and default proxy/fallback results
separately where both are checked; do not infer a successful install from
`go list` or archive download alone.
This remote check is migration evidence when the revised commit is available,
not authorization to push and not a new publication-completion gate. Keep network
checks outside the deterministic default suite, avoid polling external services,
and preserve the policy that successful tag publication completes a release.
After publication, retrieval of the exact released version remains optional and
non-gating under the existing procedure. Record any unavailable verification
honestly instead of claiming that baseline retrieval validates migrated code.
## Completion Criteria
- The repository consistently declares and imports the vanity module path,
while preserving the package name, facade ownership, and configuration behavior.
- Current documentation, examples, path-sensitive tests, and Forge publication
references agree with the implemented identities.
- Applicable local checks pass, without unrelated dependency or contract changes.
- Migration evidence distinguishes the preliminary infrastructure checks from
any later successful consumer installation of the actual migrated revision.
- Historical releases remain unchanged, and downstream migration guidance
explains both import changes and distinct Go type identities.
Repository implementation completion, external retrieval evidence, downstream
application adoption, and release publication are separate outcomes. No push,
tag, or downstream change is authorized merely by completing this roadmap.
No significant open decision remains for this migration.
## Implementation And Verification
The module declaration and all ConfigKit self-imports now use
`go.maximumdirect.net/configkit`, including internal packages, external-package
tests, maintained examples, and benchmarks. The import-boundary predicates and
root-type reflection expectations use the new prefix. Review of every changed
Go hunk confirmed only the intended module-prefix replacements and publication
URL expectation; no loading behavior or public symbol names changed.
`releasekit.json`, its profile test, and the runbook now use the retained Forge
SSH publication endpoint, matching the existing effective `origin` push URL.
The runbook distinguishes that transport from Forge HTTPS browser links and
vanity-path consumer retrieval. README and the consumer guide identify the new
import path; migration guidance covers named-type identity and historical tags.
The Go minimum, dependency/tool versions, and `go.sum` are unchanged. Historical
release records, accepted ADRs, adopted policies, and upstream attribution were
left intact. Remaining old ConfigKit path references describe the migration's
baseline, consumer upgrade instructions, or historical releases.
Local validation passed on Linux with Go 1.26.10 and cached dependencies:
```sh
GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off ./scripts/check.sh
GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off go mod tidy -diff
GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off go test -race ./...
```
The everyday check included maintained examples, documentation links, root type
ownership, dependency boundaries, and the release profile. Module/package
inspection reported the new main-module identity and no old ConfigKit imports
in the assembled test dependency graph. The module-selected ReleaseKit built
outside the checkout and reported v0.4.2. Module tidiness produced no diff.
### Remote Consumer Verification
With subsequent user authorization, migration commit
`587f407a32dec1e00d2aa17d2790c293d994721d` was pushed to authoritative `main`
through the retained Forge SSH endpoint. No release tag was created or published.
Two disposable consumer modules outside the repository retrieved that exact
revision through `go.maximumdirect.net/configkit`, using separate fresh module
caches and Go 1.26.10:
- Direct retrieval with `GOPROXY=direct` passed.
- Retrieval with `GOPROXY=https://proxy.golang.org,direct` passed. This verifies
the standard proxy/fallback configuration, not a proxy-only availability claim.
Checksum verification was enabled, `GOWORK=off` disabled workspace overrides, and
neither consumer had a `replace` directive. Go selected
`v0.10.3-0.20261101141937-587f407a32de`; the downloaded origin metadata identified
the exact migration commit in the Forge HTTPS repository. Both consumers received
the same module and module-file checksums.
After retrieval, each consumer passed `GOPROXY=off go test -mod=readonly -v ./...`.
The smoke test compiled and exercised the public API: explicit false/zero input
over typed defaults, effective provenance with `LayerMain`, source lookup by an
origin's source ID, and effective YAML rendering. Module inspection confirmed
that ConfigKit came from the corresponding fresh download cache, not the checkout.
This completes the one-time remote migration verification. The Go-generated
pseudo-version identifies an untagged commit; it is not an additional release.
No CI waiting or release gate was introduced.