Repository navigation
Description
Problem
pkgs/pkarr-worker/deploy.mjs performs no argument validation: it reads only the two spellings it knows and silently ignores everything else on the command line. A misspelled --dry-run, the conventional --deploy-version=<id> equals form, or any stray flag is dropped without a word — and the script proceeds to make a real production deploy. For a deploy tool, an ignored argument is not a cosmetic papercut: the operator believes they asked for a preview (or a rollback to a named version) and instead ships HEAD at 100%.
This is the sibling of #3252 (a known flag ignored on one path): here the flag is never recognized at all, on every path.
Evidence (verified this run, main f4f800e7)
-
Arg parsing is two lookups and nothing else (
deploy.mjs:39-45):const args = process.argv.slice(2); const dryRun = args.includes("--dry-run"); const deployVersionAt = args.indexOf("--deploy-version"); const deployVersion = deployVersionAt >= 0 ? args[deployVersionAt + 1] : null; if (deployVersionAt >= 0 && !deployVersion) { throw new Error("--deploy-version needs a version id"); }
No loop over
args, no rejection of unrecognized entries.--deploy-version=<id>does not match the exact-stringindexOf, sodeployVersionstaysnulland the script falls through to the deploy-HEAD flow. A typo'd--dry-rnuleavesdryRun === false. -
Laptop probe (sha-matched copy of
deploy.mjs, sha256805d407348729bf00a6010a5502b66455d66c559d79d4659a786faf067d80ff9— same hash as current main; stubcf/bws/giton PATH logging argv,CLOUDFLARE_ACCOUNT_IDstubbed, stubcf workers getfailing so the bootstrap path runs; probe dir~/git/fleet/probe-2026-10-31-laneB-deployargs/on the laptop):- Control
node deploy.mjs --dry-run→ cf log:cf -q deploy --worker pkarr --tag git-aaaaaaaaaaaa --message … --dry-run; exit 0; "dry run: config builds, nothing uploaded". node deploy.mjs --dry-rnu(one transposed letter) → cf log:cf -q deploy --worker pkarr --tag git-aaaaaaaaaaaa --message …— no--dry-run: a realcf deploycall. The run then continued toworkers versions listand stopped only because the stub returned no version; against the real account it would have proceeded to create the 100% deployment.node deploy.mjs --deploy-version=v-rollback-123→ the named rollback version is never mentioned again; cf log shows the same real bootstrap deploy of HEAD (git-aaaaaaaaaaaa). The operator asked to roll back and instead deployed current HEAD.node deploy.mjs --prod(unknown flag) → silently ignored; same real deploy of HEAD.
- Control
Why it matters
deploy.mjs is the one sanctioned path for shipping and rolling back the pkarr Worker (#1828 standard). Its safety rests entirely on the operator typing exactly --dry-run or exactly --deploy-version <id> — one typo or the ubiquitous --flag=value habit converts a preview or a rollback into a live deploy of whatever HEAD happens to be, with no warning that anything was ignored. Tools that perform irreversible outward actions must fail closed on input they do not understand.
Acceptance criteria
- Any argument that is not
--dry-run,--deploy-version <id>, or--deploy-version=<id>(if the equals form is supported) aborts before anybws/cfcall, with an error naming the offending argument and the usage. -
--deploy-version=<id>either works identically to the space form or is refused as above — it must never fall through to deploying HEAD. - A misspelled safety flag (e.g.
--dry-rnu) can no longer produce a real deploy: covered by the unknown-argument refusal, with a regression test/probe case. - The known-good invocations in the header comment (
deploy.mjs [--dry-run],deploy.mjs --deploy-version <id>) behave exactly as today (including pkarr-worker(deploy): --dry-run is ignored on the --deploy-version path — a rollback preview creates a real 100% deployment #3252's dry-run semantics once that lands). - Verification is reproducible with stub
cf/bwson PATH: unknown/equals-form arguments make zerocfcalls.
Dedup
Searched open + closed issues for pkarr-worker deploy argument handling. #3252 covers --dry-run being ignored on the --deploy-version path (both flags recognized, one branch drops the check); #3261 is RETENTION_SECONDS parsing in src/index.ts; #1828/#1829 are the deployment standard and the original implementation. No issue covers unrecognized/misspelled arguments or the --deploy-version=<id> form being silently ignored.
Activity
dezren39 commentedon Nov 1, 2026
🤖 Agent note · filed
dezren39 commentedon Nov 1, 2026
Adopted as Phase 1 of design #3352 (with #3252 — same file: the equals-form pin and the flag-on-every-path audit are yours together). 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).
39 remaining items
developing-today commentedon Nov 3, 2026
agent-note:v1
state: reviewed (coverage loop-back)
Coverage pass 2026-11-03, loop-back review: this issue was re-reviewed (drift / overlap / already-handled / stale / blockers / ordering) so every open issue in the four repos is reviewed and in the system. Verdict: still live; in the system as task 8540 (triage, queued, priority 30) in repo-health-code-pilot. Labels audited and synced. If it is already handled at current main, its triage closes it with evidence; if oversized, the triage files the split; blockers belong on this issue.
Found via: coverage loop-back 2026-11-03
dezren39 commentedon Nov 3, 2026
🤖 Agent note · handed off
opencode; handing off to the laptop claimant.67f97516con main. Expected terminal: complete task 8540 asalready_donewith that evidence and strip the claim labels.dezren39 commentedon Nov 3, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 3, 2026
agent-note:v1
state: done (queue task 8540 triaged, openchamber scheduled lane)
verdict: already_done. issue CLOSED 2026-11-03T14:35:29Z; fix PR #4946 MERGED 2026-11-03T14:35:27Z (commit 67f9751, in main): deploy arg parsing moved to deploy-args.mjs and rejects unknown arguments fail-closed. no further work.