flex-auth/internal/layer/conformance_test.go

205 lines
7.4 KiB
Go
Raw Normal View History

package layer_test
import (
Make the layer declaration a boundary, and review the boundaries it implies. INTENT.md pinned standard_version: "0.7" in the frontmatter §11 requires. That conflated two things the standard separates itself: assent "records assent to a BOUNDARY, given at the version named. It is not assent to the current text." flex-auth is Engine/PDP at v0.6, v0.7, v0.8 and after; the role does not change when the text is amended. The field was also decorative — parsed into Declaration.StandardVersion and never validated — so the version was load-bearing only via a test asserting it equalled 0.7. That test is inverted rather than deleted: internal/layer now rejects a version pin in the declaration and requires conformance_record to name a file that exists. Version-scoped state moves to docs/conformance/security-layer-conformance.md, a derived artifact carrying what it derives from and the version derived at, as §11 requires of derived artifacts. SCOPE.md: gap assessment replaces "conforming with one declared gap" with three gaps, each with an owner and a route. G2 is new — flex-auth declares no emission guarantee where §11 requires one of every §4 source of evidence. It is recorded as a gap rather than as conformance because the flattering reading, that audit-core is the source and flex-auth merely produces, has been asserted by nobody but flex-auth. Also corrects the stance register from two rows to five. Fixing one line meant reading what the declaration asserts, and a boundary is only half held here. docs/conformance/boundaries-review.md checks the other halves across twelve counterparts and finds four security-relevant repositories with no layer declaration at all — including key-cape, the identity source whose claims flex-auth consumes as normative input. That boundary is asserted from one side only. Recorded as unstated, never as agreed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 28468@bnt-lap001 Assistant-Session: c76569b2-6056-4dad-aea4-49cd7a018f5d
2026-09-21 00:11:56 +02:00
"os"
"path/filepath"
"runtime"
"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)
}
Make the layer declaration a boundary, and review the boundaries it implies. INTENT.md pinned standard_version: "0.7" in the frontmatter §11 requires. That conflated two things the standard separates itself: assent "records assent to a BOUNDARY, given at the version named. It is not assent to the current text." flex-auth is Engine/PDP at v0.6, v0.7, v0.8 and after; the role does not change when the text is amended. The field was also decorative — parsed into Declaration.StandardVersion and never validated — so the version was load-bearing only via a test asserting it equalled 0.7. That test is inverted rather than deleted: internal/layer now rejects a version pin in the declaration and requires conformance_record to name a file that exists. Version-scoped state moves to docs/conformance/security-layer-conformance.md, a derived artifact carrying what it derives from and the version derived at, as §11 requires of derived artifacts. SCOPE.md: gap assessment replaces "conforming with one declared gap" with three gaps, each with an owner and a route. G2 is new — flex-auth declares no emission guarantee where §11 requires one of every §4 source of evidence. It is recorded as a gap rather than as conformance because the flattering reading, that audit-core is the source and flex-auth merely produces, has been asserted by nobody but flex-auth. Also corrects the stance register from two rows to five. Fixing one line meant reading what the declaration asserts, and a boundary is only half held here. docs/conformance/boundaries-review.md checks the other halves across twelve counterparts and finds four security-relevant repositories with no layer declaration at all — including key-cape, the identity source whose claims flex-auth consumes as normative input. That boundary is asserted from one side only. Recorded as unstated, never as agreed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 28468@bnt-lap001 Assistant-Session: c76569b2-6056-4dad-aea4-49cd7a018f5d
2026-09-21 00:11:56 +02:00
// 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)
}
}
}
Make the layer declaration a boundary, and review the boundaries it implies. INTENT.md pinned standard_version: "0.7" in the frontmatter §11 requires. That conflated two things the standard separates itself: assent "records assent to a BOUNDARY, given at the version named. It is not assent to the current text." flex-auth is Engine/PDP at v0.6, v0.7, v0.8 and after; the role does not change when the text is amended. The field was also decorative — parsed into Declaration.StandardVersion and never validated — so the version was load-bearing only via a test asserting it equalled 0.7. That test is inverted rather than deleted: internal/layer now rejects a version pin in the declaration and requires conformance_record to name a file that exists. Version-scoped state moves to docs/conformance/security-layer-conformance.md, a derived artifact carrying what it derives from and the version derived at, as §11 requires of derived artifacts. SCOPE.md: gap assessment replaces "conforming with one declared gap" with three gaps, each with an owner and a route. G2 is new — flex-auth declares no emission guarantee where §11 requires one of every §4 source of evidence. It is recorded as a gap rather than as conformance because the flattering reading, that audit-core is the source and flex-auth merely produces, has been asserted by nobody but flex-auth. Also corrects the stance register from two rows to five. Fixing one line meant reading what the declaration asserts, and a boundary is only half held here. docs/conformance/boundaries-review.md checks the other halves across twelve counterparts and finds four security-relevant repositories with no layer declaration at all — including key-cape, the identity source whose claims flex-auth consumes as normative input. That boundary is asserted from one side only. Recorded as unstated, never as agreed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 28468@bnt-lap001 Assistant-Session: c76569b2-6056-4dad-aea4-49cd7a018f5d
2026-09-21 00:11:56 +02:00
}
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), "..", ".."))
}