Skip to content

Add OpenAPI support via Huma framework#628

Merged
wesm merged 12 commits intomainfrom
openapi-support
Apr 6, 2026
Merged

Add OpenAPI support via Huma framework#628
wesm merged 12 commits intomainfrom
openapi-support

Conversation

@wesm
Copy link
Copy Markdown
Collaborator

@wesm wesm commented Apr 6, 2026

Summary

  • Add huma/v2 dependency and define typed request/response types for all API endpoints, replacing untyped map[string]any responses with structured Go types that generate an OpenAPI spec automatically.
  • Migrate all HTTP handlers from raw HandleFunc to Huma endpoints with typed inputs/outputs, pointer-based optional query params, and proper HTTP status codes. Remove old handler functions.
  • Add cursor-based pagination (before parameter) to the ListJobs endpoint for efficient backward paging through large result sets.
  • Add Huma endpoint tests verifying request parsing, response structure, and OpenAPI spec correctness. Fix query param handling for Huma compatibility (pointer types for optional params, sentinel values for defaults).

🤖 Generated with Claude Code

wesm and others added 11 commits April 6, 2026 09:33
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement registerHumaAPI on Server to register all 12 endpoints
with Huma, and humaXxx handler methods that replicate the exact
behavior of the old handleXxx functions using typed input/output
structs from huma_types.go.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Match the old handler's HTTP 201 Created response for POST
/api/comment, which creates a new resource.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Huma v2 does not support pointer types for query parameters.
Changed ListJobsInput, GetReviewInput, and ListCommentsInput to
use value types with sentinel defaults (-1 or 0 for "not provided").

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Delete 12 old HTTP handler functions and 5 request/response types
from server.go that are now served by Huma-registered endpoints.
Move shared types (CancelJobRequest, RerunJobRequest, etc.) to
huma_types.go. Update all test files to route through the mux
instead of calling handlers directly, and adjust expected status
codes where Huma validation differs (422 vs 400 for type errors).

Fix ListBranchesInput Repo field to use explode tag for proper
repeated query parameter parsing (?repo=a&repo=b).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The old handleJobOutput streaming mode (stream=1) was not used by the
TUI or CLI -- they use /api/stream/events and /api/job/log instead.
Remove the dead Stream field from the Huma input type.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Enhance TestHumaOpenAPISpec to validate that each path has the
expected HTTP method (GET or POST), not just that the path exists.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use -1 defaults for ID fields (id, job_id, commit_id) so explicit
zero values trigger lookups matching legacy behavior. Use a distinct
sentinel for limit so explicit limit=-1 is treated as unlimited.
Make Stats a pointer with omitempty so single-job responses omit it.

Move /api/job/output back to HandleFunc to preserve stream=1 NDJSON
contract — Huma's typed response model cannot express the streaming
mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@wesm wesm requested a review from mariusvniekerk April 6, 2026 17:50
@roborev-ci
Copy link
Copy Markdown

roborev-ci bot commented Apr 6, 2026

roborev: Combined Review (ddca93f)

Verdict: One medium-severity regression was identified; otherwise the reviewed changes look clean.

Medium

  • Negative query IDs can bypass the intended filtered lookup path
    • Location: internal/daemon/huma_handlers.go around humaListJobs, humaGetReview, and humaListComments; internal/daemon/huma_types.go defaults for ID, JobID, and CommitID
    • Issue: The new sentinel-based presence detection treats any negative ID other than the sentinel as if the parameter was omitted. For example, GET /api/jobs?id=-2 now falls through to the normal listing path and may return unrelated jobs, whereas the previous behavior performed an ID lookup and returned an empty result. The same applies to job_id and commit_id on the review and comments endpoints.
    • Suggested fix: Do not infer query presence from a magic numeric sentinel. Instead, detect whether the raw query key was present, track presence separately, or reject negative IDs explicitly before falling back to the non-ID path.

Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@roborev-ci
Copy link
Copy Markdown

roborev-ci bot commented Apr 6, 2026

roborev: Combined Review (495b823)

Verdict: One medium-severity regression blocks branch filtering in /api/branches; otherwise no medium-or-higher issues were identified.

Medium

  • Broken repo query binding for branch listing
    • Location: internal/daemon/huma_types.go:166, internal/daemon/huma_types.go:177
    • Problem: ListBranchesInput uses query:"repo,explode", but Huma treats the full tag value as the query parameter name rather than parsing explode as an option. As a result, requests like /api/branches?repo=/path do not populate input.Repo, so the branch filter is skipped and unfiltered results are returned.
    • Fix: Change the tag to query:"repo" and add/update a test that verifies the repo filter actually narrows /api/branches results.

Synthesized from 3 reviews (agents: codex, gemini | types: default, security)

@wesm
Copy link
Copy Markdown
Collaborator Author

wesm commented Apr 6, 2026

"The finding is invalid. query:"repo,explode" is the correct Huma syntax for repeated query parameters per https://huma.rocks/features/request-inputs/, and the endpoint is tested."

@wesm wesm merged commit b34b5ab into main Apr 6, 2026
8 checks passed
@wesm wesm deleted the openapi-support branch April 6, 2026 18:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant