Summary
parseSecretsConfig at cmd/wfctl/infra_bootstrap.go:93 and cmd/wfctl/infra.go:1254 raw-unmarshals only the current file, bypassing config.LoadFromFile (and therefore processImports).
After PR #550 merges, wfctl infra align correctly resolves env-var tokens declared in imported secrets.generate / secrets.entries blocks. But wfctl infra bootstrap and post-apply sync use the direct-parsing path, so an imported secrets.generate block will silently fail to actually generate those secrets at bootstrap time.
Symptom
# main.yaml
imports:
- shared.yaml
# shared.yaml
secrets:
generate:
- key: STAGING_PG_PASSWORD
type: random_hex
length: 32
Reproduction
- Set up two-file config as above.
- Run
wfctl infra bootstrap --config main.yaml.
- Verify
STAGING_PG_PASSWORD does NOT appear in the configured secretStores[*] backend.
Path forward
Refactor parseSecretsConfig to call config.LoadFromFile (which honors imports + applies the merge logic added in #550) instead of yaml.Unmarshal on raw bytes. Two callers in scope:
cmd/wfctl/infra_bootstrap.go:93
cmd/wfctl/infra.go:1254
Both already have a config file path, so the change is mechanical. Add regression tests:
wfctl infra bootstrap with imported secrets.generate actually generates the secrets.
wfctl infra post-apply sync surfaces imported entries in secretStores.
Context
Surfaced by Copilot review on PR #550. Scope-cut from #550 to keep that PR focused on the original W-541 align-rule fix (per docs/plans/2026-05-05-iac-deferred-cleanup-design.md). The direct-parsing-caller refactor is a substantial enough behavior change to warrant its own PR with proper review focus + rollback story.
Related: workflow#541, PR #550.
Summary
parseSecretsConfigatcmd/wfctl/infra_bootstrap.go:93andcmd/wfctl/infra.go:1254raw-unmarshals only the current file, bypassingconfig.LoadFromFile(and thereforeprocessImports).After PR #550 merges,
wfctl infra aligncorrectly resolves env-var tokens declared in importedsecrets.generate/secrets.entriesblocks. Butwfctl infra bootstrapand post-apply sync use the direct-parsing path, so an importedsecrets.generateblock will silently fail to actually generate those secrets at bootstrap time.Symptom
wfctl infra align(post-fix(wfctl): R-A4 align rule consults top-level secrets.generate + entries (workflow#541) #550): PASS — sees imported key.wfctl infra bootstrap: silently skipsSTAGING_PG_PASSWORDgeneration; secret never lands in the configured store.Reproduction
wfctl infra bootstrap --config main.yaml.STAGING_PG_PASSWORDdoes NOT appear in the configuredsecretStores[*]backend.Path forward
Refactor
parseSecretsConfigto callconfig.LoadFromFile(which honors imports + applies the merge logic added in #550) instead ofyaml.Unmarshalon raw bytes. Two callers in scope:cmd/wfctl/infra_bootstrap.go:93cmd/wfctl/infra.go:1254Both already have a config file path, so the change is mechanical. Add regression tests:
wfctl infra bootstrapwith importedsecrets.generateactually generates the secrets.wfctl infrapost-apply sync surfaces imported entries insecretStores.Context
Surfaced by Copilot review on PR #550. Scope-cut from #550 to keep that PR focused on the original W-541 align-rule fix (per
docs/plans/2026-05-05-iac-deferred-cleanup-design.md). The direct-parsing-caller refactor is a substantial enough behavior change to warrant its own PR with proper review focus + rollback story.Related: workflow#541, PR #550.