Relationships
#3680 Workflow runs ignore defaultVault: step sensitive outputs land in the first vault, and validate predicts a vault the run doesn't use
Opened by stack72 · 10/20/2026· Shipped 10/20/2026
Problem
Workflow runs ignore defaultVault from .swamp.yaml. A workflow step's sensitive outputs land in the first user vault (lowest id) instead of the default vault, while swamp behavior run honours it.
DefaultStepExecutor.buildDeps(src/domain/workflows/execution_service.ts, theVaultService.fromRepository(repoDir, { vaultsDir })call) builds the step's vault service withoutdefaultVaultName. It runs every workflow step, locally and on serve.- Every other entry point passes
defaultVaultName: marker?.defaultVault:model_method_run.ts,workflow_validate.ts, serve's own vault services, the access and vault libswamp operations. - So
swamp workflow validatepredicts the default vault while the run stores to another one.
Repro (released 20261019.214045.0-sha.6dbc53eb)
swamp repo init --tool none --no-vault, thenswamp vault create local_encryption vault-bandswamp vault create local_encryption vault-a, so that vault-a has the lower id (swamp vault list --json).- Add
defaultVault: vault-bto.swamp.yaml. - A behavior whose
createmethod writes a resource with a sensitive field. swamp behavior run <def> createstores the field in vault-b (correct).- A workflow with one step running the same method:
swamp workflow runstores it in vault-a. - Add
vaults: [vault-b]to that workflow:swamp workflow validatepasses, thenswamp workflow runis refused before the method runs with "stores sensitive output in vault 'vault-a', which this run may not write: ... not in the vaults list".
Expected
A workflow step resolves sensitive outputs like a behavior run does: field vaultName, then step dataOutputOverrides / definition resources vaultName, then the spec's, then defaultVault, then the first user vault (design/primitives/vaults.md Vault Resolution Order).
Impact
- In a repo with more than one vault, workflow outputs go to whichever vault sorts first, which can be the vault holding author secrets that
design/enablers/access-control.mdsays to keep out of the outputs vault. - Under vault scoping it fails closed: the pre-run check refuses the wrong vault, so validate passes and the run fails.
- A repo with only the
defaultvault created byrepo initis unaffected, since the first vault is the default.
Not a regression
defaultVaultName was never passed into the workflow executor (git log -S defaultVaultName on execution_service.ts). defaultVault came in for behavior execution (swamp PR 1984) and this path was missed.
Suggested fix
Read the repo marker's defaultVault once per run, carry it through StepExecutionContext into buildDeps, and pass it as defaultVaultName. The two read-only fromRepository calls (evaluated-cache replay, workflow resume) only call get and do not need it. Add a workflow-run integration test with two vaults where the default is not the lowest id, next to the swamp-club#3606 tests in integration/sensitive_field_vault_test.ts.
Found while testing swamp-club#3606.
Shipped
Click a lifecycle step above to view its details.
Sign in to post a ripple.