From 99d1a0b926f61c17d6a4fc6876bb16ad4b1e02d5 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Mon, 7 Sep 2026 11:54:35 +0000 Subject: [PATCH] Honor explicit Notarius working directories --- docs/roadmap/remediation.md | 8 +++++++- internal/config/effective_digest.go | 3 --- internal/config/load.go | 6 ------ internal/config/notarius_test.go | 20 ++++++++++++++++++++ 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/docs/roadmap/remediation.md b/docs/roadmap/remediation.md index f4eb86d..e361c75 100644 --- a/docs/roadmap/remediation.md +++ b/docs/roadmap/remediation.md @@ -55,7 +55,13 @@ source. Validate both effective inspection and resolved runtime configuration. ## 2. Stop re-defaulting an explicitly empty Notarius working directory -Status: Open — P2 +Status: Resolved — P2 + +Resolution: Removed both legacy blank-value fallbacks after ConfigKit resolution. +An omitted working directory is still derived by the presence-aware resolver, an +explicit relative directory is still rooted at the pipeline, and explicit empty or +whitespace-only values remain empty and fail enabled-Notarius validation. Existing +relocation-invariant digest coverage remains green. **Evidence:** ConfigKit's resolver correctly uses presence-aware defaulting at `internal/config/pipeline_configkit.go:180`. However, diff --git a/internal/config/effective_digest.go b/internal/config/effective_digest.go index 6f6cc01..563e0ba 100644 --- a/internal/config/effective_digest.go +++ b/internal/config/effective_digest.go @@ -98,9 +98,6 @@ func captureLogicalNotariusPaths(cfg *PipelineConfig) { } configPath := normalizeLogicalFilesystemPath(cfg.Notarius.ConfigPath) workingDirectory := normalizeLogicalFilesystemPath(cfg.Notarius.WorkingDirectory) - if cfg.Notarius.Enabled && workingDirectory == "" && configPath != "" { - workingDirectory = normalizeLogicalFilesystemPath(filepath.Dir(configPath)) - } cfg.resolution.logicalNotariusConfig = configPath cfg.resolution.logicalNotariusWorking = workingDirectory cfg.resolution.logicalNotariusCaptured = true diff --git a/internal/config/load.go b/internal/config/load.go index 8f34376..26f7bf1 100644 --- a/internal/config/load.go +++ b/internal/config/load.go @@ -451,12 +451,6 @@ func resolveNotariusPaths(cfg *PipelineConfig, pipelinePath string) error { return fmt.Errorf("resolve pipeline.notarius.config_path: %w", err) } cfg.Notarius.ConfigPath = resolvedConfigPath - if strings.TrimSpace(cfg.Notarius.WorkingDirectory) == "" { - if resolvedConfigPath != "" { - cfg.Notarius.WorkingDirectory = filepath.Dir(resolvedConfigPath) - } - return nil - } workingDirectory, err := resolve(cfg.Notarius.WorkingDirectory) if err != nil { return fmt.Errorf("resolve pipeline.notarius.working_directory: %w", err) diff --git a/internal/config/notarius_test.go b/internal/config/notarius_test.go index 77eded3..ec04a8a 100644 --- a/internal/config/notarius_test.go +++ b/internal/config/notarius_test.go @@ -99,6 +99,26 @@ notarius: if explicit.Notarius.WorkingDirectory != filepath.Join(dir, "runtime") { t.Fatalf("explicit working_directory = %q, want %q", explicit.Notarius.WorkingDirectory, filepath.Join(dir, "runtime")) } + + for _, value := range []string{`""`, `" "`} { + t.Run("explicit blank "+value, func(t *testing.T) { + blankPath := filepath.Join(t.TempDir(), "pipeline.yml") + blankYAML := strings.Replace(pipelineYAML, " pipeline_id: dnd-session\n", " pipeline_id: dnd-session\n working_directory: "+value+"\n", 1) + if err := os.WriteFile(blankPath, []byte(blankYAML), 0o644); err != nil { + t.Fatal(err) + } + blank, err := LoadPipeline(blankPath) + if err != nil { + t.Fatalf("LoadPipeline(explicit blank working directory) error = %v", err) + } + if blank.Notarius.WorkingDirectory != "" { + t.Fatalf("explicit blank working_directory = %q, want empty", blank.Notarius.WorkingDirectory) + } + if err := ValidatePipelineConfig(blank); err == nil || !strings.Contains(err.Error(), "working_directory is required") { + t.Fatalf("ValidatePipelineConfig() error = %v, want required working directory", err) + } + }) + } } func TestNotariusRelativePathsDoNotMakeEffectiveDigestLocationDependent(t *testing.T) {