package engine import ( "bytes" "fmt" "reflect" "strings" "testing" "testing/fstest" ) func TestLayeredDestinationInheritanceUsesFinalSiblingScopes(t *testing.T) { t.Parallel() loaded, err := LoadLayered( Input{Source: Bytes("main", []byte("parent:\n label: final\n settings:\n primary: {height: 4}\ncancelled:\n extends: null\n own: retained\n")), Destination: Keys("catalog", "entries")}, testSecretBinding(), LayeredOptions[map[string]any]{Underlays: []Underlay{{Inputs: []Input{ {Source: Bytes("parent", []byte("parent:\n label: lower\n settings:\n primary: {width: '10'}\n secondary: {extends: primary}\ncancelled:\n extends: parent\n own: retained\n")), Destination: Keys("catalog", "entries")}, {Source: Bytes("child", []byte("child:\n extends: parent\n settings:\n primary: {width: '20'}\n secondary: {extends: primary}\n")), Destination: Keys("catalog", "entries")}, }}}}, ) if err != nil { t.Fatalf("LoadLayered: %v", err) } result := testLoaded(loaded) entries := layeredMap(t, layeredMap(t, result.Config, "catalog"), "entries") parent := layeredMap(t, entries, "parent") child := layeredMap(t, entries, "child") parentSettings := layeredMap(t, parent, "settings") childSettings := layeredMap(t, child, "settings") if parent["label"] != "final" || child["label"] != "final" { t.Fatalf("higher-tier parent was not inherited after precedence: parent=%#v child=%#v", parent, child) } if layeredMapValue(t, parentSettings, "secondary", "width") != "10" || fmt.Sprint(layeredMapValue(t, parentSettings, "secondary", "height")) != "4" || layeredMapValue(t, childSettings, "secondary", "width") != "20" || fmt.Sprint(layeredMapValue(t, childSettings, "secondary", "height")) != "4" { t.Fatalf("nested sibling scopes were not resolved at their destinations: parent=%#v child=%#v", parentSettings, childSettings) } cancelled := layeredMap(t, entries, "cancelled") if len(cancelled) != 1 || cancelled["own"] != "retained" { t.Fatalf("higher-tier cancellation did not suppress inheritance: %#v", cancelled) } if _, ok := result.Metadata().Lookup(Keys("catalog", "entries", "child", inheritanceKey)); ok { t.Fatal("effective child retained its extends directive") } } func TestLayeredDestinationInheritanceDoesNotSearchOtherCollections(t *testing.T) { t.Parallel() _, err := LoadLayered( Input{Source: Bytes("main", []byte("parent: {value: foreign}\n")), Destination: Keys("catalog", "other")}, testSecretBinding(), LayeredOptions[map[string]any]{Underlays: []Underlay{{Inputs: []Input{{ Source: Bytes("child", []byte("child: {extends: parent}\n")), Destination: Keys("catalog", "entries"), }}}}}, ) if got := groupedErrorCode(t, err); got != CodeInheritanceMissing { t.Fatalf("cross-collection parent lookup error = %s, want %s", got, CodeInheritanceMissing) } } func TestLayeredMountedVersionProtectionCoversInheritanceAndUpperTiers(t *testing.T) { t.Parallel() for _, test := range []struct { name string body string rulePath Path }{ {name: "inherited protected value", body: "parent: {version: v2}\nchild: {extends: parent}\n", rulePath: Keys("catalog", "entries", "child", "version")}, {name: "inherited protected ancestor", body: "parent: {schema: null}\nchild: {extends: parent}\n", rulePath: Keys("catalog", "entries", "child", "schema", "version")}, } { t.Run(test.name, func(t *testing.T) { t.Parallel() _, err := LoadLayered( Input{Source: NoSource()}, testSecretBinding(), LayeredOptions[map[string]any]{ Definition: Definition[map[string]any]{Version: &VersionRule{Path: test.rulePath, Check: func(Version, *Validation) error { return nil }}}, Underlays: []Underlay{{Inputs: []Input{{Source: Bytes("underlay", []byte(test.body)), Destination: Keys("catalog", "entries")}}}}, }, ) if got := groupedErrorCode(t, err); got != CodeInheritanceVersion { t.Fatalf("inheritance version protection code = %s", got) } }) } t.Run("inheritance consumes a protected directive", func(t *testing.T) { _, err := LoadLayered( Input{Source: Bytes("main", []byte("parent: {value: inherited}\nchild: {extends: parent}\n")), Destination: Keys("catalog", "entries")}, testSecretBinding(), LayeredOptions[map[string]any]{Definition: Definition[map[string]any]{Version: &VersionRule{ Path: Keys("catalog", "entries", "child", "extends"), Check: func(version Version, _ *Validation) error { if !version.Present || version.Text != "parent" { t.Errorf("mounted protected directive value = %#v", version) } return nil }, }}}, ) if got := groupedErrorCode(t, err); got != CodeInheritanceVersion { t.Fatalf("consumed directive protection code = %s", got) } }) t.Run("inherited mapping ancestor without a version claim", func(t *testing.T) { loaded, err := LoadLayered( Input{Source: NoSource()}, testSecretBinding(), LayeredOptions[map[string]any]{ Definition: Definition[map[string]any]{Version: &VersionRule{Path: Keys("catalog", "entries", "child", "schema", "version"), Check: func(Version, *Validation) error { return nil }}}, Underlays: []Underlay{{Inputs: []Input{{ Source: Bytes("underlay", []byte("parent: {schema: {name: ordinary}}\nchild: {extends: parent}\n")), Destination: Keys("catalog", "entries"), }}}}, }, ) if err != nil { t.Fatalf("nonclaiming inherited mapping ancestor was rejected: %v", err) } if got := layeredMapValue(t, testLoaded(loaded).Config, "catalog", "entries", "child", "schema", "name"); got != "ordinary" { t.Fatalf("inherited non-version value = %#v", got) } }) for _, test := range []struct { name string body string }{ {name: "overlay protected value", body: "catalog: {schema: {version: v2}}\n"}, {name: "overlay protected ancestor", body: "catalog: {schema: null}\n"}, } { t.Run(test.name, func(t *testing.T) { t.Parallel() filesystem := NewFilesystem("overlay", fstest.MapFS{"overlays/test.yml": &fstest.MapFile{Data: []byte(test.body)}}) _, err := LoadLayered( Input{Source: Bytes("main", []byte("schema: {version: v1}\n")), Destination: Keys("catalog")}, testSecretBinding(), LayeredOptions[map[string]any]{ Definition: Definition[map[string]any]{Version: &VersionRule{Path: Keys("catalog", "schema", "version"), Check: func(version Version, _ *Validation) error { if !version.Present || version.Text != "v1" { t.Errorf("mounted main version = %#v", version) } return nil }}}, Overlay: "test", OverlayFilesystem: &FilesystemContext{Root: ".", BaseDir: ".", FS: &filesystem}, }, ) if got := groupedErrorCode(t, err); got != CodeOverlayVersion { t.Fatalf("overlay version protection code = %s", got) } }) } for _, test := range []struct { name string path Path value any }{ {name: "override protected value", path: Keys("catalog", "schema", "version"), value: "v2"}, {name: "override protected ancestor", path: Keys("catalog", "schema"), value: map[string]any{"version": "v2"}}, } { t.Run(test.name, func(t *testing.T) { t.Parallel() _, err := LoadLayered( Input{Source: Bytes("main", []byte("schema: {version: v1}\n")), Destination: Keys("catalog")}, testSecretBinding(), LayeredOptions[map[string]any]{ Definition: Definition[map[string]any]{Version: &VersionRule{Path: Keys("catalog", "schema", "version"), Check: func(Version, *Validation) error { return nil }}}, Overrides: []Override{{Path: test.path, Value: test.value, Flag: "--config"}}, }, ) if got := groupedErrorCode(t, err); got != CodeOverrideVersion { t.Fatalf("override version protection code = %s", got) } }) } t.Run("unrelated inheritance under the protected mapping ancestor", func(t *testing.T) { loaded, err := LoadLayered( Input{Source: Bytes("main", []byte("schema: {version: v1}\nentries:\n parent: {value: inherited}\n child: {extends: parent}\n")), Destination: Keys("catalog")}, testSecretBinding(), LayeredOptions[map[string]any]{Definition: Definition[map[string]any]{Version: &VersionRule{Path: Keys("catalog", "schema", "version"), Check: func(Version, *Validation) error { return nil }}}}, ) if err != nil { t.Fatalf("unrelated mounted inheritance was rejected: %v", err) } child := layeredMapValue(t, testLoaded(loaded).Config, "catalog", "entries", "child", "value") if child != "inherited" { t.Fatalf("unrelated inheritance value = %#v", child) } }) } func TestLayeredItemVersionProtectionTracksAssignedPeerIndexes(t *testing.T) { t.Parallel() definition := Definition[map[string]any]{ Version: &VersionRule{Path: Keys("schema", "version"), Check: func(Version, *Validation) error { return nil }}, sequenceIdentityRegistrations: []sequenceIdentityRegistration{{selector: sequenceIdentitySelector{literalSequenceSelector("catalog"), literalSequenceSelector("entries")}, identityFields: []string{"id"}}}, } item := func(label string, value map[string]any) Input { return Input{Source: Mapping(label, value), Destination: Keys("catalog", "entries"), PlacementMode: PlacementModeSequenceItem} } options := func(inputs ...Input) LayeredOptions[map[string]any] { return LayeredOptions[map[string]any]{Definition: definition, SourceVersionMode: sourceVersionModeIfPresent, Underlays: []Underlay{{Inputs: inputs}}} } main := item("main", map[string]any{"id": "main", "schema": map[string]any{"version": "v1"}}) t.Run("same assigned main path is protected", func(t *testing.T) { _, err := LoadLayered(main, testSecretBinding(), options(item("underlay", map[string]any{"id": "main", "schema": nil}))) if got := groupedErrorCode(t, err); got != CodeUnderlayVersion { t.Fatalf("protected item claim code = %s, want %s", got, CodeUnderlayVersion) } }) t.Run("appended peer does not claim main path", func(t *testing.T) { loaded, err := LoadLayered(main, testSecretBinding(), options( item("first", map[string]any{"id": "first", "schema": map[string]any{"other": "value"}}), item("peer", map[string]any{"id": "peer", "schema": nil}), )) if err != nil { t.Fatalf("unrelated appended peer rejected: %v", err) } entries := layeredMapValue(t, testLoaded(loaded).Config, "catalog", "entries").([]any) if len(entries) != 3 || entries[0].(map[string]any)["id"] != "first" || entries[1].(map[string]any)["id"] != "peer" || entries[2].(map[string]any)["id"] != "main" { t.Fatalf("main item projection = %#v", entries) } }) } type destinationDecodeProbe string var destinationDecodeProbeValues []string func (value *destinationDecodeProbe) UnmarshalText(text []byte) error { destinationDecodeProbeValues = append(destinationDecodeProbeValues, string(text)) *value = destinationDecodeProbe(text) return nil } func (value destinationDecodeProbe) MarshalText() ([]byte, error) { return []byte(value), nil } type destinationLifecycleConfig struct { Defaulted string `yaml:"defaulted"` Tenant struct { Tagged string `yaml:"tagged" configkit:"secret"` Dynamic string `yaml:"dynamic"` Credential Secret `yaml:"credential"` Derived string `yaml:"derived"` Decoded destinationDecodeProbe `yaml:"decoded"` } `yaml:"tenant"` } func TestLayeredDestinationLifecycleAndSensitiveInspectionUseFinalShape(t *testing.T) { const ( oldTagged = "SUPERSEDED-TAGGED-CANARY" newTagged = "CURRENT-TAGGED-CANARY" oldDynamic = "SUPERSEDED-DYNAMIC-CANARY" newDynamic = "CURRENT-DYNAMIC-CANARY" credential = "RESOLVED-CREDENTIAL-CANARY" secretName = "DESTINATION_SECRET_NAME" decodeValue = "decoded-once" ) type calls struct{ defaults, resolve, lookup, validate int } newLoad := func(mounted bool, observed *calls) (*testResult[destinationLifecycleConfig], error) { mainBody := "tagged: " + newTagged + "\ndynamic: " + newDynamic + "\ncredential: " + secretName + "\ndecoded: " + decodeValue + "\n" underlayBody := "tagged: " + oldTagged + "\ndynamic: " + oldDynamic + "\ncredential: OLD_DESTINATION_SECRET_NAME\ndecoded: old\n" if !mounted { mainBody = "tenant:\n" + indentDestinationBody(mainBody) underlayBody = "tenant:\n" + indentDestinationBody(underlayBody) } main := loadInput{source: Bytes("main", []byte(mainBody))} underlay := loadInput{source: Bytes("underlay", []byte(underlayBody))} if mounted { main.destination = Keys("tenant") underlay.destination = Keys("tenant") } definition := Definition[destinationLifecycleConfig]{ Defaults: func() destinationLifecycleConfig { observed.defaults++ return destinationLifecycleConfig{Defaulted: "from-default"} }, Resolve: func(configuration *destinationLifecycleConfig, resolution *Resolution) error { observed.resolve++ configuration.Tenant.Derived = configuration.Tenant.Dynamic resolution.Record(Keys("tenant", "derived"), ChangeNormalization, "derive from mounted input", Keys("tenant", "dynamic")) return nil }, Validate: func(configuration *destinationLifecycleConfig, _ *Validation) { observed.validate++ if configuration.Tenant.Decoded != destinationDecodeProbe(decodeValue) || configuration.Tenant.Dynamic != newDynamic { t.Errorf("validation saw a non-final mounted configuration: %#v", configuration.Tenant) } }, Secret: func(path Path) bool { return path.String() == "/tenant/dynamic" }, } loaded, err := loadGroupedWithSecretLookup(loadRequest[destinationLifecycleConfig]{ main: main, underlays: []loadGroup{{inputs: []loadInput{underlay}}}, definition: definition, }, testSecretBinding(), func(name string) (string, bool) { observed.lookup++ if name != secretName { return "", false } return credential, true }) return testLoaded(loaded), err } var observed calls destinationDecodeProbeValues = nil mounted, err := newLoad(true, &observed) if err != nil { if loadError, ok := err.(*LoadError); ok { t.Fatalf("mounted load: %#v", loadError.Diagnostics()) } t.Fatalf("mounted load: %v", err) } if observed != (calls{defaults: 1, resolve: 1, lookup: 1, validate: 1}) { t.Fatalf("mounted lifecycle counts = %#v", observed) } sawFinalDecode := false for _, value := range destinationDecodeProbeValues { if value == decodeValue { sawFinalDecode = true } else if value != "" { t.Fatalf("decoder observed a non-final mounted value %q: %#v", value, destinationDecodeProbeValues) } } if !sawFinalDecode { t.Fatal("final mounted value was not decoded") } if mounted.Config.Defaulted != "from-default" || mounted.Config.Tenant.Tagged != newTagged || mounted.Config.Tenant.Dynamic != newDynamic || mounted.Config.Tenant.Derived != newDynamic || mounted.Config.Tenant.Decoded != destinationDecodeProbe(decodeValue) || mounted.Config.Tenant.Credential.Value() != credential { t.Fatalf("mounted final configuration = %#v", mounted.Config) } for _, path := range []Path{Keys("tenant", "tagged"), Keys("tenant", "dynamic"), Keys("tenant", "derived")} { if !mounted.Inspection.secrets[path.String()] { t.Errorf("effective sensitivity missing at %s: %#v", path, mounted.Inspection.secrets) } } for _, path := range []Path{Keys("tenant", "tagged"), Keys("tenant", "dynamic"), Keys("tenant", "derived")} { explanation, ok := mounted.Explain(path) if !ok || !explanation.Effective.Redacted { t.Errorf("effective explanation at %s = %#v, %v", path, explanation, ok) continue } for _, change := range explanation.History { if strings.Contains(change.Before.YAML+change.After.YAML, oldTagged) || strings.Contains(change.Before.YAML+change.After.YAML, newTagged) || strings.Contains(change.Before.YAML+change.After.YAML, oldDynamic) || strings.Contains(change.Before.YAML+change.After.YAML, newDynamic) { t.Errorf("classified history leaked a canary at %s: %#v", path, change) } } var rendered bytes.Buffer if err := mounted.WriteExplanation(&rendered, path); err != nil || strings.Contains(rendered.String(), "CANARY") { t.Errorf("safe explanation at %s = %q, %v", path, rendered.String(), err) } } var effective bytes.Buffer if err := mounted.WriteEffective(&effective); err != nil { t.Fatal(err) } for _, canary := range []string{oldTagged, newTagged, oldDynamic, newDynamic, credential} { if strings.Contains(effective.String(), canary) { t.Fatalf("effective rendering exposed %q: %s", canary, effective.String()) } } if serializedConfig := fmt.Sprintf("%#v", mounted.Config); strings.Contains(serializedConfig, credential) { t.Fatalf("configuration formatting exposed the resolved credential: %s", serializedConfig) } for _, path := range []Path{Keys("tenant", "tagged"), Keys("tenant", "dynamic")} { if history := fmt.Sprintf("%#v", mounted.Metadata().History(path)); strings.Contains(history, "CANARY") { t.Fatalf("metadata history at %s exposed a canary: %s", path, history) } } var authoredCalls calls destinationDecodeProbeValues = nil authored, err := newLoad(false, &authoredCalls) if err != nil { t.Fatalf("explicitly wrapped load: %v", err) } if authoredCalls != (calls{defaults: 1, resolve: 1, lookup: 1, validate: 1}) { t.Fatalf("authored lifecycle counts = %#v", authoredCalls) } sawFinalDecode = false for _, value := range destinationDecodeProbeValues { if value == decodeValue { sawFinalDecode = true } else if value != "" { t.Fatalf("authored decoder observed a non-final value %q: %#v", value, destinationDecodeProbeValues) } } if !sawFinalDecode { t.Fatal("final authored value was not decoded") } if !reflect.DeepEqual(mounted.Config, authored.Config) { t.Fatalf("mounted config %#v differs from explicitly wrapped config %#v", mounted.Config, authored.Config) } differences, err := Diff(mounted.Inspection, authored.Inspection) if err != nil || len(differences) != 0 { t.Fatalf("mounted versus authored diff = %#v, %v", differences, err) } } func TestLayeredDestinationDiffUsesBilateralSensitivity(t *testing.T) { t.Parallel() type config struct { Tenant struct { Dynamic string `yaml:"dynamic"` Derived string `yaml:"derived"` } `yaml:"tenant"` } load := func(value string, classify bool) *testResult[config] { t.Helper() loaded, err := loadGroupedWithSecretLookup(loadRequest[config]{ main: loadInput{source: Bytes("input", []byte("dynamic: "+value+"\n")), destination: Keys("tenant")}, definition: Definition[config]{ Resolve: func(configuration *config, resolution *Resolution) error { configuration.Tenant.Derived = configuration.Tenant.Dynamic resolution.Record(Keys("tenant", "derived"), ChangeNormalization, "derive from dynamic input", Keys("tenant", "dynamic")) return nil }, Secret: func(path Path) bool { return classify && path.String() == "/tenant/dynamic" }, }, }, testSecretBinding(), func(string) (string, bool) { return "", false }) if err != nil { t.Fatalf("LoadLayered: %v", err) } return testLoaded(loaded) } left := load("LEFT-DIFF-CANARY", true) right := load("RIGHT-DIFF-CANARY", false) differences, err := Diff(left.Inspection, right.Inspection) if err != nil { t.Fatal(err) } if len(differences) != 2 { t.Fatalf("differences = %#v", differences) } seen := make(map[string]bool) for _, difference := range differences { path := difference.Path.String() seen[path] = true if !difference.Left.Redacted || !difference.Right.Redacted || !difference.HiddenChanged || strings.Contains(difference.Left.YAML+difference.Right.YAML, "DIFF-CANARY") { t.Errorf("bilaterally classified difference at %s = %#v", path, difference) } } for _, path := range []string{"/tenant/dynamic", "/tenant/derived"} { if !seen[path] || !left.Inspection.secrets[path] || right.Inspection.secrets[path] { t.Errorf("classification/difference at %s: seen=%v left=%v right=%v", path, seen[path], left.Inspection.secrets[path], right.Inspection.secrets[path]) } } } func TestLayeredDestinationDecodeFailureReturnsNoResultOrLaterCallbacks(t *testing.T) { t.Parallel() type config struct { Tenant struct { Count int `yaml:"count"` } `yaml:"tenant"` } calls := struct{ defaults, resolve, lookup, validate int }{} loaded, err := loadGroupedWithSecretLookup(loadRequest[config]{ main: loadInput{source: Bytes("invalid", []byte("count: not-an-integer\n")), destination: Keys("tenant")}, definition: Definition[config]{ Defaults: func() config { calls.defaults++; return config{} }, Resolve: func(*config, *Resolution) error { calls.resolve++; return nil }, Validate: func(*config, *Validation) { calls.validate++ }, }, }, testSecretBinding(), func(string) (string, bool) { calls.lookup++; return "", false }) if loaded != nil || err == nil { t.Fatalf("mounted decode failure returned a usable result: %#v, %v", loaded, err) } if calls.defaults != 1 || calls.resolve != 0 || calls.lookup != 0 || calls.validate != 0 { t.Fatalf("callbacks after mounted decode failure = %#v", calls) } if got := groupedErrorCode(t, err); got != CodeDecodeType { t.Fatalf("mounted decode failure code = %s", got) } } func indentDestinationBody(body string) string { var result strings.Builder for _, line := range strings.Split(strings.TrimSuffix(body, "\n"), "\n") { result.WriteString(" ") result.WriteString(line) result.WriteByte('\n') } return result.String() }