feat(server): generate OpenAPI spec with utoipa (#241)#271
feat(server): generate OpenAPI spec with utoipa (#241)#271haseebrabbani wants to merge 1 commit into
Conversation
Integrate utoipa to auto-generate an OpenAPI 3.1 spec from the HTTP handlers and wire models, so API docs stay in sync with the code. - Annotate every HTTP handler (client, dashboard, and feature-gated EVM surfaces) with `#[utoipa::path]` and derive `ToSchema` / `IntoParams` on the request/response/query/model types. - Add `openapi::openapi()` which assembles the document and merges the EVM routes only when the `evm` feature is compiled in. - Serve the spec at `GET /api-docs/openapi.json` (unauthenticated, read-only) and add a `gen-openapi` binary to write it to a file. - Commit the generated `docs/openapi.json` (built with `evm`) and document it in `docs/OPENAPI.md`. 36 operations / 82 schemas. Purely additive: no wire-shape changes, so the Rust/TS clients need no updates. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
WalkthroughThis PR integrates ChangesOpenAPI Spec Generation Integration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR integrates utoipa into the guardian-server crate to generate an OpenAPI 3.1 specification directly from HTTP handlers and wire models, then exposes and documents that spec for downstream tooling (docs, SDK generators).
Changes:
- Adds
#[utoipa::path]annotations to HTTP handlers andToSchema/IntoParamsderives to request/response/query models across client, dashboard, and feature-gated EVM HTTP surfaces. - Introduces a new
crates/server/src/openapi.rsaggregator module plus agen-openapibinary to emit a committeddocs/openapi.json. - Serves the OpenAPI spec at
GET /api-docs/openapi.jsonand documents regeneration/usage underdocs/OPENAPI.md.
Reviewed changes
Copilot reviewed 32 out of 34 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/README.md | Adds links to the OpenAPI documentation/spec artifact. |
| docs/OPENAPI.md | Documents where the spec lives, runtime endpoint, and regeneration command. |
| docs/openapi.json | Adds the generated OpenAPI 3.1 JSON spec (built with evm). |
| crates/shared/src/lib.rs | Derives utoipa::ToSchema for shared signature types used on the wire. |
| crates/shared/Cargo.toml | Adds utoipa dependency to guardian-shared. |
| crates/server/src/state_object.rs | Derives ToSchema and marks state_json as schema-free object. |
| crates/server/src/services/unpause_account.rs | Derives ToSchema for UnpauseResponse. |
| crates/server/src/services/pause_account.rs | Derives ToSchema for PauseResponse. |
| crates/server/src/services/dashboard_pagination.rs | Derives ToSchema for PagedResult<T>. |
| crates/server/src/services/dashboard_info.rs | Derives ToSchema for dashboard info/status response models. |
| crates/server/src/services/dashboard_global_proposals.rs | Derives ToSchema for global proposal feed entries. |
| crates/server/src/services/dashboard_global_deltas.rs | Derives ToSchema for global delta feed entries. |
| crates/server/src/services/dashboard_accounts.rs | Derives ToSchema for dashboard account summary/detail types. |
| crates/server/src/services/dashboard_account_snapshot.rs | Derives ToSchema for snapshot types. |
| crates/server/src/services/dashboard_account_proposals.rs | Derives ToSchema for per-account proposal feed entries. |
| crates/server/src/services/dashboard_account_deltas.rs | Derives ToSchema for per-account delta feed types. |
| crates/server/src/services/dashboard_account_delta_detail.rs | Derives ToSchema for delta detail response type. |
| crates/server/src/services/account_status.rs | Derives ToSchema for AccountStatus. |
| crates/server/src/openapi.rs | Adds OpenAPI document aggregation, error schema, EVM merge, and unit tests. |
| crates/server/src/metadata/network.rs | Derives ToSchema for NetworkConfig and MidenNetworkType. |
| crates/server/src/metadata/auth/mod.rs | Derives ToSchema for Auth enum used in client configure requests. |
| crates/server/src/lib.rs | Exposes the new openapi module. |
| crates/server/src/evm/proposal.rs | Derives ToSchema for EVM proposal models. |
| crates/server/src/delta_summary/mod.rs | Derives ToSchema for dashboard delta metadata and decode projection types. |
| crates/server/src/delta_object.rs | Derives ToSchema for delta objects/status/signatures and schema-free payload. |
| crates/server/src/builder/handle.rs | Serves the generated spec at /api-docs/openapi.json. |
| crates/server/src/bin/gen-openapi.rs | Adds a binary to generate/write the spec JSON. |
| crates/server/src/api/http.rs | Adds utoipa annotations for client HTTP handlers + schemas/params. |
| crates/server/src/api/evm.rs | Adds utoipa annotations for EVM HTTP handlers + schemas/params. |
| crates/server/src/api/dashboard.rs | Adds utoipa annotations for dashboard auth/account/session/pause endpoints. |
| crates/server/src/api/dashboard_feeds.rs | Adds utoipa annotations for dashboard feed endpoints + query params. |
| crates/server/Cargo.toml | Adds utoipa dependency to the server crate. |
| Cargo.toml | Adds workspace utoipa dependency with axum_extras feature. |
| Cargo.lock | Locks utoipa (and transitive updates like itertools). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Issue #241: serve the auto-generated OpenAPI spec. Unauthenticated | ||
| // and read-only — it documents the contract, not data. | ||
| async fn openapi_json() -> axum::Json<utoipa::openapi::OpenApi> { | ||
| axum::Json(crate::openapi::openapi()) | ||
| } |
| /// Wire shape of a Guardian error response body. Mirrors the envelope | ||
| /// produced by [`crate::error::GuardianError`]'s `IntoResponse` impl. | ||
| /// Documented as the body of every non-2xx response. Optional fields | ||
| /// are populated only for the error codes that carry them. |
| [dependencies] | ||
| miden-protocol = { version = "=0.14.5" } | ||
| serde = { workspace = true, features = ["derive"] } | ||
| serde_json = { workspace = true } | ||
| base64 = { workspace = true } | ||
| rand = "0.8" | ||
| hex = { workspace = true } | ||
| prost = { workspace = true } | ||
| utoipa = { workspace = true } |
zeljkoX
left a comment
There was a problem hiding this comment.
Thanks for working on this! Great first contribution.
I have reviewed it and would like to propose few improvements. Please let me know if they make sense to you.
-
Document auth in OpenAPI
- Add security schemes for:
- Signed client headers:
x-pubkey,x-signature,x-timestamp - Cookies:
guardian_operator_session,guardian_evm_session
- Signed client headers:
- Apply
security(...)per operation - Leave challenge/public endpoints unauthenticated
- Add security schemes for:
-
Add missing error responses to utoipa annotations
- Cross-cutting:
429rate limit,413body limit if we want them per-endpoint - Dashboard endpoints: add
404/503gaps for detail/snapshot/feed - Unpause: add
400 - EVM: add
403for signer authorization errors where applicable - Lookup: cover malformed input and storage errors
- Cross-cutting:
-
Add CI spec drift detection
- Regenerate OpenAPI to a temp file
- Diff against
docs/openapi.jsonor against more granular openapi spec files. - Fail CI when stale
-
Generate more granual specs alongside the combined one
docs/openapi.jsondocs/openapi-client.jsondocs/openapi-dashboard.jsondocs/openapi-evm.json
This maps to existing TS clients and reduces unrelated schema exposure for potential SDK generation.
-
Reduce manual endpoint docs
- Review
spec/api.md. Avoid duplicating spec in that document.
- Review
-
Update agent/contributor guidance
- Any change to HTTP handlers, DTOs, query/path params, auth behavior, or feature-gated routes must update utoipa annotations and regenerate the OpenAPI spec files
Summary
Resolves #241. Integrates
utoipato auto-generate an OpenAPI 3.1 specification directly from the HTTP handlers and wire models, so API docs stay in sync with the code (no manual drift).Scope covers both HTTP surfaces — the client API (
tag: client) consumed by SDKs/packages and the operator dashboard API (tag: dashboard) — plus the feature-gated EVM API (tag: evm).Per the task framing, the deliverable is the generated spec file; a bundled Swagger UI was treated as optional and is not included (consumers can point Swagger UI / ReDoc / SDK generators at the spec).
What changed
#[utoipa::path(...)]on all 36 operations acrossapi/http.rs,api/dashboard.rs,api/dashboard_feeds.rs,api/evm.rs(method, path, params, request body, per-status responses);#[derive(ToSchema)]/IntoParamson every request/response/query/model type in the graph (→ 82 component schemas), including the shared signature types.openapimodule with anApiDocOpenApiderive and a sharedApiErrorResponseschema mirroringGuardianError's envelope.openapi::openapi()merges the EVM surface only when theevmfeature is compiled in, so the spec matches the routes actually mounted.GET /api-docs/openapi.json(unauthenticated, read-only); agen-openapibinary writes the spec to a file; the generateddocs/openapi.json(built withevm) is committed and documented indocs/OPENAPI.md.Regenerating
Testing
cargo check(default) and--features evm: clean.cargo clippy --all-targets --all-features -- -D warningson the touched crates: clean.Notes
Purely additive documentation — no wire-shape changes — so the Rust/TS clients need no updates under the contract-change workflow.