Test normalized configuration inspection and provenance

This commit is contained in:
2026-11-03 03:31:37 +00:00
parent 9f33fed823
commit 43abbcb414
6 changed files with 116 additions and 2 deletions

View File

@@ -81,6 +81,34 @@ func TestConfigurationInspectionDiffIgnoresSourceHistory(t *testing.T) {
}
}
func TestConfigurationInspectionDiffUsesNormalizedValues(t *testing.T) {
inspect := func(endpoint string) promptkit.ConfigurationInspection {
t.Helper()
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Underlays: []configkit.Underlay{{Inputs: []configkit.Input{{Source: configkit.Mapping("backend", map[string]any{
"backends": []any{map[string]any{"id": "local", "endpoint": endpoint}},
})}}}}}})
if err != nil {
t.Fatal(err)
}
view, err := engine.InspectConfiguration()
if err != nil {
t.Fatal(err)
}
return view
}
left := inspect(" HTTPS://example.invalid/v1 ")
equal := inspect("https://example.invalid/v1")
differences, err := left.Diff(equal)
if err != nil || len(differences) != 0 {
t.Fatalf("normalized diff = %+v, %v", differences, err)
}
changed := inspect("https://other.invalid/v1")
differences, err = left.Diff(changed)
if err != nil || len(differences) != 1 || differences[0].Path.String() != "/backends" {
t.Fatalf("changed diff = %+v, %v", differences, err)
}
}
func TestConfigurationInspectionDiffReportsPresenceAndSequences(t *testing.T) {
left := comparisonInspectionFrom(t, "before", "same-model", map[string]any{
"sequence": []any{"earlier", "unchanged"},

View File

@@ -21,7 +21,7 @@ func TestConfigurationInspectionReportsLiteralKeysAndRedactedHistory(t *testing.
Underlays: []configkit.Underlay{
{Inputs: []configkit.Input{{Source: configkit.Mapping("defaults", map[string]any{
"backends": []any{map[string]any{
"id": "local", "endpoint": "https://example.invalid/v1", "api_key_env": "OPTIONAL_KEY",
"id": "local", "endpoint": " HTTPS://example.invalid/v1 ", "api_key_env": "OPTIONAL_KEY",
"extra_params": map[string]any{"token": "private-sentinel", "visible": "public-value"},
}},
"collections": map[string]any{"literal": map[string]any{
@@ -64,6 +64,11 @@ func TestConfigurationInspectionReportsLiteralKeysAndRedactedHistory(t *testing.
t.Fatalf("literal-key path = %q", inheritedPath)
}
secretPath := configkit.Keys("backends").Index(0).Key("extra_params").Key("token")
endpointPath := configkit.Keys("backends").Index(0).Key("endpoint")
endpoint, found := view.Explain(endpointPath)
if !found || !strings.Contains(endpoint.Effective.YAML, "https://example.invalid/v1") || strings.Contains(fmt.Sprintf("%+v", view.Metadata().History(endpointPath)), "private-sentinel") {
t.Fatalf("normalized endpoint explanation = %+v", endpoint)
}
secret, found := view.Explain(secretPath)
if !found || !secret.Effective.Redacted || strings.Contains(secret.Effective.YAML, "private-sentinel") {
t.Fatalf("credential-shaped provider value was not redacted: (%+v, %t)", secret, found)

View File

@@ -221,6 +221,10 @@ Scope: focused configuration tests and existing public inspection/diff tests.
Validation: focused configuration, public inspection/diff, preparation, and
execution tests. All new tests use deterministic offline sources/collaborators.
Completion: focused tests cover recorded target dependencies, imported content
origins, invalid identities, normalized-value diffs, and sensitive inspection.
Configuration, engine, and public API tests pass on Go 1.27.0.
## Stage 6: Align Documentation And Verify The Sprint
Scope: current contract/implementation documentation and final integration.

View File

@@ -117,3 +117,36 @@ func TestPromptResolutionRecordsMessageFields(t *testing.T) {
t.Fatal("null input metadata was not retained")
}
}
func TestResolutionRecordsTargetDependencies(t *testing.T) {
backend := func(id string) map[string]any {
return map[string]any{"id": id, "endpoint": " HTTPS://example.invalid/v1 ", "concurrency_limit": 2, "queue_capacity": nil}
}
state, err := load(mapping("targets", map[string]any{
"backends": []any{backend("root")},
"collections": map[string]any{"scoped": map[string]any{"backends": []any{backend("local")}}},
}), nil)
if err != nil {
t.Fatal(err)
}
for _, base := range []configkit.Path{configkit.Keys("backends").Index(0), configkit.Keys("collections", "scoped", "backends").Index(0)} {
endpoint, ok := state.result.Explain(base.Key("endpoint"))
if !ok || !strings.Contains(endpoint.Effective.YAML, "https://example.invalid/v1") {
t.Fatalf("endpoint explanation: %+v", endpoint)
}
history := state.result.Metadata().History(base.Key("queue_capacity"))
found := false
for _, change := range history {
if change.Origin.Operation == configkit.ChangeDerivedDefault {
for _, dependency := range change.Dependencies {
if dependency.String() == base.Key("concurrency_limit").String() {
found = true
}
}
}
}
if !found {
t.Fatalf("missing queue dependency: %+v", history)
}
}
}

View File

@@ -153,6 +153,50 @@ func TestIdentifiedResourcesRejectDuplicateStrictPeers(t *testing.T) {
}
}
func TestInvalidIdentitiesWithNormalizableFieldsAreRejected(t *testing.T) {
for _, kind := range []string{"backends", "profiles", "prompts"} {
for _, id := range []string{" ", "bad/id"} {
t.Run(kind+"/"+id, func(t *testing.T) {
record := map[string]any{"id": id}
switch kind {
case "backends":
record["endpoint"] = " HTTPS://example.invalid/v1 "
record["concurrency_limit"] = 1
case "profiles":
record["service_tier"] = " standard "
case "prompts":
record["description"] = " padded "
}
_, err := load(mapping("invalid", map[string]any{kind: []any{record}}), nil)
if err == nil || strings.Contains(strings.ToLower(err.Error()), "unrecorded") {
t.Fatalf("invalid identity error = %v", err)
}
})
}
}
}
func TestDuplicateIdentitiesWithNormalizableFieldsAreRejected(t *testing.T) {
for _, kind := range []string{"backends", "profiles", "prompts"} {
t.Run(kind, func(t *testing.T) {
record := map[string]any{"id": "same"}
switch kind {
case "backends":
record["endpoint"] = " HTTPS://example.invalid/v1 "
record["concurrency_limit"] = 1
case "profiles":
record["service_tier"] = " standard "
case "prompts":
record["description"] = " padded "
}
_, err := load(mapping("duplicates", map[string]any{kind: []any{record, record}}), nil)
if err == nil || strings.Contains(strings.ToLower(err.Error()), "unrecorded") {
t.Fatalf("duplicate identity error = %v", err)
}
})
}
}
func TestFinalIdentitiesAreCheckedAfterApplicationResolution(t *testing.T) {
for _, kind := range []string{"backends", "profiles", "prompts"} {
for _, namespace := range []string{"", "*"} {

View File

@@ -16,7 +16,7 @@ import (
func TestLoadCapturesInheritedImportedContent(t *testing.T) {
files := fstest.MapFS{
"app/main.yaml": {Data: []byte("config:\n imports:\n - path: ../catalog/base.yaml\n required: true\ncollections:\n docs:\n prompts:\n - id: child\n extends: {id: base}\n other:\n prompts:\n - id: child\n messages:\n - role: user\n content_file: ./body.md\n output:\n format: text\n validation_mode: none\n")},
"app/main.yaml": {Data: []byte("config:\n imports:\n - path: ../catalog/base.yaml\n required: true\ncollections:\n docs:\n prompts:\n - id: child\n extends: {id: base}\n description: ' description '\n other:\n prompts:\n - id: child\n messages:\n - role: user\n content_file: ./body.md\n output:\n format: text\n validation_mode: none\n")},
"app/body.md": {Data: []byte("Replacement {{.name}}")},
"catalog/base.yaml": {Data: []byte("collections:\n docs:\n release_version: r1\n prompts:\n - id: base\n description: ' description '\n session_id: ' session '\n inputs:\n - name: ' document '\n content_type: ' text/plain '\n description: ' document source '\n messages:\n - role: ' USER '\n cache_control:\n type: ' ephemeral '\n ttl: ' 1h '\n content_file: ./body.md\n output:\n format: text\n validation_mode: basic\n")},
"catalog/body.md": {Data: []byte("Captured {{.name}}")},