package engine import ( "bytes" "reflect" "strings" "testing" ) func TestInheritanceSensitivityFollowsCopiesWithoutMaskingNeighbors(t *testing.T) { const canary = "INHERITED-CANARY-CREDENTIAL" input := parseCompositionDocument(t, "source-1", "parent: {token: "+canary+", plain: visible}\nchild: {extends: parent}\nnext: {extends: child}\nother: {extends: parent}\n") for _, classified := range []Path{Keys("parent", "token"), Keys("next", "token")} { t.Run(classified.String(), func(t *testing.T) { inspection, _ := inheritanceInspectionForTest(t, input) inspection.secrets = classifySecretPaths(nil, func(path Path) bool { return path.String() == classified.String() }, inspection.metadata, inspection.final, inspection.applications, inspection.input) for _, path := range []Path{Keys("parent", "token"), Keys("child", "token"), Keys("next", "token"), Keys("other", "token")} { explanation, found := inspection.Explain(path) if !found || !explanation.Effective.Redacted || strings.Contains(explanation.Effective.YAML, canary) { t.Fatalf("sensitive copy %s = %#v, %v", path, explanation, found) } for _, change := range explanation.History { if strings.Contains(change.Before.YAML, canary) || strings.Contains(change.After.YAML, canary) { t.Fatalf("historical canary at %s: %#v", path, change) } } } plain, found := inspection.Explain(Keys("other", "plain")) if !found || plain.Effective.Redacted || plain.Effective.YAML != "visible\n" { t.Fatalf("unrelated field = %#v, %v", plain, found) } var output bytes.Buffer if err := inspection.WriteEffective(&output); err != nil || strings.Contains(output.String(), canary) || !strings.Contains(output.String(), "visible") { t.Fatalf("effective rendering = %q, %v", output.String(), err) } }) } } func TestInheritanceSensitivityPreservesDisplacedHistoryAndControl(t *testing.T) { const canary = "DISPLACED-CANARY-CREDENTIAL" inspection, _ := inheritanceInspectionForTest(t, parseCompositionDocument(t, "source-1", "parent: {branch: {token: "+canary+"}}\nchild: {extends: parent, branch: public}\n")) inspection.secrets = classifySecretPaths(nil, func(path Path) bool { return path.String() == Keys("parent", "branch", "token").String() || path.String() == Keys("child", inheritanceKey).String() }, inspection.metadata, inspection.final, inspection.applications, inspection.input) path := Keys("child", "branch", "token") explanation, found := inspection.Explain(path) if !found || explanation.Effective.Present { t.Fatalf("displaced sensitive path = %#v, %v", explanation, found) } for _, change := range explanation.History { if strings.Contains(change.Before.YAML, canary) || strings.Contains(change.After.YAML, canary) || (change.After.Present && !change.After.Redacted) { t.Fatalf("displaced secret leaked: %#v", explanation.History) } } var rendered bytes.Buffer if err := inspection.WriteExplanation(&rendered, path); err != nil || strings.Contains(rendered.String(), canary) { t.Fatalf("displaced explanation rendering = %q, %v", rendered.String(), err) } control, found := inspection.Explain(Keys("child", inheritanceKey)) if !found || control.Effective.Present || len(control.History) == 0 || !control.History[0].After.Redacted { t.Fatalf("sensitive control history = %#v, %v", control, found) } info, found := inspection.Metadata().Lookup(Keys("child", "branch")) if !found || len(info.Origin.Inheritance) != 0 { t.Fatalf("independent replacement provenance = %#v, %v", info, found) } } func TestInheritanceSensitivityIncludesSchemaTaggedSource(t *testing.T) { type entry struct { Token string `yaml:"token"` } type configuration struct { Parent struct { Token string `yaml:"token" configkit:"secret"` } `yaml:"parent"` Child entry `yaml:"child"` } schema, issue := buildSchema(reflect.TypeFor[configuration](), testSecretBinding()) if issue != nil { t.Fatal(issue) } inspection, _ := inheritanceInspectionForTest(t, parseCompositionDocument(t, "source-1", "parent: {token: TAGGED-CANARY}\nchild: {extends: parent}\n")) inspection.secrets = classifySecretPaths(schema, nil, inspection.metadata, inspection.final, inspection.applications, inspection.input) child, found := inspection.Explain(Keys("child", "token")) if !found || !child.Effective.Redacted || strings.Contains(child.Effective.YAML, "TAGGED-CANARY") { t.Fatalf("tagged source copy = %#v, %v", child, found) } } func TestInheritedSecretReferencesResolveOnlyAfterExpansion(t *testing.T) { type entry struct { Credential Secret `yaml:"credential"` } type configuration struct { Entries map[string]entry `yaml:"entries"` } schema, issue := buildSchema(reflect.TypeFor[configuration](), testSecretBinding()) if issue != nil { t.Fatal(issue) } composed, diagnostics := composeDocuments(parseCompositionDocument(t, "source-1", "entries:\n parent: {credential: INHERITED_SECRET_NAME}\n child: {extends: parent}\n")) if len(diagnostics) != 0 { t.Fatal(diagnostics) } expanded, diagnostics := expandInheritanceWithOrigins(composed.root, composed.origins, defaultProjectionLimits()) if len(diagnostics) != 0 { t.Fatal(diagnostics) } lookupCount := 0 decoded, issues := decodeConfiguration(schema, reflect.Zero(reflect.TypeFor[configuration]()), expanded.root) if len(issues) != 0 || lookupCount != 0 { t.Fatalf("decoding and lookup order = %#v, %d", issues, lookupCount) } resolved := resolveSecretReferences(decoded.value, schema, expanded.root, func(name string) (string, bool) { lookupCount++ if name != "INHERITED_SECRET_NAME" { t.Fatalf("inherited reference name = %q", name) } return "RESOLVED-CREDENTIAL-CANARY", true }) if len(resolved.diagnostics) != 0 || lookupCount != 1 || decoded.value.Interface().(configuration).Entries["child"].Credential.Value() != "RESOLVED-CREDENTIAL-CANARY" { t.Fatalf("inherited reference resolution = %#v, %d", resolved.diagnostics, lookupCount) } inspection, _ := inheritanceInspectionFromComposition(t, composed) inspection.secrets = classifySecretPaths(schema, nil, inspection.metadata, inspection.final, inspection.applications, inspection.input) var rendered bytes.Buffer if err := inspection.WriteEffective(&rendered); err != nil || strings.Contains(rendered.String(), "RESOLVED-CREDENTIAL-CANARY") { t.Fatalf("reference rendering = %q, %v", rendered.String(), err) } }