fix(backends): pass provider API keys through to cmux crewmate spawns#360
Open
Kadriya89 wants to merge 9 commits into
Open
fix(backends): pass provider API keys through to cmux crewmate spawns#360Kadriya89 wants to merge 9 commits into
Kadriya89 wants to merge 9 commits into
Conversation
Kadriya89
force-pushed
the
fm/fix-cmux-env-passthrough
branch
from
July 13, 2026 19:54
8b94f6c to
b1269df
Compare
5 tasks
Kadriya89
force-pushed
the
fm/fix-cmux-env-passthrough
branch
3 times, most recently
from
July 16, 2026 02:30
73a29d1 to
ce2585f
Compare
Owner
|
Automated reminder: thanks for the PR! This branch currently has a merge conflict with the base branch. When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again. Noted for firstmate#360 at |
cmux workspaces get none of firstmate's own process environment, so an opencode crewmate spawned via the cmux backend never saw FIREWORKS_API_KEY and its Fireworks-backed models (e.g. GLM 5.2) failed outright. fm_backend_cmux_create_task now takes the resolved harness, fetches the key from AWS Secrets Manager (opencode/fireworks-api-key, us-east-1) using whatever AWS profile is ambient, and passes it to `cmux new-workspace` as --env FIREWORKS_API_KEY=<value> - the flag cmux-control's own cmuxctl already uses for this. The secret only ever lands in a shell variable, never printed or logged. Fixed along the way: an empty-array expansion under `set -u` that bash 3.2 treats as an unbound-variable error, caught by the real-cmux smoke test.
… skip, peer readiness
Kadriya89
force-pushed
the
fm/fix-cmux-env-passthrough
branch
from
July 16, 2026 18:19
ce2585f to
94d64f2
Compare
Owner
|
Automated reminder: thanks for the PR! This branch currently has a merge conflict with the base branch. When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again. Noted for firstmate#360 at |
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.
Intent
Fix the cmux backend so provider API keys reach spawned crewmate processes: opencode spawns need FIREWORKS_API_KEY so opencode's Fireworks-backed models (e.g. GLM 5.2) work. fm_backend_cmux_create_task now builds --env FIREWORKS_API_KEY= for cmux new-workspace by fetching the key at spawn time from AWS Secrets Manager (secret opencode/fireworks-api-key, region us-east-1) using ambient AWS credentials - no hardcoded profile; a missing key fails the spawn loudly rather than silently continuing. Deliberate decisions already made and binding: the harness-to-secret pairing lives in local gitignored config/cmux-env-secrets so shipped code stays provider-neutral (captain decision); the fetched secret value is never printed, logged, or committed, and is redacted from cmux new-workspace failure output (captain decision); the SC2015 and-or chain in the empty-value check was rewritten as a proper if/then to satisfy shellcheck CI. Unit tests stub the aws CLI so no real AWS calls happen in tests. Push goes through the fork Kadriya89/firstmate per CONTRIBUTING.md since contributors lack upstream push access; PR targets kunchenguid/firstmate. An earlier hand-raised PR #360 exists and should be updated or superseded by the pipeline-raised PR.
What Changed
bin/backends/cmux.shgains a provider-credential passthrough for workspace creation: a new local, gitignoredconfig/cmux-env-secretsfile pairs a harness withENV_VAR / secret-name / optional regionlines, andfm_backend_cmux_create_task(now taking an optional harness argument, whichbin/fm-spawn.shpasses on every cmux spawn) fetches each paired secret from AWS Secrets Manager at spawn time using ambient AWS credentials and injects it via cmux'snew-workspace --env KEY=VALUE. This fixes opencode spawns on the cmux backend, whose scrubbed surface environment never receivedFIREWORKS_API_KEY, breaking Fireworks-backed models.awsCLI, failed call with AWS stderr surfaced, or empty secret) instead of silently launching without a configured key; the fetched value is never printed or logged and is redacted from echoed-backnew-workspacefailure output; malformed pairing lines are skipped with a stderr warning; an absent file or unpaired harness triggers no AWS call at all. An SC2015 and-or chain in the empty-value check was rewritten as if/then for shellcheck.tests/fm-backend-cmux.test.shenv-passthrough coverage (63/63 pass, including 7 new cases: spec parsing, malformed-line warning,--envinjection, no-injection paths, loud fetch failure, redaction, missing-aws failure) with a stubbedawsCLI so no real AWS calls run; synceddocs/cmux-backend.md,docs/configuration.md,docs/scripts.md, andAGENTS.md; and fixed unrelated test fixtures (composer-lib symlink, tasks-axi version skip, peer readiness) that the pipeline's test stage caught.Risk Assessment
✅ Low: The feature is strictly opt-in via a local gitignored config (absent file preserves prior behavior exactly), fails loudly before workspace creation on any fetch problem, redacts the secret from error output, and is covered by eight targeted unit tests stubbing both cmux and aws.
Testing
Baseline full suite passed; re-ran the new cmux backend test file (63/63, covering all passthrough behaviors) and the four fixture-touched test files (all pass), then captured a manual end-to-end CLI transcript with stubbed aws and cmux showing the Fireworks key fetched from Secrets Manager with ambient credentials and injected via --env into the opencode workspace spawn, with no injection for unpaired harnesses, loud spawn failure on fetch errors, and secret redaction in error output.
Evidence: End-to-end demo transcript: cmux --env passthrough (4 scenarios)
== Scenario A: opencode spawn == aws secretsmanager get-secret-value --secret-id opencode/fireworks-api-key --region us-east-1 --query SecretString --output text cmux new-workspace --name fm-firstmate-960fe46d-glm52-demo --cwd /tmp/proj --env FIREWORKS_API_KEY=fw-DEMO-fake-fireworks-key-0000 --focus false --id-format uuids == Scenario B: claude spawn == no --env, aws never invoked == Scenario C: fetch failure == error: failed to fetch secret 'opencode/fireworks-api-key' from AWS Secrets Manager (region us-east-1) - AccessDeniedException...; new-workspace never called == Scenario D: redaction == ... --env FIREWORKS_API_KEY=[redacted] ... (fetched value absent from error output)Evidence: fm-backend-cmux.test.sh full output (63/63 ok)
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
🔧 **Rebase** - 3 issues found → auto-fixed ✅
CONTRIBUTING.md- merge conflict rebasing onto origin/maindocs/configuration.md- merge conflict rebasing onto origin/maindocs/scripts.md- merge conflict rebasing onto origin/main🔧 Fix applied.
✅ Re-checked - no issues remain.
bin/backends/cmux.sh:426- The fetched secret is passed as--env KEY=VALUEin the argv of the externalcmuxCLI process, making it briefly visible in the local process table (ps) whilenew-workspaceruns. This is inherent to cmux-control's--envmechanism (no env-file/stdin alternative exists), but it is an exposure channel the "never printed, logged, or written to a file" documentation claim does not cover.bin/backends/cmux.sh:392- Theaws secretsmanager get-secret-valuecalls run inside awhile readloop fed by process substitution, so the aws CLI inherits the spec stream as stdin. Adding< /dev/nullto the aws invocations would guarantee a prompting or stdin-reading CLI can never consume subsequent pairing lines when multiple secrets are configured for one harness.🔧 **Test** - 1 issue found → auto-fixed ✅
command -v tmux >/dev/null || { echo "tmux is required for e2e tests" >&2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo "== $t =="; bash "$t" || rc=1; done; exit "$rc"🔧 Fix: fix test fixtures: composer-lib symlink, tasks-axi skip, peer readiness
✅ Re-checked - no issues remain.
command -v tmux >/dev/null || { echo "tmux is required for e2e tests" >&2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo "== $t =="; bash "$t" || rc=1; done; exit "$rc"Baseline configured suite (all tests/*.test.sh under tmux) — ran successfully before this roundbash tests/fm-backend-cmux.test.sh— 63/63 pass, including the 7 new env-passthrough cases (spec parsing, malformed-line warning, --env injection for opencode, no injection for unpaired harness, no injection with absent config, loud fetch failure with AWS stderr, secret redaction, missing-aws-CLI failure)bash tests/fm-backlog-handoff.test.sh,bash tests/fm-gotmp.test.sh,bash tests/fm-watcher-lock.test.sh,bash tests/fm-secondmate-lifecycle-e2e.test.sh— the four files whose fixtures the branch's test-fix commit touched; all pass (tasks-axi cases skip cleanly on the older installed version, as intended)Manual end-to-end demo driving real bin/backends/cmux.sh via fm_backend_cmux_create_task with the harness argument fm-spawn.sh now passes, using stubbed aws + cmux CLIs: verified the recordedaws secretsmanager get-secret-value --secret-id opencode/fireworks-api-key --region us-east-1call (no --profile), the--env FIREWORKS_API_KEY=<value>flag on new-workspace, no aws call / no --env for a claude spawn, spawn abort before workspace creation on AccessDenied, and[redacted]in echoed-back new-workspace failure output✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.