fix(deploy): stop MAPLE_ENVIRONMENT being overridable by a stray env var - #284
Merged
Conversation
Both workers passed MAPLE_ENVIRONMENT through `optionalPlain`, which resolves to `process.env[key]?.trim() || fallback` — so process.env WINS over the stage-derived value it was meant to fall back to. That matters because both non-production email gates derive from this single variable: the alerting worker's scheduled() early return, and EmailService.emailAllowed. A stray MAPLE_ENVIRONMENT=production reaching a pr-N or stg deploy environment opens both at once, and preview stages run the same digest and onboarding crons against branched DBs holding real Clerk members — so the only thing left standing between a preview worker and a duplicate mailing to real users is the absence of the prd-only EMAIL binding. Deriving it from the stage removes the override. The binding gating stays as defence in depth; this just means it is no longer load-bearing on its own. Found while designing containment for a third-party email vendor, which needed an equivalent guard and had no binding to lean on. That work is dropped, but this bug predates it and stands alone.
Contributor
|
Your Pullfrog Router balance is exhausted. You have a payment method on file but auto-reload is disabled, so runs paused once your balance went past the overdraft buffer. Top up balance → · Enable auto-reload →
|
🍁 Maple PR previewNote Preview resources were removed when this pull request closed. Final commit |
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.

The bug
Both email-capable workers passed
MAPLE_ENVIRONMENTthroughoptionalPlain:So
optionalPlain("MAPLE_ENVIRONMENT", resolveDeploymentEnvironment(stage))doesn't mean "use the stage" — it means "useprocess.envif present, otherwise the stage." The stage-derived value is the fallback, not the source of truth.Why it matters
Both non-production email gates derive from that one variable:
apps/alerting/src/worker.ts— thescheduled()early return that skips all crons off productionapps/api/src/lib/EmailService.ts—emailAllowed, whichisConfigureddepends onA stray
MAPLE_ENVIRONMENT=productionreaching apr-Norstgdeploy environment opens both at once. Preview and staging stages run the same digest and onboarding crons against branched databases that still hold real Clerk members, so at that point the only remaining guard is the absence of the prd-onlyEMAILbinding — one config line away from a duplicate mailing to real users.The fix
Derive it from the stage, non-overridable, in both workers. The prd-only binding gating stays as defence in depth; it's just no longer load-bearing on its own.
chat-flueandelectric-syncuse the sameoptionalPlainpattern but have noEMAILbinding and no email gate, so they're left alone — worth a follow-up only if consistency is wanted for its own sake.Provenance
Found while designing non-prod containment for a third-party email vendor, which needed an equivalent guard and had no Cloudflare binding to lean on. That vendor work has been dropped — onboarding will instead move to a Cloudflare Workflow with durable
step.sleep, since the machinery is largely already there. This bug predates that whole exercise and stands on its own.Verification
Config-only change, no runtime code touched.
tsc --noEmitclean onapps/apiandapps/alerting.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.