ValidatedAgainst named the proposed v0.8, which is held under GH-DEC-2026-019, so every run claimed a check against text that does not govern. It now names security-layer-model_v0.7.md (net-kingdom@66dc491) as amended by GH-DEC-2026-017, -020 and -021 (gate-house@39d9287), per 021 §2. The pin detector converges on ops-warden's reference (021 §3): keys naming a standard or companion version, versions in path or file-name tokens, and the 021 addition of any version token in a standard:/companion: value. A revision cited in prose is provenance and is no longer reached (021 §1), including under standard_*-prefixed keys that name no version. One kept difference: an empty version key carries no version and is not flagged. Survey receipt refreshed; no declaration in the estate carries a pin. 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
309 lines
12 KiB
Go
309 lines
12 KiB
Go
package layer_test
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/netkingdom/flex-auth/internal/layer"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
func TestLayerDeclarationConforms(t *testing.T) {
|
|
root := repoRoot(t)
|
|
if err := layer.Check(root); err != nil {
|
|
t.Fatalf("layer conformance: %v", err)
|
|
}
|
|
|
|
decl, err := layer.LoadDeclaration(filepath.Join(root, "INTENT.md"))
|
|
if err != nil {
|
|
t.Fatalf("LoadDeclaration: %v", err)
|
|
}
|
|
if decl.Layer != "Engine" {
|
|
t.Fatalf("layer = %q; want Engine", decl.Layer)
|
|
}
|
|
if decl.Role != "PDP" {
|
|
t.Fatalf("role = %q; want PDP", decl.Role)
|
|
}
|
|
if decl.Framework != "netkingdom-security-layer-model" {
|
|
t.Fatalf("framework = %q", decl.Framework)
|
|
}
|
|
// The declaration is a boundary and must NOT pin a standard version: the
|
|
// role does not change when the standard text is amended. Version-scoped
|
|
// conformance state lives in the derived record named below.
|
|
if decl.StandardVersion != "" {
|
|
t.Fatalf("standard_version = %q; want empty (boundary, not version-scoped)", decl.StandardVersion)
|
|
}
|
|
if decl.ConformanceRecord == "" {
|
|
t.Fatal("conformance_record is empty; version-stamped state must have a home")
|
|
}
|
|
if _, err := os.Stat(filepath.Join(repoRoot(t), decl.ConformanceRecord)); err != nil {
|
|
t.Fatalf("conformance_record %q does not exist: %v", decl.ConformanceRecord, err)
|
|
}
|
|
// GH-DEC-2026-018: flex-auth is the §4 source of evidence for the decision
|
|
// record and owes a per-event-class emission guarantee. The declaration
|
|
// must say so and must name the published inventory.
|
|
if decl.SourceOfEvidence == nil || !*decl.SourceOfEvidence {
|
|
t.Fatal("source_of_evidence must be true: GH-DEC-2026-018 §2")
|
|
}
|
|
if decl.EmissionGuarantee == "" {
|
|
t.Fatal("emission_guarantee is empty; §11 requires it of a §4 evidence source")
|
|
}
|
|
if _, err := os.Stat(filepath.Join(repoRoot(t), decl.EmissionGuarantee)); err != nil {
|
|
t.Fatalf("emission_guarantee %q does not exist: %v", decl.EmissionGuarantee, err)
|
|
}
|
|
}
|
|
|
|
// The per-class rule is the operative half of GH-DEC-2026-018 §3: a single
|
|
// repository-level guarantee over a stream carrying both a high-volume allow
|
|
// and a rare deny is an average, not a declaration. Assert the published
|
|
// inventory actually classifies each class, so a later edit cannot collapse it
|
|
// back into one number.
|
|
func TestEmissionInventoryIsPerEventClass(t *testing.T) {
|
|
root := repoRoot(t)
|
|
body, err := os.ReadFile(filepath.Join(root, "cadence.yaml"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var doc struct {
|
|
Source string `yaml:"source"`
|
|
Classes map[string]struct {
|
|
Action string `yaml:"action"`
|
|
EvidenceClass string `yaml:"evidence_class"`
|
|
Rarity string `yaml:"rarity"`
|
|
RateMonitoring string `yaml:"rate_monitoring"`
|
|
Detection []string `yaml:"detection"`
|
|
} `yaml:"classes"`
|
|
}
|
|
if err := yaml.Unmarshal(body, &doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(doc.Classes) < 2 {
|
|
t.Fatal("cadence.yaml declares fewer than two event classes; §11 requires the guarantee per class, not per repository")
|
|
}
|
|
for name, c := range doc.Classes {
|
|
if c.Action == "" || c.EvidenceClass == "" || c.Rarity == "" {
|
|
t.Errorf("class %q: action, evidence_class and rarity must all be published — a run may not infer them (§11)", name)
|
|
}
|
|
// A rare load-bearing class MUST carry heartbeat AND reconciliation and
|
|
// MUST NOT be covered by rate monitoring.
|
|
if c.EvidenceClass == "load-bearing" && c.Rarity == "rare" {
|
|
if c.RateMonitoring != "forbidden" {
|
|
t.Errorf("class %q is rare load-bearing; rate_monitoring must be forbidden", name)
|
|
}
|
|
var heartbeat, reconciliation bool
|
|
for _, d := range c.Detection {
|
|
heartbeat = heartbeat || d == "heartbeat"
|
|
reconciliation = reconciliation || d == "reconciliation"
|
|
}
|
|
if !heartbeat || !reconciliation {
|
|
t.Errorf("class %q is rare load-bearing; it must carry heartbeat AND reconciliation, not either alone", name)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestVersionPinInDeclarationIsRejected(t *testing.T) {
|
|
err := layer.ValidateDeclaration(layer.Declaration{
|
|
Layer: "Engine", Role: "PDP",
|
|
ConformanceRecord: "docs/conformance/security-layer-conformance.md",
|
|
StandardVersion: "0.8",
|
|
})
|
|
if err == nil {
|
|
t.Fatal("a standard_version pin in the boundary declaration was accepted")
|
|
}
|
|
}
|
|
|
|
func TestEngineWithoutRoleIsRejected(t *testing.T) {
|
|
err := layer.ValidateDeclaration(layer.Declaration{Layer: "Engine"})
|
|
if err == nil {
|
|
t.Fatal("Engine without role was accepted")
|
|
}
|
|
}
|
|
|
|
func TestUnknownLayerIsRejected(t *testing.T) {
|
|
err := layer.ValidateDeclaration(layer.Declaration{Layer: "ControlPlane", Role: "PDP"})
|
|
if err == nil {
|
|
t.Fatal("unknown layer was accepted")
|
|
}
|
|
}
|
|
|
|
// The defect this validator carried: the vocabulary has FOUR tokens and this
|
|
// set admitted three, omitting the layer the standard itself occupies.
|
|
// railiance-master's `Taxonomy` was conforming and the checker was wrong.
|
|
func TestVocabularyHasFourTokensIncludingTaxonomy(t *testing.T) {
|
|
want := map[string]bool{"Taxonomy": true, "Tooling": true, "Engine": true, "Staff": true}
|
|
got := layer.Vocabulary()
|
|
if len(got) != len(want) {
|
|
t.Fatalf("vocabulary = %v; want the four §3 tokens", got)
|
|
}
|
|
for _, tok := range got {
|
|
if !want[tok] {
|
|
t.Errorf("unexpected token %q", tok)
|
|
}
|
|
}
|
|
if canon, ok := layer.CanonicalLayer("Taxonomy"); !ok || canon != "Taxonomy" {
|
|
t.Fatal("Taxonomy was rejected: §3.1 defines it, §4 catalogues it twice, and the standard is an instance of it")
|
|
}
|
|
}
|
|
|
|
// GH-DEC-2026-017 §2: comparison is ASCII case-insensitive and a run MUST fold
|
|
// before comparing. A lowercase declaration is conforming, not tolerated.
|
|
func TestVocabularyComparisonFoldsCase(t *testing.T) {
|
|
for _, in := range []string{"engine", "ENGINE", "Engine", " engine "} {
|
|
canon, ok := layer.CanonicalLayer(in)
|
|
if !ok {
|
|
t.Fatalf("%q was rejected; comparison must fold ASCII case", in)
|
|
}
|
|
// §4's column form is canonical, so the folded result reports as `Engine`
|
|
// however the declaration spelled it.
|
|
if canon != "Engine" {
|
|
t.Fatalf("CanonicalLayer(%q) = %q; want the §4 column spelling Engine", in, canon)
|
|
}
|
|
}
|
|
if err := layer.ValidateDeclaration(layer.Declaration{
|
|
Layer: "engine", Role: "PDP",
|
|
ConformanceRecord: "docs/conformance/security-layer-conformance.md",
|
|
SourceOfEvidence: boolPtr(true), EmissionGuarantee: "cadence.yaml",
|
|
}); err != nil {
|
|
t.Fatalf("a lowercase declaration was rejected: %v", err)
|
|
}
|
|
}
|
|
|
|
// §3's table heading reads `Engines`, plural, while §4's column reads `Engine`.
|
|
// A9 states the token once and it is §4's. A declaration of `Engines` is a
|
|
// declaration of a token the vocabulary does not have.
|
|
func TestPluralEnginesIsNotTheToken(t *testing.T) {
|
|
if _, ok := layer.CanonicalLayer("Engines"); ok {
|
|
t.Fatal("`Engines` was admitted; the token is `Engine`, as §4's Layer column carries it")
|
|
}
|
|
}
|
|
|
|
// A §4 evidence source that names no emission guarantee is not conforming.
|
|
func TestEvidenceSourceWithoutEmissionGuaranteeIsRejected(t *testing.T) {
|
|
err := layer.ValidateDeclaration(layer.Declaration{
|
|
Layer: "Engine", Role: "PDP",
|
|
ConformanceRecord: "docs/conformance/security-layer-conformance.md",
|
|
SourceOfEvidence: boolPtr(true),
|
|
})
|
|
if err == nil {
|
|
t.Fatal("a marked evidence source with no emission_guarantee was accepted")
|
|
}
|
|
}
|
|
|
|
func boolPtr(b bool) *bool { return &b }
|
|
|
|
func repoRoot(t *testing.T) string {
|
|
t.Helper()
|
|
_, file, _, ok := runtime.Caller(0)
|
|
if !ok {
|
|
t.Fatal("runtime.Caller failed")
|
|
}
|
|
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",
|
|
"prose version under standard": "layer: Engine\nstandard: security-layer-model v0.7\n",
|
|
"version under companion": "layer: Engine\ncompanion: SECURITY-COMPANION 0.2\n",
|
|
"reviewed-version key": "layer: Engine\nstandard_version_reviewed: \"0.7\"\n",
|
|
"at-version reference": "layer: Engine\nsource: net-kingdom@0.7\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" +
|
|
// GH-DEC-2026-021 §1: a revision cited in prose is provenance, not a
|
|
// pin, even under a standard_*-prefixed key that names no version.
|
|
"standard_note: the standard's v0.5 scope rule\n" +
|
|
"rationale: adopted under security-layer-model v0.7 and GH-DEC-2026-020\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")
|
|
}
|
|
}
|