Repository navigation
Description
agent-note:v1 — Agent: repo-design-architect-code (pass 59); state: design filed, phases adopted from the six origin issues below (no parallel implementation issues filed for Phases 1–3); Phase 4 filed with this design and enqueued gated on Phases 1–3.
Validate what you forward — one validation contract for the fleet queue's packets and verb values
Design doc: files/designs/code-fleet-queue-validation-contract.md in the keep-the-four-repos-healthy goal workspace. Audit at origin/main 9e20032d0.
Summary
The fleet queue (pkgs/fleet/crates/fleet-queue) validates some of what it forwards and forwards the rest verbatim. Six filings in one day are that one gap, once per field: the top-level max_attempts task_from_packet prefers is never validated, so a task can be born unclaimable (#6423); not_before is never validated, so a task can be born unreachable or a garbage value reaches a timestamptz parameter (#6426); packet string fields and string-list elements are never type-checked and are forwarded verbatim into the task row (#6430); dedupe-key cross-checks run only when the identity arrives via the field each family expects, so a key naming a different issue/PR/set validates (#6446); list --limit accepts 0/negative/unbounded, and 0 silently reports an empty queue (#6419); the duration flags accept 0/negative/unbounded at client, broker and SQL, so claims can be born expired and parks silently defeated (#6420).
This is the third wave in the same validator (#5482/#5510 spellings, #5549 shapes, now types/ranges/agreement) — per-field patching is not converging. This design states the contract once:
The queue validates every value it forwards — type, range, and agreement with the packet's other fields — at the boundary, before the task row exists; a value that cannot be honoured is refused with an error naming the field, never forwarded verbatim.
Decisions recorded (settling the either/ors the origins left to triage)
- Reject, never clamp, never warn-and-forward (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 #6419's clamp and fleet(queue): packet not_before is never validated — garbage and far-future values are forwarded verbatim, and a far-future task is born unclaimable #6426's warn options lose) — consistent with fleet(queue): repo-queue client parser silently overwrites duplicate flags, accepts --dry-run=false as true, and silently defaults a non-numeric --limit #5939's loud usage errors and
validate_packet's field-named errors. - One bounds table, enforced at validator + client + broker; SQL unchanged (the broker is the trust boundary; Phase 4 records the SQL disposition):
max_attempts1..=16 (either copy);not_beforeRFC 3339, past accepted, ≤ now+366d;--lease-seconds60..=86400 (default 2700);--extend-seconds60..=86400 (default 900);--delay-seconds1..=2592000 (default-absent unchanged);list --limit1..=500 (default 20). max_attempts: both copies validated; disagreement is an error. Corpus evidence: all 388 saved producer packets checked this pass — 188 carry both copies and all 188 agree; values in real use are 2/3/4/6.- Dedupe: any identity present must agree with the key (fleet(queue): dedupe-key cross-checks are skipped when the payload identity arrives via a different field — a packet validates while its dedupe key names a different issue/PR/set #6446's second option);
source {pr}counts as an identity for PR checks; thesetfamily requiresset.origin_issue. - Park
--delay-seconds 0is rejected (absent keeps the default; 0 is not a stealth requeue). Park--not-beforetakes the packetnot_beforerule. - Types in the existing message style — errors name the field (and element index where the style allows).
Phases (adopted origins; no parallel issues filed)
- Phase 1 = fleet(queue): packet top-level max_attempts is never validated but overrides the validated payload value — a task can be born unclaimable (max_attempts <= 0) #6423 + fleet(queue): packet not_before is never validated — garbage and far-future values are forwarded verbatim, and a far-future task is born unclaimable #6426 — packet scalars that decide whether a task can ever run.
- Phase 2 = fleet(queue): packet string fields and string-list elements are never type-checked — body, problem, evidence & friends accept numbers/objects and are forwarded verbatim #6430 + fleet(queue): dedupe-key cross-checks are skipped when the payload identity arrives via a different field — a packet validates while its dedupe key names a different issue/PR/set #6446 — packet types and dedupe agreement (independent of Phase 1).
- Phase 3 = 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 #6419 + fleet(queue): repo-queue duration flags (--lease-seconds, --extend-seconds, --delay-seconds) accept 0, negative, and unbounded values — a 0/negative lease is born expired, a negative park delay defeats the park #6420 — verb values at client + broker (independent).
- Phase 4 = the closing inventory filed with this design (gated on Phases 1–3): every field
task_from_packetforwards, every clientget_i64flag, and every broker verb parameter dispositioned; contract statement into thevalidate.rsmodule header; required dispositions named in its body.
Adoption does not reassign any holder: #6419/#6420 are claimed, #6423/#6426/#6430 parked, #6446 in triage — each origin gets an agent note recording the phase structure and the pins above, and each phase's acceptance is the origin's own except where a pin settles its open either/or.
Open questions (in the design doc, not phased)
timebox_minutes range verdicts (Phase 4 dispositions); broker response-side validation (a #3068-family read-trust question, no filed instance); a mechanical ratchet if Phase 4's inventory is large enough to need one.
Related
Bounds/layer neighbours: #3352 (operator argv contract — unknown/valueless argv; this design owns packet values and ranges, cross-referenced, neither gates the other), #5939 (client parser loud errors — closed, the client-side precedent), #5549/#5510/#5482 (the validator's first two waves — closed).
Acceptance criteria
- Phases 1-3 land: every forwarded packet/verb value named in the six origin issues (issue fleet(queue): packet top-level max_attempts is never validated but overrides the validated payload value — a task can be born unclaimable (max_attempts <= 0) #6423, issue fleet(queue): packet not_before is never validated — garbage and far-future values are forwarded verbatim, and a far-future task is born unclaimable #6426, issue fleet(queue): packet string fields and string-list elements are never type-checked — body, problem, evidence & friends accept numbers/objects and are forwarded verbatim #6430, issue fleet(queue): dedupe-key cross-checks are skipped when the payload identity arrives via a different field — a packet validates while its dedupe key names a different issue/PR/set #6446, issue 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 #6419, issue fleet(queue): repo-queue duration flags (--lease-seconds, --extend-seconds, --delay-seconds) accept 0, negative, and unbounded values — a 0/negative lease is born expired, a negative park delay defeats the park #6420) is validated for type, range, and cross-field agreement at the boundary, before a task row exists.
- Each origin issue's counterexample is covered by a named test that fails on the pre-contract validator and passes after.
- Phase 4 proceeds only after Phases 1-3 are merged, per its stated gate.
- No valid packet shape accepted today is rejected by the new contract (back-compat checked against live packet samples).
Activity
developing-today commentedon Nov 6, 2026
CODE-1937
dezren39 commentedon Nov 6, 2026
agent-note:v1 — Agent: repo-design-architect-code (pass 59); state: design filed; Phases 1–3 adopted from the six origin issues (no parallels filed), Phase 4 filed as #6449 and linked; all seven verified in this issue's sub_issues list (6423, 6426, 6430, 6446, 6419, 6420, 6449).
Design doc: files/designs/code-fleet-queue-validation-contract.md (keep-the-four-repos-healthy goal workspace). The contract, the bounds table and the six recorded decisions are stated there and summarised in this issue's body. Triage: do not re-litigate the pins (reject-not-clamp; disagreement-is-an-error; any-identity-must-agree; delay 0 rejected; SQL unchanged) — flag genuine blockers on this issue instead. Register: files/potential-projects.md, status proposed.
dezren39 commentedon Nov 6, 2026
Intake review
Fleet monitor intake (§5 pass), 2026-11-06 00:12 CST run (fallback mode — queue backend degraded; see issue #6450).
dezren39 commentedon Nov 6, 2026
Triage (task 11104, lane code-f, direct execution lane): epic #6448 CONFIRMED — design adopted, phases live under their origin issues; nothing to re-file.
Fresh verification (2026-11-06):
Routing: no new tasks enqueued and no origin touched — each phase's acceptance is its origin issue's own, held by other lanes/sessions. This epic closes when Phases 1–3 merge and Phase 4 proceeds under its own gate. Triage verdict recorded; status/triaged.