The same declared-vs-enforced family as #7359, on the sibling parameter of the same route, left behind when status was fixed.
Symptom
GET /api/v1/automation/:name/runs against a flow with 10 runs:
| query | result |
|---|
?limit=0 | 200 with zero rows |
?limit=-5 | 200 with zero rows |
?limit=101 | 200 with all 10 rows (cap not applied) |
?limit=abc | 400 VALIDATION_FAILED — "Invalid `limit` query parameter — expected a whole number, received "abc"" |
?limit=1.5 | the same 400 |
So the boundary refuses the wrong type but accepts anything outside the declared range. Reproduced 2×, identical both passes.
The ?limit=0 arm is the one that bites: a caller paging with a computed limit that reaches 0 is told the flow has no runs — a confidently wrong answer of exactly the shape #7359 was filed for.
Root cause
packages/runtime/src/query-param.ts:121parseIntegerParam checks Number.isInteger and returns the value; it has no min/max arm — unlike its sibling parseEnumParam, which does read the closed set. packages/runtime/src/domains/automation.ts:737 calls it bare, so ListRunsRequestSchema's declared (1, 100) never reaches the boundary.
Suggested shape
Give parseIntegerParam optional bounds and pass ListRunsRequestSchema's own at the call site, so the declared and enforced ranges cannot drift — the discipline #7359's fix applied to status by reading ExecutionStatus.options rather than re-listing them.
Severity
P3 — no corruption, no leak. A wrong-but-confident answer and an unenforced result-set cap.
Source
Found by the platform checklist retest of automation.flow-runs-page-test-trigger (framework 279ee48a), while verifying #7359's fix. Held no clause of that item.
The same declared-vs-enforced family as #7359, on the sibling parameter of the same route, left behind when
statuswas fixed.Symptom
GET /api/v1/automation/:name/runsagainst a flow with 10 runs:?limit=0?limit=-5?limit=101?limit=abcVALIDATION_FAILED— "Invalid `limit` query parameter — expected a whole number, received "abc""?limit=1.5So the boundary refuses the wrong type but accepts anything outside the declared range. Reproduced 2×, identical both passes.
The
?limit=0arm is the one that bites: a caller paging with a computed limit that reaches 0 is told the flow has no runs — a confidently wrong answer of exactly the shape #7359 was filed for.Root cause
packages/runtime/src/query-param.ts:121parseIntegerParamchecksNumber.isIntegerand returns the value; it has no min/max arm — unlike its siblingparseEnumParam, which does read the closed set.packages/runtime/src/domains/automation.ts:737calls it bare, soListRunsRequestSchema's declared(1, 100)never reaches the boundary.Suggested shape
Give
parseIntegerParamoptional bounds and passListRunsRequestSchema's own at the call site, so the declared and enforced ranges cannot drift — the discipline #7359's fix applied tostatusby readingExecutionStatus.optionsrather than re-listing them.Severity
P3 — no corruption, no leak. A wrong-but-confident answer and an unenforced result-set cap.
Source
Found by the platform checklist retest of
automation.flow-runs-page-test-trigger(framework279ee48a), while verifying #7359's fix. Held no clause of that item.