Prepare ConfigKit v0.2.0

This commit is contained in:
2026-09-12 01:33:17 +00:00
parent 244104f84f
commit 8a62b42503
6 changed files with 67 additions and 299 deletions

View File

@@ -42,11 +42,9 @@ git show cb5b435:docs/roadmap/remediation.md
Release-candidate, publication, and verification work follows the operational
[release procedure](release.md).
The completed string-and-integer schema-version work remains recorded in its
[feature roadmap](roadmap/integer-schema-versions.md) and
[sequential implementation plan](roadmap/implementation.md) until release
preparation retires them. The [configuration contract](config.md) owns current
behavior.
The completed string-and-integer schema-version implementation and remediation
records are preserved in Git history at `244104f`. The
[configuration contract](config.md#application-schema-versions) owns current behavior.
## Baseline validation

View File

@@ -227,5 +227,11 @@ minor-version increment. The release note must explain the renamed directive,
the lack of a legacy alias, and the newly reserved application key. This exception
does not apply to subsequent releases or waive any validation or publication gate.
For v0.2.0 only, the maintainer accepted the successful native macOS check at
`244104f` for the final candidate, provided subsequent changes are documentation
only. The final candidate still requires the complete Linux release checker.
This exception waives only repeating the macOS check after those documentation
changes; it does not waive other publication or verification gates.
Candidate selection, publication, and post-publication verification remain
mandatory steps in the [release procedure](../release.md).

58
docs/releases/v0.2.0.md Normal file
View File

@@ -0,0 +1,58 @@
# ConfigKit v0.2.0
This release adds integer schema-version input and consistent canonical sequence
path handling.
## Summary
Applications can retain YAML such as `version: 4` while storing and checking their
version as a Go string. The exception applies only to the path designated by
`VersionRule`; unrelated fields keep strict decoding. See the
[configuration contract](../config.md#application-schema-versions).
## Compatibility
This minor release intentionally changes integer schema-version input from a
`version.type` rejection to invoking the application checker with its decimal text.
Plain string destinations at that path now accept it. Public Go API shapes,
minimum Go version, and supported platforms are unchanged.
Parsed sequence indices now require canonical nonnegative decimal spelling.
Signed tokens such as `+0` and `-0`, previously accepted by some traversal paths,
no longer identify sequence elements. They remain valid literal mapping keys.
Version checking, decoding, and metadata matching now agree on this boundary.
The private YAML dependency remains pinned to `go.yaml.in/yaml/v4 v4.0.0-rc.6`,
confirmed as the newest available v4 release during candidate preparation. Linux
candidate checks use Go 1.25.5 and Go 1.26.7. The maintainer confirmed native macOS
checks at `244104f` and approved carrying that result across the documentation-only
candidate changes under the [recorded exception](../policy/release.md#policy-exceptions).
## Upgrade
```sh
go get gitea.maximumdirect.net/eric/ConfigKit@v0.2.0
```
Existing string schema versions need no configuration changes. Applications using
integer YAML versions can retain them and use a plain string field plus a
`VersionRule`. Review the application checker: it now receives integer identifiers
as text, and remains responsible for rejecting unsupported versions. Fractions,
exponents, booleans, and containers remain invalid version kinds.
Replace signed sequence-index tokens in configured paths with canonical indices
(for example, `/versions/+0` becomes `/versions/0`). Do not change signed mapping
keys. Literal integers elsewhere still do not decode into strings, and numeric
destinations retain their existing range checks.
## Changes
- Added load-local, path-scoped integer-to-string schema-version decoding without
mutating original input or introducing general scalar coercion.
- Preserved numeric historical input, string effective output, decoding
reconciliation, source attribution, and secret redaction.
- Unified sequence path interpretation and added regression coverage for signed
tokens, literal mapping keys, and explicit key/index distinctions.
- Updated maintained Notarius-shaped fixtures and migration guidance for quoted
and integer version forms.
- Retired completed implementation and remediation roadmaps to Git history.

View File

@@ -1,190 +0,0 @@
# Integer schema versions: implementation plan
Status: implementation complete (2026-09-12). The
[feature roadmap](integer-schema-versions.md) records the feature scope, the
[configuration contract](../config.md) owns implemented behavior, and this document
owns execution and progress.
## Execution rules
Execute stages sequentially. Each stage is a bounded assignment for one
gpt-5.6-terra coding agent: one coherent outcome, targeted files, focused tests,
and a reviewable handoff. Do not delegate or parallelize dependent stages by
default. No stage authorizes changing downstream repositories or publishing a tag.
Before each stage, read [development](../development.md), the relevant task-specific
policies, the roadmap, and the preceding handoff. Inspect the worktree and preserve
unrelated work. Prefer the repository's code graph for code discovery, and verify
current symbols rather than assuming the file inventory below is frozen.
Keep every stage green: add behavioral coverage alongside its implementation, run
the stated focused commands and `./scripts/check.sh`, and update implemented
contracts in the same change. Do not relax tests unrelated to this feature.
Record files changed, commands/results, remaining risks, and the next stage here.
Commit a coherent stage when committing is authorized; otherwise hand off its diff.
## Stage 1 — Deliver the checker-to-decoder vertical slice
Status: complete (2026-09-12). Depends on: none.
Scope: `validation.go`, the private decoding plumbing in `decode.go` and
`load_result.go`, necessary private call sites, and focused version/decode tests.
- Add the shared private integer-text recognition and extend `checkVersion`
according to the roadmap. Preserve diagnostics, callback order, and public types.
- Thread per-load version-path context to recursive decoding; enable integer to
plain-string decoding only at that path. Do not mutate source/history trees or
type-wide descriptors. Keep no-rule decoder callers strict.
- Add public-load coverage for integer and string `4` into `string` and `*string`,
identical checker text, absent/null states, and unsupported version kinds.
- Keep the suite green by updating the existing integer-version rejection test in
`load_test.go`. In `examples/consumers/consumers_test.go`, remove integer input
from the structural-rejection expectation or convert it to the appropriate
success/domain-policy assertion; do not merely delete migration coverage.
- Update `Version`/`VersionRule` comments, the configuration contract's version and
conversion sections, and stale consumer claims that all integer versions must
be rewritten. Describe only behavior implemented by this stage.
Acceptance: a full load of `version: 4` with a configured rule and string-backed
field succeeds and stores `"4"`; without the rule it still fails strict decoding.
An unrelated integer-to-string field still fails. Existing accepted input remains
unchanged. Both checking and decoding are implemented before this stage is done.
Validation: `go test . -run 'Version|Decode'`,
`go test ./examples/consumers`, then the everyday checker.
Completion record: checker and load-local decoder support landed with strict
no-rule and unrelated-field behavior retained. Focused package tests, consumer
tests, and `./scripts/check.sh` pass with Go 1.26.7 on Linux. Stage 2 should expand
the scalar, destination-type, and semantic-path boundary matrix.
## Stage 2 — Close scalar and path-boundary gaps
Status: complete (2026-09-12). Depends on: Stage 1.
Scope: focused tests in `load_test.go`, `decode_test.go`, and relevant path/decoder
helpers only where those tests expose defects. Avoid broad schema refactoring.
- Cover zero, negative integer, `-0`, a decimal identifier beyond int64 range,
empty string, fractional/exponent numbers, booleans, and containers. Check parser
rejection remains separate for non-JSON numeric spellings; reuse parser coverage.
- Exercise a nonstandard nested version path, an escaped mapping key, contextual
numeric path tokens, and sibling fields sharing a named string type. Prove
conversion is path-scoped rather than descriptor-wide or name-based.
- Cover named strings and pointer wrappers; show integer destinations and dynamic
values retain ordinary types/range errors, while custom text codecs, durations,
and secret-reference destinations do not gain integer coercion.
- Verify unsupported kinds prevent the version callback, accepted integer input
reaches application policy, and rejection by that policy prevents later hooks.
Assert codes, semantic paths, and locations, not incidental message wording.
Acceptance: the target scalar/destination matrix is covered with lean table-driven
tests, no silent overflow/rounding, and no coercion leakage to unrelated fields or
loads. Expand a stage-1 test instead of duplicating the same behavior.
Validation: `go test . -run 'Version|Decode|Path'`, then the everyday checker.
Completion record: boundary coverage now includes exact zero, negative, negative
zero, unbounded textual integer, rejected scalar/container kinds, parsed numeric
tokens in maps and sequences, escaped keys, named and nested-pointer strings, and
ordinary numeric, dynamic, codec, duration, and secret destinations. Existing
parser-policy tests continue to own non-JSON number rejection. The focused command
and `./scripts/check.sh` pass with Go 1.26.7 on Linux. Stage 3 should verify retained
history, rendering, composition ownership, detachment, and redaction invariants.
## Stage 3 — Verify provenance and pipeline invariants
Status: complete (2026-09-12). Depends on: Stage 2.
Scope: `explain_test.go`, `provenance_test.go`, import/profile/override and secret
test owners as needed. Production changes only for demonstrated integration gaps.
- Add an end-to-end integer-version case asserting final string configuration,
effective string rendering, original numeric history, and the existing decoding
reconciliation event. Confirm locations, explicitness, and historical lookup.
- Exercise equal-valued defaults and detached repeated loads/queries so conversion
does not masquerade as resolution or mutate retained input.
- Verify integer versions do not bypass fragment-version rejection, profile version
protection, or CLI overlap checks; extend existing owners rather than recreating
each suite. Include a nonstandard version path where practical.
- Check sensitive original/effective version snapshots remain redacted and that
the conversion adds no secret resolution or credential-bearing diagnostics.
Use synthetic fixtures and existing lookup seams, never real credentials.
Acceptance: typed configuration, metadata, rendering, and explanation agree; the
only intentional change is the version input/decoding exception. If inspection
needs repair, retain original input rather than suppressing its history.
Validation: `go test . -run 'Version|Import|Profile|Override|Provenance|Explain|Secret'`,
`go test -race ./...`, then the everyday checker.
Completion record: end-to-end inspection now proves a numeric retained input, a
string typed/effective value, a decoding reconciliation event, exact base origin
and location, historical lookup, equal-default handling, and detached repeated
results. Integer fixtures exercise fragment, profile, and CLI version protection.
Sensitive version history is redacted and performs no credential lookup. The
focused suite, race suite, and `./scripts/check.sh` pass with Go 1.26.7 on Linux.
Stage 4 should finish the maintained Notarius evidence, canonical documentation,
and release-readiness validation without publishing a release.
## Stage 4 — Complete consumer evidence and release readiness
Status: complete (2026-09-12). Depends on: Stage 3.
Scope: maintained Notarius-shaped examples/fixtures, consumer documentation,
documentation consistency review, and validation handoff. No downstream app edits.
- Make integer `version: 4` and quoted `version: "4"` representative successful
Notarius-shaped inputs with the same string-backed application result. Configure
the example's application checker consistently; do not bypass version policy.
- Retain negative examples for unsupported application versions and non-integer
version kinds, with stable diagnostic codes/paths. Verify unrelated dynamic
option integers and runtime conversions remain unchanged.
- Audit current documentation and Go examples for string-only claims. Keep
historical release notes, extraction records, and ADR rationale historical;
repair navigation without rewriting historical decisions. Transfer completed
target descriptions from the roadmap to canonical owners.
- Run the full release checker using the command below (or qualifying cached
toolchains selected under the release runbook). Report actual versions and results.
- Hand off the compatibility assessment and remaining release work. Select an
unused version with the maintainer; create version-matched notes only for a real
candidate. A changed rejection contract must be reviewed explicitly; do not reuse
the v0.1.1-only policy exception.
Acceptance: complete consumer regression and all available automated gates pass;
no current documentation promises unimplemented behavior. Mark implementation
complete separately from publication. Exact-commit Linux/macOS checks, candidate
commit/push, release-note approval, roadmap retirement, tagging, and clean consumer
retrieval follow the [release procedure](../release.md) when separately authorized.
Unavailable macOS evidence is a release blocker, not permission to waive the gate.
Validation: `go test ./examples/consumers`, `go test . -run '^Example'`, the everyday
checker, and the full release checker:
```sh
CONFIGKIT_BASELINE_TOOLCHAIN=go1.25.5 \
CONFIGKIT_NEWER_TOOLCHAIN=go1.26.7 \
./scripts/release-check.sh
```
Rerun exact-commit release checks after
any later candidate or roadmap-retirement changes.
Completion record: maintained Notarius fixtures now accept integer `4` and quoted
`"4"` with the same string-backed result. Unsupported integer `5` reaches domain
policy, fractional `4.0` remains `version.type`, and dynamic option integers remain
`int64`. Current documentation and Go examples were audited; canonical behavior is
owned by the configuration contract and consumer guide, while historical release,
extraction, and ADR records were left unchanged. The focused consumer/example
commands, `./scripts/check.sh`, and the full release checker pass on Linux with
Go 1.25.5 and Go 1.26.7.
Compatibility handoff: exported API shapes are unchanged, but integer input at a
configured version path intentionally changes from structural rejection to invoking
application policy and, for plain string destinations, successful decoding. The
conservative release choice is therefore a new pre-v1 minor version, subject to
maintainer selection and unused-version checks. No version, note, candidate, or tag
was created. Release preparation must still select the version, create and approve
matching notes, retire these completed roadmap files, rerun Linux and native macOS
checks on the exact candidate commit, push and guard that commit, publish the exact
tag, and verify clean consumer retrieval.

View File

@@ -1,17 +0,0 @@
# String and integer schema versions
Status: implemented on 2026-09-12; retained until release preparation. The
[implementation plan](implementation.md) records validation and stage handoffs.
ConfigKit now accepts strings and strict decimal-integer syntax at the exact path
configured by `Definition.Version`. The application checker and a plain
string-backed destination receive the preserved text, while all unrelated decoding
remains strict. Composition ownership, source history, explanation reconciliation,
and secret redaction retain their existing behavior.
The [configuration contract](../config.md#application-schema-versions) is the
canonical definition of the implemented behavior. The
[consumer adoption guide](../consumers/README.md) links maintained Notarius-shaped
string and integer examples. This roadmap chooses no release version and grants no
publication authority; compatibility review and roadmap retirement follow the
[release procedure](../release.md) when separately authorized.

View File

@@ -1,87 +0,0 @@
# Integer schema version remediation
Review baseline: `fd8a68d`, covering implementation commits `f5bbc2b` through
`fd8a68d` against `b3e7b62`. Status: finding resolved. This document records
required corrective work, not an implemented contract or release approval.
## R1 — Unify sequence-path interpretation between checking and decoding
Priority: medium. Status: resolved.
Resolution: sequence traversal now requires canonical nonnegative decimal index
tokens in the shared `schemaIndex` helper. Version decoding reuses
`matchesPathShape`, which shares that helper with traversal; its independent
numeric matcher was removed. Signed tokens remain literal mapping keys but no
longer alias sequence elements. Public-load regression coverage verifies numeric
and quoted input, metadata lookup, mapping keys, and explicit segment intent.
Focused Version/Decode/Path tests and the everyday checker passed on Linux.
### Finding and evidence
The new `pathMatches` helper in [validation.go](../../validation.go) implements
sequence-token matching independently of the existing `schemaIndex` helper in
[schema.go](../../schema.go). `checkVersion` looks up its node through
`documentAtPath`, which uses `schemaIndex`; typed integer-to-string conversion
instead uses `pathMatches`.
These rules disagree. `schemaIndex` currently accepts parsed `+0` and `-0` as
sequence index zero through `strconv.Atoi`, but `pathMatches` requires the exact
canonical spelling returned by `strconv.Itoa`, namely `0`.
A public-API probe against the review baseline used a configuration with
`Versions []string` bound to `versions`, a no-op version checker, and each path
returned by `ParsePath`:
| Configured path | YAML value | Checker receives | Load result |
| --- | --- | --- | --- |
| `/versions/0` | `[4]` | Present, text `4` | Success |
| `/versions/0` | `['4']` | Present, text `4` | Success |
| `/versions/+0` | `[4]` | Present, text `4` | Decode failure |
| `/versions/+0` | `['4']` | Present, text `4` | Success |
| `/versions/-0` | `[4]` | Present, text `4` | Decode failure |
| `/versions/-0` | `['4']` | Present, text `4` | Success |
Thus the checker accepts and identifies a version node, but the decoder does not
recognize that same node as the configured version path. Canonical index paths and
the ordinary Notarius `version` mapping key work correctly. The permissive lookup
predates these commits; the new, separately implemented matcher introduces the
checker/decoder disagreement. The existing canonical-index tests do not catch it.
### Required correction
Establish one sequence-token interpretation for version lookup and conversion,
using shared semantic-path machinery rather than independent numeric spelling
rules. Preserve explicit mapping-key versus index intent and exact string matching
for mapping keys. Do not simply substitute a helper without checking its semantics:
metadata matching also compares pointer spellings before interpreting indices.
Decide explicitly whether noncanonical signed sequence tokens are supported or
rejected. If retaining current lookup behavior, decoding must identify the same
node. If tightening it to canonical JSON Pointer sequence indices, apply that rule
consistently to lookup and matching, document the compatibility impact, and ensure
the checker cannot report a present version that conversion refuses to recognize.
Do not broaden mapping-key matching or unrelated scalar coercion as a workaround.
### Acceptance and verification
- Add public-load regressions for integer and string input with canonical and
signed parsed sequence tokens, asserting checker presence/text and decoding
outcomes under the chosen policy.
- Retain coverage for literal numeric/signed mapping keys, escaped keys, explicit
`Key`/`Index` distinctions, and unrelated string fields.
- Verify lookup, version checking, and conversion share the chosen semantics;
check other users of any shared path helper changed by the fix.
- Run `go test . -run 'Version|Decode|Path'`, `./scripts/check.sh`, and the full
release checker before selecting a corrected release candidate.
## Review validation and remaining release work
The full release checker passed on Linux at the review baseline with Go 1.25.5
and Go 1.26.7, including race tests, examples, documentation links, and cross-builds.
The independent public-API probe above exposed behavior outside that suite.
No production code or existing tests were modified during review.
Release selection, version-matched notes, retirement of completed roadmap material,
and exact-candidate native Linux/macOS validation remain governed by the
[release procedure](../release.md). They are separate from resolving R1; older
release validation is not evidence for a newly changed candidate.