- parse_ids_filter: one shared parser/validator for the ids query param, used
by the /api/jobs handler AND its tests (no more hand-copied wiring that can
drift from — and silently outlive a regression in — the shipped handler)
- present-but-empty ids (?ids=, ?ids=,,) is now a zero-match filter, not a
silent 'return the entire job history'
- bounded history lookup when an ids filter is present: a batch poll costs
O(requested ids), not O(total history)
- dedupe ids so the max-count cap bounds distinct values, not repeats
- .get('id') instead of j['id'] so a job missing its id degrades to no-match
rather than a 500
Add an optional comma-separated `ids` query parameter to GET /api/jobs so a
caller can poll a known set of jobs in a single request instead of one call
per job. The filter narrows the result to the requested job ids and composes
with the existing status / workflow_id filters; an absent or empty `ids` means
no filter.
The handler caps the request at 100 ids (checked before validation) and
validates each id with the existing validate_job_id helper, returning HTTP 400
on overflow or a malformed id. get_all_jobs gains an optional ids argument that
narrows the normalized job list by id.
Adds unit coverage for the filter logic and the endpoint's validation contract.