fix: utoipa IntoParams generates 'in: path' for query parameters (3+ endpoints)
External audit finding #7 (closed) (2026-05-26), confirmed by reading generated OpenAPI snapshots.
Endpoints that take Query<...> parameters are emitting "in": "path" in the generated OpenAPI spec because utoipa::IntoParams defaults to parameter_in = Path when no explicit annotation is provided.
Confirmed-affected endpoints (from docs/modules/ROOT/openapi/eligibility.json + appeals.json):
GET /v1/eligibility/case-status?household_id=...—eligibility.json:459GET /v1/eligibility/cross-program-alerts?worker_id=...—eligibility.json:512GET /v1/eligibility/determinations?household_id=...(new in MR-e !380 (merged)) —eligibility.json:513(per #586 / #587)GET /v1/appeals/hearings/upcoming?days=...—appeals.json:796
Likely-affected (utoipa::IntoParams pattern repeats):
- Any
Query<SomeQuery>handler whereSomeQueryderivesIntoParamswithout#[into_params(parameter_in = Query)]or per-field#[param(in = Query)].
Impact:
- Generated typed clients (e.g. via openapi-generator) emit positional path-segment params instead of query string params → 404 at runtime
- Swagger UI documents the endpoints incorrectly — readers can't tell whether to pass
?household_id=Xor/X
Fix:
- Add
#[into_params(parameter_in = Query)]above each affected struct (single line per struct). - Sweep the workspace:
grep -rn "Query<.*>\|IntoParams" services/*/src/api/and confirm every struct used in aQuery<>extractor has the annotation. - Add a
cargo xtask api-docs --checkstep that asserts no"in": "path"schemas on endpoints whose handler signature usesQuery<>.
Severity: medium — not a runtime bug (axum routes ignore the spec annotation) but generated clients are wrong and #587 paging follow-up will trip over the same drift if not fixed first.
Labels: type::bug, priority::medium, service::ci, program::infrastructure