Bug report
The OpenAPI spec generated by the gateway contains zero query parameters, even though several handlers read query parameters at runtime via req.query_param(...). Clients generated from the spec therefore cannot pass these filters type-safely.
Steps to reproduce
- Run the gateway and fetch the spec:
curl http://localhost:8080/api/v1/docs
- Count query parameters across all paths:
... | jq "[.paths[][]?.parameters[]? | select(.in==\"query\")] | length"
- Result is
0.
Expected behavior
Endpoints whose handlers read query parameters should declare them in the spec (in: query), so the generated TypeScript/Python clients expose them. Affected endpoints and the parameters their handlers read:
GET /faults, GET /{entity}/faults: status, include_muted, include_clusters
DELETE /faults: status
GET /{entity}/logs: severity, context
GET /updates: origin, target-version
Actual behavior
The spec declares only path parameters; every operation gets query?: never in the generated TypeScript types. The gateway runtime still reads the parameters (e.g. log_handlers.cpp reads severity/context; fault_handlers.cpp reads status/include_muted/include_clusters), so filtering works over raw HTTP but is invisible to any generated client.
Root cause: query parameters were read ad-hoc in handler bodies with no link to the route OpenAPI metadata, so the spec generator never saw them. Request and response bodies are derived from typed DTOs, but query parameters had no equivalent typed contract.
This was masked for a long time: an earlier published TypeScript client shipped without its generated types, so consumer types silently degraded to any and query usage was never type-checked. Once the client shipped real types, the gap surfaced.
Environment
- ros2_medkit version: 0.5.0
- ROS 2 distro: Jazzy / Humble / Rolling (spec generation is distro-independent)
- OS: Ubuntu 24.04
Additional information
Fix approach: make query parameters a typed, descriptor-driven contract like request/response bodies. A query DTO whose dto_fields descriptor drives both the OpenAPI parameters and the handler typed query read, so the two cannot drift. A pre-commit guard bans raw query reads in handlers to keep the typed path the only way in.
Bug report
The OpenAPI spec generated by the gateway contains zero query parameters, even though several handlers read query parameters at runtime via
req.query_param(...). Clients generated from the spec therefore cannot pass these filters type-safely.Steps to reproduce
curl http://localhost:8080/api/v1/docs... | jq "[.paths[][]?.parameters[]? | select(.in==\"query\")] | length"0.Expected behavior
Endpoints whose handlers read query parameters should declare them in the spec (
in: query), so the generated TypeScript/Python clients expose them. Affected endpoints and the parameters their handlers read:GET /faults,GET /{entity}/faults:status,include_muted,include_clustersDELETE /faults:statusGET /{entity}/logs:severity,contextGET /updates:origin,target-versionActual behavior
The spec declares only path parameters; every operation gets
query?: neverin the generated TypeScript types. The gateway runtime still reads the parameters (e.g.log_handlers.cppreadsseverity/context;fault_handlers.cppreadsstatus/include_muted/include_clusters), so filtering works over raw HTTP but is invisible to any generated client.Root cause: query parameters were read ad-hoc in handler bodies with no link to the route OpenAPI metadata, so the spec generator never saw them. Request and response bodies are derived from typed DTOs, but query parameters had no equivalent typed contract.
This was masked for a long time: an earlier published TypeScript client shipped without its generated types, so consumer types silently degraded to
anyand query usage was never type-checked. Once the client shipped real types, the gap surfaced.Environment
Additional information
Fix approach: make query parameters a typed, descriptor-driven contract like request/response bodies. A query DTO whose
dto_fieldsdescriptor drives both the OpenAPIparametersand the handler typed query read, so the two cannot drift. A pre-commit guard bans raw query reads in handlers to keep the typed path the only way in.