Check import opt-in before processing source headers

This commit is contained in:
2026-10-15 22:18:57 +00:00
parent e5a6df7af7
commit 0a2246bdbe
3 changed files with 47 additions and 4 deletions

View File

@@ -218,7 +218,13 @@ Required remediation:
### 4. Preserve import opt-in before stripping source directives (P2)
Status: open.
Status: complete. Directive opt-in is now checked on the original document
before source-version processing. The shared acquisition boundary covers main
and direct underlay sources. The public regression failed for both enabled
modes and roles before the fix and now verifies `import.disabled`, source-local
attribution, and no partial result. Focused source-version/directive/import
tests and the everyday check passed on `go1.26.9 linux/amd64`; existing enabled
import and selected-overlay tests remain green.
Affected: `assembleBaseInputTrackedForRole` in
[load_input.go](../../internal/engine/load_input.go), lines 54–87, and

View File

@@ -78,6 +78,41 @@ func TestFacadeSourceVersionEvidenceRedactsCollidingShapes(t *testing.T) {
}
}
func TestFacadeSourceVersionModesPreserveImportOptIn(t *testing.T) {
t.Parallel()
for _, mode := range []configkit.SourceVersionMode{configkit.SourceVersionModeIfPresent, configkit.SourceVersionModeRequired} {
for _, underlay := range []bool{false, true} {
bad := configkit.Bytes("disabled-imports", []byte("version: accepted\nconfigkit: {imports: [{path: missing.yml}]}\nvalue: visible\n"))
definition := configkit.Definition[map[string]any]{Version: &configkit.VersionRule{
Path: configkit.Keys("version"), Check: func(configkit.Version, *configkit.Validation) error { return nil },
}}
var err error
var resultPresent bool
wantSource := "source-1"
if underlay {
loaded, loadErr := configkit.LoadLayered(configkit.Input{Source: configkit.Bytes("main", []byte("version: main\n"))}, configkit.LayeredOptions[map[string]any]{
Definition: definition, SourceVersionMode: mode,
Underlays: []configkit.Underlay{{Inputs: []configkit.Input{{Source: bad}}}},
})
err, resultPresent, wantSource = loadErr, loaded != nil, "source-2"
} else {
loaded, loadErr := configkit.Load(bad, configkit.Options[map[string]any]{Definition: definition, SourceVersionMode: mode})
err, resultPresent = loadErr, loaded != nil
}
var failure *configkit.LoadError
if resultPresent || !errors.As(err, &failure) {
t.Errorf("mode=%v underlay=%v: import opt-in did not fail safely", mode, underlay)
continue
}
diagnostics := failure.Diagnostics()
if len(diagnostics) != 1 || diagnostics[0].Code != configkit.CodeImportDisabled || diagnostics[0].Path.String() != "/configkit" ||
diagnostics[0].Primary == nil || diagnostics[0].Primary.SourceID != wantSource {
t.Errorf("mode=%v underlay=%v: diagnostics=%#v", mode, underlay, diagnostics)
}
}
}
}
func (reader *sourceVersionModeReader) Read(data []byte) (int, error) {
reader.reads++
return reader.Reader.Read(data)

View File

@@ -51,6 +51,11 @@ func assembleBaseInputTrackedForRole[T any](source Source, options Options[T], d
}
return input, diagnostics
}
if !options.Imports && parsed.document != nil {
if diagnostics := disabledDirectiveDiagnostics(parsed.document, Path{}); len(diagnostics) != 0 {
return input, diagnostics
}
}
var versionProcessing *sourceVersionProcessingResult
if versionState != nil && versionState.mode != sourceVersionModeDefault {
var sourceID string
@@ -84,9 +89,6 @@ func assembleBaseInputTrackedForRole[T any](source Source, options Options[T], d
}
}
if !options.Imports && input.document != nil {
if diagnostics := disabledDirectiveDiagnostics(input.document, Path{}); len(diagnostics) != 0 {
return input, diagnostics
}
_, placed, err := placeDocument(input.document, destination, input.document.Location, parseLimits.document.Depth, parseLimits.document.Nodes)
if err != nil {
return input, []Diagnostic{sourceDiagnostic(CodeSourceLimitExceeded, parsed.source.ID, "configuration exceeds the source depth or node limit after destination placement")}