feat(secrets): per-execution environment scoping for secret resolution (ADR-0031 Phase 3, PR A) - #83
Merged
Conversation
…n (ADR-0031 Phase 3) Make "environment" a per-execution scoping dimension instead of a single server-wide config string baked into the secret resolver at DI time. - workflow.New gains an environment field + getter; the WorkflowHandler builds a per-workflow secrets.Resolver scoped to that environment. New executions take the environment from the trigger (default FUSE_ENVIRONMENT); replay reads it from the reconstructed workflow so resolution stays deterministic across restart/recovery/retry. - Thread environment trigger -> message -> workflow_sup spawn -> instance supervisor -> WorkflowHandlerInitArgs. Sub-workflows inherit the parent's environment. TriggerWorkflowRequest/Response gain an optional environment field; CLI `fuse workflow` gains -e/--environment. - Persist environment on the workflows row (migration 000009, NOT NULL DEFAULT 'default' backfill) and read it back in Get; excluded from the upsert UPDATE clause so state-change saves never clobber it. - Drop the now-orphaned process-wide secret resolver DI provider. Tests: unit coverage for New/Environment(); functional contract subtest asserts Save/Get preserves environment (memory + postgres). Strict environments registry and trigger validation follow in a separate PR. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
ADR-0031 Phase 3, deliverable 1 of 4 (PR A — threading core). Makes
environmentaper-execution scoping dimension instead of a single server-wide config string baked into
the secret resolver at DI time. This unblocks per-context LLM keys, credentials, and external
backends, all of which scope by environment.
Changes
workflow.Newgains anenvironmentfield + getter; theWorkflowHandlerbuilds asecrets.NewResolver(store, env)per workflow. New executions takethe environment from the trigger (default
FUSE_ENVIRONMENT); replay reads it from thereconstructed workflow so resolution is deterministic across restart/recovery/retry. The
process-wide resolver DI provider is removed.
environmentflows trigger →TriggerWorkflowMessage→workflow_supspawn →instance supervisor →
WorkflowHandlerInitArgs. Sub-workflows inherit the parent'senvironment.
TriggerWorkflowRequest/Responsegain an optionalenvironment;fuse workflowgains
-e/--environment.000009addsworkflows.environment(NOT NULL DEFAULT 'default'backfill + index);
postgresGetreads it,Savewrites it and excludes it from theON CONFLICT DO UPDATEso state-change saves can't clobber it. Memory backend unchanged.Tests
make lintclean,make buildok,make test638→ passing incl. newTestNewStoresEnvironmentand a functional contract subtest asserting Save/Get preserves environment (memory + postgres).
🤖 Generated with Claude Code