Detach captured backend and profile values

This commit is contained in:
2026-11-05 20:07:55 +00:00
parent 6c015a17fa
commit 88725e79ab
6 changed files with 29 additions and 42 deletions

View File

@@ -300,6 +300,12 @@ passed.
## Stage 11: Detach Captured Backend And Profile Values Without Revalidation ## Stage 11: Detach Captured Backend And Profile Values Without Revalidation
**Completed:** Backend registry construction and lookups, and captured profile
lookups, use trusted detached copies while configured acceptance and overlay
validation remain intact. Go 1.27.3 `go test ./internal/backend
./internal/configuration ./internal/domain` passed, including ownership,
composition, presence, and construction-error coverage.
**Finding:** 5; preserve 8. **Files:** `internal/domain/smoke_diagnostics.go`, **Finding:** 5; preserve 8. **Files:** `internal/domain/smoke_diagnostics.go`,
`internal/backend/registry.go`, `internal/configuration/targets.go`, associated tests. `internal/backend/registry.go`, `internal/configuration/targets.go`, associated tests.

View File

@@ -27,17 +27,13 @@ type Registry struct {
// NewEffectiveRegistry stores already-validated effective backend definitions // NewEffectiveRegistry stores already-validated effective backend definitions
// under their exact configuration keys. Configuration validation and // under their exact configuration keys. Configuration validation and
// normalization precede this ownership boundary. // normalization precede this ownership boundary.
func NewEffectiveRegistry(definitions map[string]domain.Backend) (*Registry, error) { func NewEffectiveRegistry(definitions map[string]domain.Backend) *Registry {
registry := &Registry{backends: make(map[string]domain.Backend, len(definitions))} registry := &Registry{backends: make(map[string]domain.Backend, len(definitions))}
for id, definition := range definitions { for id, definition := range definitions {
definition.ID = id definition.ID = id
cloned, err := domain.CloneBackend(definition) registry.backends[id] = domain.CloneBackend(definition)
if err != nil {
return nil, fmt.Errorf("backend %q: %w", id, err)
}
registry.backends[id] = cloned
} }
return registry, nil return registry
} }
// GetBackend returns a defensive copy of the backend registered with id. // GetBackend returns a defensive copy of the backend registered with id.
@@ -49,11 +45,7 @@ func (r *Registry) GetBackend(id string) (domain.Backend, error) {
if !ok { if !ok {
return domain.Backend{}, fmt.Errorf("%w: %q", ErrBackendNotFound, id) return domain.Backend{}, fmt.Errorf("%w: %q", ErrBackendNotFound, id)
} }
cloned, err := domain.CloneBackend(definition) return domain.CloneBackend(definition), nil
if err != nil {
return domain.Backend{}, fmt.Errorf("copy backend %q: %w", id, err)
}
return cloned, nil
} }
// CapacityPolicies returns a copy of the normalized policies for limited // CapacityPolicies returns a copy of the normalized policies for limited

View File

@@ -22,16 +22,13 @@ func TestEffectiveRegistryOwnsDefinitionsAndCapacityPolicies(t *testing.T) {
Kind: &authenticationKind, Endpoint: &authenticationEndpoint, Kind: &authenticationKind, Endpoint: &authenticationEndpoint,
}, },
} }
registry, err := backend.NewEffectiveRegistry(map[string]domain.Backend{ registry := backend.NewEffectiveRegistry(map[string]domain.Backend{
" local.v1 ": { " local.v1 ": {
Endpoint: "https://backend.example/v1", ExtraParams: params, Endpoint: "https://backend.example/v1", ExtraParams: params,
ConcurrencyLimit: 2, QueueCapacity: 3, ConcurrencyLimit: 2, QueueCapacity: 3,
SmokeTests: smokeTests, SmokeTests: smokeTests,
}, },
}) })
if err != nil {
t.Fatal(err)
}
params["nested"].(map[string]any)["enabled"] = false params["nested"].(map[string]any)["enabled"] = false
defaultProfile = "mutated-profile" defaultProfile = "mutated-profile"
reachabilityEndpoint = "https://mutated.example/ready" reachabilityEndpoint = "https://mutated.example/ready"
@@ -79,10 +76,7 @@ func TestEffectiveRegistryOwnsDefinitionsAndCapacityPolicies(t *testing.T) {
} }
func TestEffectiveRegistryMissingBackend(t *testing.T) { func TestEffectiveRegistryMissingBackend(t *testing.T) {
registry, err := backend.NewEffectiveRegistry(nil) registry := backend.NewEffectiveRegistry(nil)
if err != nil {
t.Fatal(err)
}
if _, err := registry.GetBackend("missing"); !errors.Is(err, backend.ErrBackendNotFound) { if _, err := registry.GetBackend("missing"); !errors.Is(err, backend.ErrBackendNotFound) {
t.Fatalf("missing backend error = %v", err) t.Fatalf("missing backend error = %v", err)
} }

View File

@@ -19,15 +19,11 @@ func (state *loaded) buildExecutionProfiles() error {
config := backendConfigs[id] config := backendConfigs[id]
definitions[id] = captureBackend(id, config) definitions[id] = captureBackend(id, config)
} }
registry, err := backend.NewEffectiveRegistry(definitions) state.registry = backend.NewEffectiveRegistry(definitions)
if err != nil {
return err
}
state.registry = registry
state.indexedProfiles = make(map[string]domain.ExecutionProfile, len(profileConfigs)) state.indexedProfiles = make(map[string]domain.ExecutionProfile, len(profileConfigs))
for _, id := range sortedKeys(profileConfigs) { for _, id := range sortedKeys(profileConfigs) {
config := profileConfigs[id] config := profileConfigs[id]
profile, err := captureExecutionProfile(id, config, state.profiles[id], registry) profile, err := captureExecutionProfile(id, config, state.profiles[id], state.registry)
if err != nil { if err != nil {
return err return err
} }
@@ -199,11 +195,7 @@ func (state *loaded) GetProfile(ctx context.Context, id string) (*domain.Executi
return nil, err return nil, err
} }
target := *profile.ResolvedTarget target := *profile.ResolvedTarget
params, err := jsonvalue.CopyMap(target.ExtraParams) target.ExtraParams = jsonvalue.CloneTrusted(target.ExtraParams).(map[string]any)
if err != nil {
return nil, err
}
target.ExtraParams = params
profile.ResolvedTarget = &target profile.ResolvedTarget = &target
return &profile, nil return &profile, nil
} }

View File

@@ -122,15 +122,11 @@ const (
) )
// CloneBackend returns a copy of a backend, including its mutable settings. // CloneBackend returns a copy of a backend, including its mutable settings.
func CloneBackend(backend Backend) (Backend, error) { func CloneBackend(backend Backend) Backend {
cloned := backend cloned := backend
var err error cloned.ExtraParams = jsonvalue.CloneTrusted(backend.ExtraParams).(map[string]any)
cloned.ExtraParams, err = jsonvalue.CopyMap(backend.ExtraParams)
if err != nil {
return Backend{}, err
}
cloned.SmokeTests = CloneBackendSmokeTestConfig(backend.SmokeTests) cloned.SmokeTests = CloneBackendSmokeTestConfig(backend.SmokeTests)
return cloned, nil return cloned
} }
// CloneBackendSmokeTestConfig returns an independent copy of optional metadata. // CloneBackendSmokeTestConfig returns an independent copy of optional metadata.

View File

@@ -19,10 +19,7 @@ func TestCloneBackendCopiesDiagnosticMetadataAndProviderValues(t *testing.T) {
}, },
} }
cloned, err := CloneBackend(backend) cloned := CloneBackend(backend)
if err != nil {
t.Fatal(err)
}
*cloned.SmokeTests.DefaultProfile = "changed" *cloned.SmokeTests.DefaultProfile = "changed"
*cloned.SmokeTests.Reachability.Endpoint = "changed" *cloned.SmokeTests.Reachability.Endpoint = "changed"
*cloned.SmokeTests.Authentication.Kind = "changed" *cloned.SmokeTests.Authentication.Kind = "changed"
@@ -37,3 +34,13 @@ func TestCloneBackendCopiesDiagnosticMetadataAndProviderValues(t *testing.T) {
t.Fatalf("source provider parameter changed through clone: %v", got) t.Fatalf("source provider parameter changed through clone: %v", got)
} }
} }
func TestCloneBackendPreservesProviderMapPresence(t *testing.T) {
if cloned := CloneBackend(Backend{}); cloned.ExtraParams != nil {
t.Fatalf("nil provider map became %#v", cloned.ExtraParams)
}
cloned := CloneBackend(Backend{ExtraParams: map[string]any{"empty": map[string]any{}, "null": nil}})
if cloned.ExtraParams == nil || cloned.ExtraParams["empty"].(map[string]any) == nil || cloned.ExtraParams["null"] != nil {
t.Fatalf("provider map presence changed: %#v", cloned.ExtraParams)
}
}