Unify canonical sequence index semantics for version decoding
This commit is contained in:
87
docs/roadmap/remediation.md
Normal file
87
docs/roadmap/remediation.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user