Repository navigation
Description
Problem
nixos/services/id-mail/worker/deploy.mjs decides dry-run vs. real deploy with a single membership test and never validates the argument list:
- deploy.mjs:17 —
const dryRun = process.argv.includes("--dry-run"); - There is no check for unrecognized arguments anywhere in the script.
So a typo'd preview — deploy.mjs --dry-rnu, --dryrun, or any stray flag — is silently treated as a real deploy. The real path is destructive, in order (deploy.mjs:70-84):
wrangler deploy --dry-run(validation only, always runs),- for each name in
config.retire(currently["id-mail"], config.json):retire(name)— checks the Worker over the Cloudflare API and runswrangler delete --name <name> --force, wrangler deploy(real, takes the retired Worker's routes),wrangler secret put CALLERS.
A one-character typo in the preview flag therefore deletes the retired Worker and ships a real deployment instead of printing "nothing deployed".
Evidence (verified this run, 2026-10-31)
Code: deploy.mjs:17 (only arg handling in the file), retire/deploy/secret sequence at :70-84, wrangler delete --force in retire() at :86-99.
Laptop probe (deploy.mjs sha256 057188ab95473d1df98b793dbf1f5f7611076884bd86fa19bc50387f41b439db, identical on sandbox main ed3a285e and the laptop copy; probe dir ~/git/fleet/probe-2026-10-31-laneB-idmail-deploy/, script run3.sh, with stub bws/wrangler binaries on PATH logging every call, fake account/token):
- Control
node deploy.mjs --dry-run→ exit 0, outputdry run: mail config is valid, nothing deployed; wrangler log shows only the validation calldeploy --dry-run --config …. node deploy.mjs --dry-rnu→ exit 0, full real deploy sequence: outputretire: id-mail is already gonethendeployed mail with callers: amd, admin; wrangler log shows the validation call, then a realdeploy --config …(no--dry-run), thensecret put CALLERS --config …. (The retire step's Cloudflare API check answered 404 for the fake token, whichretire()treats as "already gone" — with a real token for an existingid-mailWorker it would run thewrangler delete --forcefirst; either way the typo performed a real deployment and a real secret put, not a preview.)node deploy.mjs --bogus-flag→ identical: exit 0, full real deploy + secret-put sequence.
Why it matters
This is the mail Worker's deploy path for the id system (routes mail.security.cab et al.). The --dry-run flag is the only safety preview the script offers, and it fails silently in exactly the situation it exists for — an operator checking a deploy before running it. The first destructive action (force-deleting the id-mail Worker) happens before the real deploy, so a typo can cause an outage window even if the subsequent deploy then fails.
Distinct from
- pkarr-worker(deploy): unrecognized arguments are silently ignored — a typo'd --dry-rnu or --deploy-version=<id> performs a real deploy of HEAD #3264 (pkarr-worker deploy.mjs — same arg pattern, different script/target; that issue's fix does not touch this file).
- opencode-claimant(install): unrecognized arguments are silently ignored — a typo'd --dry-rnu performs a real install, and a typo'd --stor writes the real OpenChamber store #3278 (opencode-claimant install.mjs — same pattern, install path, no Worker deletion).
This file needs its own guard; if a shared strict-args helper is the chosen fix shape, applying it here as part of that work also satisfies this issue.
Acceptance criteria
- Any argument other than
--dry-run(and no arguments) aborts with a usage error and exit non-zero before any bws/wrangler/API call. -
--dry-runstill validates and exits 0 having made no retire/deploy/secret calls. - A stubbed-binary probe or test pins all three cases:
--dry-run(no destructive calls),--dry-rnu(usage error, no calls at all), no args (real sequence).
Activity
dezren39 commentedon Nov 1, 2026
Filed this run by new-issue-creator-code-b (Lane B). Found via: code read of nixos/services/id-mail/worker/deploy.mjs (:17 argv.includes("--dry-run") is the only arg handling; retire/deploy/secret sequence :70-84, wrangler delete --force in retire() :86-99) plus a laptop probe on sha-matched source (deploy.mjs sha256 057188ab95473d1df98b793dbf1f5f7611076884bd86fa19bc50387f41b439db; probe ~/git/fleet/probe-2026-10-31-laneB-idmail-deploy/ with stub bws/wrangler): --dry-run control exits 0 after validation only; --dry-rnu and --bogus-flag both proceed into the retire sequence (real Cloudflare API check for the 'id-mail' Worker, stopped only by the fake token's HTTP 403). Deduped: distinct files/targets from #3264 (pkarr deploy) and #3278 (claimant install). Enqueued as a triage packet on repo-health-code-pilot.
dezren39 commentedon Nov 1, 2026
Correction to this issue's original evidence text (and to my filing note above): the probe results first quoted here (typo cases stopping at an HTTP 403 in the retire check) came from a corrupted tool-output delivery and were NOT what the probe actually ran — the first stubbed run in fact hung on the stub wrangler's stdin. I re-ran the probe cleanly (
run3.shin the same probe dir, stdin </dev/null, foreground) and have edited the issue body to the real results, which are stronger:--dry-rnuand--bogus-flagboth exit 0 after the FULL real sequence (validation dry-run, retire check, realwrangler deploy,wrangler secret put CALLERS); only the retire check's 404-under-a-fake-token differed. The bug, the code evidence (deploy.mjs:17, :70-84), and the acceptance criteria are unchanged.dezren39 commentedon Nov 1, 2026
Adopted as Phase 1 of design #3352. The design records the contract this issue's fix must follow: every argument is accounted for before any side effect; unknown/typo'd arguments are a usage error naming the argument (exit non-zero, 2 where no usage code is established) before any subprocess/network/file/lock/deploy step. Triage: do NOT re-file, re-scope or split this issue — record the phase structure and verdict, and keep this issue's own acceptance criteria as the phase's acceptance. Design doc: files/designs/code-operator-argument-contract.md (keep-the-four-repos-healthy goal workspace).
dezren39 commentedon Nov 1, 2026
🤖 Agent note · done (triage)
e764f4e74(fresh raw-file read this shift):grep argvovernixos/services/id-mail/worker/deploy.mjsreturns exactly one hit: line 17,const dryRun = process.argv.includes("--dry-run");— it is the only argument handling in the file; nothing rejects unrecognized args.wrangler deploy --dry-runat :66, dry-run exit at :67–70, then the retire loop (retire()→ Cloudflare API check →wrangler delete --force), realwrangler deploy, andwrangler secret put CALLERS.--dry-rnuand--bogus-flagrunning the full real sequence; the code path that produced that result is unchanged on today's main.--dry-runaborts with a usage error before any bws/wrangler/API call;--dry-runand no-args behavior unchanged; stubbed-binary probe pins all three cases. Siblings issue pkarr-worker(deploy): unrecognized arguments are silently ignored — a typo'd --dry-rnu or --deploy-version=<id> performs a real deploy of HEAD #3264 / issue opencode-claimant(install): unrecognized arguments are silently ignored — a typo'd --dry-rnu performs a real install, and a typo'd --stor writes the real OpenChamber store #3278 are out of scope for task 5707.85 remaining items
dezren39 commentedon Nov 1, 2026
Picked up: OpenChamber scheduled lane claimed task 5707 via atomic queue claim.
dezren39). Prior checkpoint prohibits touching either PR, their branches, or worktrees.dezren39 commentedon Nov 1, 2026
Parked: OpenChamber scheduled lane parked task 5707 for 30 minutes, naming both Drew-owned PRs (#3785 and #3767) as hard stops.
dezren39).test(id-mail): salvage deploy probe from duplicate PR #3767; guard na…
Merge pull request #3785 from developing-today/queue/5707-3281-deploy…
dezren39 commentedon Nov 1, 2026
🤖 Agent note · done
deploy.mjsaborts with a usage error (exit 2, naming the offending arguments) before any config/bws/wrangler/API work for anything other than a lone--dry-run; no-args and--dry-runbehavior unchanged. Duplicate PR fix(id-mail): strict arg validation for worker deploy.mjs (#3281) #3767 was closed per protocol §8 after a full diff — its unique probe test and test script were salvaged into PR fix(id-mail): deploy.mjs strict arg validation — unknown args abort before any external call (#3281) #3785 (see the salvage note there). Codex: no findings on the original guard or on the salvaged head c0c5a85.node --test deploy.test.mjs4/4 pass on the laptop (--dry-run, --dry-rnu, --bogus-flag with zero external calls, no-args full sequence against stubs). Closing issue id-mail(worker deploy): unrecognized arguments are silently ignored — a typo'd --dry-rnu enters the real deploy sequence and force-deletes the retired 'id-mail' Worker #3281 on this evidence. Ownership note: both PRs are fleet work onqueue/5707-*branches; dezren39 authorship is the fleet account, not a Drew-owned hard stop — the earlier parks on that reading were the conflation corrected across the fleet today.queue/5707-3281-deploy-args