Widen A12 enforcement from the key name to the declaration's content (GH-DEC-2026-020).
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Build and Publish Container Image / build-and-push (push) Successful in 1m11s

internal/layer/conformance.go enforced A12 as "no key named standard_version",
and so could not see the same pin as a versioned standard: path or as
companion_version. It now detects a version of the standard or its companion
in any key or value of the declaration (INTENT.md frontmatter, layer.yaml),
including a version in a path, and excludes comments and schema_version. It
refuses to be applied to pep-stance.yaml, pip-claims.yaml or
evidence-classification.yaml, which A12 r2 does not reach (§3).

Every run of check_layer_conformance and of the estate survey now prints the
standard version it checks against (layer.ValidatedAgainst, kings-guard's
pattern) and its scope (§4). The survey applies the same detection to peers'
declarations; the receipt is refreshed because the survey's output changed
(no peer declaration currently carries a version).

Tests fail if a versioned standard: path or a companion_version comes back.
flex-auth's own INTENT.md needed no change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 63291@bnt-lap001
Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703
This commit is contained in:
tegwick 2026-09-21 09:39:46 +02:00
parent 2be655703d
commit e0c6c4389d
7 changed files with 334 additions and 17 deletions

View file

@ -4,6 +4,7 @@ import (
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"github.com/netkingdom/flex-auth/internal/layer"
@ -202,3 +203,99 @@ func repoRoot(t *testing.T) string {
}
return filepath.Clean(filepath.Join(filepath.Dir(file), "..", ".."))
}
// A12 r2 reaches CONTENT, not a key name (GH-DEC-2026-020 §1, §2). Each of these
// is a version of the standard or its companion that a key-name check on
// `standard_version` could not see. If any of them comes back into a
// declaration, this test fails.
func TestVersionAnywhereInDeclarationIsFound(t *testing.T) {
for name, doc := range map[string]string{
"versioned standard path": "layer: Engine\nstandard: net-kingdom/canon/standards/security-layer-model_v0.7.md\n",
"versioned companion path": "layer: Engine\ncompanion: net-kingdom/SECURITY-COMPANION_v0.2.md\n",
"companion_version": "layer: Engine\ncompanion_version: \"0.2\"\n",
"standard_version": "layer: Engine\nstandard_version: \"0.8\"\n",
"bare version under standard": "layer: Engine\nstandard: \"v0.8\"\n",
"nested versioned path": "layer: Engine\nassented_by:\n - ref: security-layer-model_v0.8.md\n",
"version in a list of sources": "layer: Engine\nsources: [net-kingdom/canon/standards/security-layer-model_v0.6.md]\n",
} {
pins, err := layer.VersionPins(doc)
if err != nil {
t.Fatalf("%s: %v", name, err)
}
if len(pins) == 0 {
t.Errorf("%s: version was not detected in %q", name, doc)
}
}
}
// What A12 r2 states it does NOT reach: comments, schema_version, and versions
// that are not versions of the standard or its companion. Unversioned standard
// and companion paths are the conforming form.
func TestVersionPinsLeavesWhatA12DoesNotReach(t *testing.T) {
doc := "# declared against security-layer-model_v0.7.md, kept as history\n" +
"schema_version: \"0.2\"\n" +
"intent_version: 0.1.0\n" +
"layer: engine # v0.8 comment\n" +
"standard: net-kingdom/canon/standards/security-layer-model\n" +
"companion: net-kingdom/SECURITY-COMPANION.md\n" +
"declared_at: \"2026-08-29\"\n" +
"declared_by: decisions/decisions.md FLEX-DEC-2026-001\n" +
"companion_version:\n"
pins, err := layer.VersionPins(doc)
if err != nil {
t.Fatal(err)
}
if len(pins) != 0 {
t.Fatalf("A12 r2 reached what it does not reach: %v", pins)
}
}
// Check must fail on a declaration whose only pin is in the standard: path.
// Stance, claims and classification maps SHOULD carry the version of the text
// they answer; a run MUST NOT apply A12 to them (GH-DEC-2026-020 §3).
func TestCheckRejectsVersionedStandardPathButNotStanceMaps(t *testing.T) {
good := "---\nlayer: Engine\nrole: PDP\nconformance_record: record.md\nsource_of_evidence: false\n" +
"standard: net-kingdom/canon/standards/security-layer-model\n---\n\n# x\n"
dir := t.TempDir()
for name, body := range map[string]string{
"INTENT.md": good,
"record.md": "x\n",
"pep-stance.yaml": "standard_version: \"0.8\"\n",
"pip-claims.yaml": "standard_version: \"0.8\"\nstandard: security-layer-model_v0.8.md\n",
"evidence-classification.yaml": "standard_version: \"0.8\"\n",
} {
if err := os.WriteFile(filepath.Join(dir, name), []byte(body), 0o644); err != nil {
t.Fatal(err)
}
}
if err := layer.Check(dir); err != nil {
t.Fatalf("a version in a stance/claims/classification map failed the declaration check: %v", err)
}
for _, f := range []string{"pep-stance.yaml", "pip-claims.yaml", "evidence-classification.yaml"} {
if _, err := layer.DeclarationVersionPins(filepath.Join(dir, f)); err == nil {
t.Errorf("DeclarationVersionPins accepted %s; A12 r2 must not be applied to it", f)
}
}
bad := strings.Replace(good, "security-layer-model\n", "security-layer-model_v0.7.md\n", 1)
if err := os.WriteFile(filepath.Join(dir, "INTENT.md"), []byte(bad), 0o644); err != nil {
t.Fatal(err)
}
if err := layer.Check(dir); err == nil {
t.Fatal("a versioned standard: path in INTENT.md was accepted")
}
}
// flex-auth's own declaration carries no version under any key (A12 r2).
func TestOwnDeclarationCarriesNoVersionAnywhere(t *testing.T) {
pins, err := layer.DeclarationVersionPins(filepath.Join(repoRoot(t), "INTENT.md"))
if err != nil {
t.Fatal(err)
}
if len(pins) != 0 {
t.Fatalf("INTENT.md declaration carries a version: %v", pins)
}
if layer.ValidatedAgainst == "" {
t.Fatal("the checker must state the version it validates against on every run")
}
}