Repository navigation
Description
fleet(queue): repo-queue list --limit accepts 0, negative, and unbounded values — 0 silently reports "(no tasks)", and the broker forwards the value verbatim to PostgREST
Evidence (verified this run, origin/main 669788ab0344)
Neither end of the list path validates the limit's range:
- Client —
pkgs/fleet/crates/fleet-queue/src/client.rs:parse_i64_flag(:579-582) accepts anyi64(the fleet(queue): repo-queue client parser silently overwrites duplicate flags, accepts --dry-run=false as true, and silently defaults a non-numeric --limit #5939 fix made non-numeric values a loud error, but range was never checked), andcmd_list(:875, :883) sends the parsed value verbatim as"limit". - Broker —
pkgs/fleet/crates/fleet-queue/src/queue_broker.rs: the/listhandler (:492) takesreq.get("limit").and_then(|l| l.as_i64()).unwrap_or(20)and interpolates it unchecked into the PostgREST query (:502-505):tasks?select=…&limit={limit}.
Verified on the laptop with the real repo-queue binary (built this run from the laptop primary; client.rs/queue_broker.rs limit paths are identical HEAD..origin/main) against a recording stub broker (probe ~/git/fleet/probe-queue-limit, REPO_QUEUE_BROKER_URL direct transport):
| invocation | recorded /list body |
exit |
|---|---|---|
list --limit 0 |
"limit":0 |
0 |
list --limit -5 |
"limit":-5 |
0 |
list --limit 999999999 |
"limit":999999999 |
0 |
list --limit 20 (control) |
"limit":20 |
0 |
list --limit abc (control, #5939) |
— rejected: argument --limit: invalid int value "abc" |
2 |
Consequences, by value:
--limit 0→ PostgRESTlimit=0returns zero rows → the client prints(no tasks)and exits 0, even when the queue is non-empty. A typo'd or scripted0reads as an empty queue — the false-empty misreport class (cf. fleet(queue): repo-queue client accepts empty REPO_QUEUE_DEFAULT_QUEUE / REPO_QUEUE_SIGNAL_PATH — silently uses queue "" and fails signal writes with a blank path #6314, where an empty queue name also reported "(no tasks)").- Negative → forwarded verbatim; PostgREST rejects a negative limit, so the operator gets a downstream database-API error instead of a usage error naming the flag.
- Huge → no cap on either side: the broker issues an unbounded select and streams/prints the whole result set.
Why it matters
repo-queue list is the fleet's own visibility surface — lanes and monitors use it to decide whether work exists. A limit that can silently mean "show nothing, successfully" undermines exactly the checks that rely on it (a Step-0 gate or a human checking a queue with --limit 0 in a script sees an empty queue that is not empty). The fix layer is a triage call: client-side range validation (consistent with #5939's loud-error pattern), a broker-side clamp/reject (the broker is the trust boundary for non-CLI callers, e.g. the claimant's rich list reads), or both.
Acceptance criteria
-
repo-queue list --limit 0and negative values are rejected with a usage error naming--limit(exit 2), consistent with the fleet(queue): repo-queue client parser silently overwrites duplicate flags, accepts --dry-run=false as true, and silently defaults a non-numeric --limit #5939 non-numeric error — or, if a clamp is chosen instead, the chosen semantics are documented in the--help/command docs and pinned by tests. Silent(no tasks)for a configured 0 is not an acceptable outcome. - The broker's
/listhandler validates or clamps the limit it interpolates into the PostgREST query, so a non-CLI caller cannot drive a negative or unbounded select through it. - A sane maximum exists (value is triage's call) and is enforced on the client and/or broker;
--limit 20and the default (absent flag → 20) behave exactly as before. - Tests pin the boundary: 0, -1, the maximum, maximum+1, and the default; the existing fleet(queue): repo-queue client parser silently overwrites duplicate flags, accepts --dry-run=false as true, and silently defaults a non-numeric --limit #5939 non-numeric rejection test still passes.
- Same-pass audit note: the sibling
get_i64flags (--lease-secondsat claim,--extend-secondsat heartbeat,--delay-seconds) share the range-unchecked parse — triage records whether each is already validated downstream (SQL/broker) or needs the same treatment; this issue's fix is not blocked on that audit.
Activity
developing-today commentedon Nov 6, 2026
CODE-1921
dezren39 commentedon Nov 6, 2026
🤖 Agent note · filed
dezren39 commentedon Nov 6, 2026
🤖 Agent note · handed off
50 remaining items
dezren39 commentedon Nov 6, 2026
🤖 Agent note · picked up
dezren39 commentedon Nov 6, 2026
🤖 Agent note · parked
list --limitrange validation, 1..=500, reject-not-clamp, tests pin 0/-1/max/max+1/default; Codex review completed with no findings). CI (scripts-test) is still pending, so task 11209 parks instead of waiting.Merge pull request #6556 from developing-today/queue/11209-6419-limit…
dezren39 commentedon Nov 6, 2026
🤖 Agent note · done