# Changelog
All notable changes are recorded here. This project follows semantic versioning,
with one pre-1.0 qualification: a minor release may change generated Rust APIs
when correcting output that was wrong or incomplete on the wire.
## [Unreleased]
## [0.12.0] - 2026-07-29
This release broadens the set of real-world protocols that generated clients
and servers can represent, and replaces the old inline SSE helpers with a
reusable typed transport. Regenerated clients may have new request/response
types, a new `ApiError::raw_body` field, and newer HTTP dependencies; review
generated-code diffs when upgrading.
### Added
- SSE-enabled output now includes a standalone `sse.rs` transport with
`SseClient`, raw `SseEvent<String>` streams, typed JSON `SseEvent<T>` streams,
and the backwards-compatible payload-only stream. Event name, ID, and
server-provided `retry:` delay remain available to callers.
- SSE streams can reconnect with bounded exponential backoff, honor the
server's `retry:` value, and send the most recently observed event ID as
`Last-Event-ID`. HTTP 429, 5xx, connection failures, and early EOF are
retryable; invalid content types and other terminal errors are not. The
generated runtime was exercised against live OpenAI- and
Anthropic-compatible streaming endpoints.
- Flat `multipart/form-data` object schemas generate typed reqwest clients and
Axum extractors, including required and optional binary/scalar fields,
configured body limits, validation, and deterministic rejection of shapes
the generator cannot encode symmetrically.
- Generated clients and servers support bounded binary and text request bodies,
including `application/octet-stream`, `application/pdf`, `text/plain`, XML,
and `application/jwt`. Non-JSON responses preserve exact bytes, and
`ApiError<E>::raw_body` exposes the unmodified response alongside its lossy
text rendering.
- Buffered client responses and SSE error responses have an 8 MiB default
limit, configurable through `http_client.max_response_body_bytes` and the
generated runtime builders. Oversized bodies return `ResponseTooLarge`
without buffering beyond the limit.
- Component-level Request Body Object references are resolved during operation
analysis, so `requestBody: { $ref: ... }` participates in normal client and
server generation.
- The checked-in corpus now includes Storyden, and the documentation includes a
dated Progenitor workflow comparison with a reproducible compile benchmark.
### Changed
- Generated HTTP dependencies now target `reqwest` 0.13,
`reqwest-middleware` 0.5, `reqwest-retry` 0.9, `reqwest-tracing` 0.7, and
`thiserror` 2. Required reqwest and middleware features are inferred from the
selected operations, including query, form, multipart, streaming, and JSON
usage; rustls builds use reqwest 0.13's `rustls` feature.
- AWS query-protocol operations can use bounded nested object/array form
encodings, while simple array headers and path parameters with literal
prefixes or suffixes now have matching typed client/server serialization.
- Text and binary response media produce `String` and `bytes::Bytes` values
instead of being forced through JSON or lossy UTF-8 conversion. Generated
server response variants retain their declared media type.
- The real-world corpus contains 56 documents: 55 supported OpenAPI specs and
one intentionally skipped Swagger 2.0 Gitea document. The ordinary full tier
compiles 54 and reports Microsoft Graph as generate-only because its generated
crate exceeds CI memory; `SPEC_COMPILE_FORCE_CHECK=1` enables local
compile-verification on larger machines.
### Fixed
- Bodyless operations that declare request-content semantics send
`Content-Length: 0`; ordinary methods without content semantics remain
unchanged, and optional bodies add the header only when absent.
- Media selection recognizes PDF as binary and XML, `+xml`, and JWT as text,
prefers schema-bearing vendor JSON over schema-less canonical JSON, and
rejects wildcard or proprietary request media instead of emitting an invalid
`Content-Type`.
- Recursive annotation-only `allOf` references are aliases again, avoiding
expansion overflows, and generated server code consistently uses canonical
Rust model names while avoiding response-enum name collisions.
- Spec parsing tolerates literal tabs in YAML block-scalar prose and ignores
extension scalars parked inside `paths`. AWS route fragments are stripped and
synthetic webhook paths receive a leading slash.
- Server-side validation normalizes common Java POSIX, ECMA Unicode, and legacy
octal regex syntax; unsupported look-around/backreference patterns no longer
abort generation. Component keys that resemble JSON Schema keywords are
namespaced in generated validation bundles.
- Portable scratch directories and complete generated dependency fragments
keep the expanded corpus and packaged examples compiling on clean CI runners.
## [0.11.0] - 2026-07-27
Nearly everything here was found by generating a client from RunPod's published
OpenAPI document and exercising it against the live API. The spec was accurate;
the generator was not. Two of these defects broke real calls outright, and both
would have passed any amount of spec-diffing.
### Changed
- `format: float` now maps to `f64` instead of `f32`. JSON carries no binary32,
so the declared format describes the server's storage rather than the
transport: a value sent as `0.03` survives in `f64` but becomes
`0.029999999329447746` through `f32`, which matters when the field is money.
Set `float_precision = "f32"` under `[generator.types]` to map strictly by
declared format. `--types-conservative` keeps the literal `f32` mapping.
### Fixed
- Parameter-level inline enums honor `x-enum-varnames`. Schema-level enums
already did, so the same enum produced different Rust variant names depending
on whether it lived in `components.schemas` or on a parameter. A varnames
array whose length disagrees with `enum` is ignored rather than applied to a
prefix.
- Properties that are both `required` and nullable via OpenAPI 3.1's
`type: ["X", "null"]` now generate `Option<T>` instead of a bare `T`, in plain
object schemas and in `allOf`-composed ones alike. Previously such a client
compiled and then failed to deserialize the first real response containing
`null`. All three nullability spellings (`nullable: true`, the 3.1 type array,
and an `anyOf`/`oneOf` null branch) now route through one helper.
- Client operations whose only success content is `text/event-stream` return a
`futures_util::Stream` of bytes instead of `()`. They previously buffered the
response with `.text()`, which never returns on a live SSE stream and hung the
caller's task indefinitely.
- Generated clients default `base_url` to the document's `servers[0].url` when
configuration does not set one, so `HttpClient::new()` targets the real API
instead of an empty string. Explicit configuration still wins; relative and
templated server URLs are ignored.
- The `Default(..)` per-operation error variant is now constructed for responses
matched by the spec's `default` response. It was previously declared but
unreachable, so a typed `default` body still surfaced as `typed: None`.
- Specs with `multipart/form-data` operations now request reqwest's `multipart`
feature in `REQUIRED_DEPS.toml`. The feature was enabled for
`reqwest-middleware` but not for `reqwest` itself, so generated file-upload
clients failed to compile.
### Internal
- The `full-spec-compile` CI tier passes again. It had been killed with SIGTERM
roughly 25 minutes into a 240-minute budget, on `main` as well as branches.
The cause was memory, not time or disk: `microsoft-graph` generates 2.4M lines
from 16,153 operations and peaks at ~14.3 GB in a single rustc process against
a 16 GB runner. It is now generated but not compile-checked, reported in its
own bucket so a green run is never mistaken for full corpus verification.
`SPEC_COMPILE_FORCE_CHECK=1` checks it where there is headroom.
## [0.10.0] - 2026-07-26
### Added
- Every-PR compatibility coverage for the generated Anthropic Messages server
through the pinned official Python SDK, including unary and SSE responses.
### Changed
- Regenerated server response enums now use the declared status in bodyless and
SSE variant names and require a runtime status for wildcard/default variants.
This is a source-breaking correction for existing server trait implementations.
### Fixed
- Config-driven `server list` and `server add` now apply
`generator.schema_extensions`, so overlay-provided operations and SSE media
types match generation.
- Schema extensions accept the documented JSON, YAML, and YML formats with
path-rich parse errors.
- Generated server response enums retain reusable Response Object references,
including structurally compatible local refs stored outside
`components.responses`, plus bodyless status codes, vendor/problem JSON media
types, SSE status codes, and runtime status values for wildcard/default
responses.
- Server generation rejects response sets that contain only unsupported media
types and reports normalized Rust identifier collisions between distinct tags.
- Server example tests use Cargo's current integration-test binary instead of
a potentially stale hard-coded `target/debug` executable.
## [0.9.1] - 2026-07-26
### Fixed
- Restored client generation for operations whose selected JSON or form request
content declares no schema. These operations keep their historical no-body
client signature, while server generation fails with an actionable error
because there is no request contract to validate.
## [0.9.0] - 2026-07-26
### Added
- Default-on request validation for generated Axum servers, compiled offline
from the selected OpenAPI/JSON Schema contract with bounded body and error
limits.
- Sanitized `application/problem+json` responses for malformed input (`400`),
oversized bodies (`413`), undeclared media types (`415`), schema violations
(`422`), and generated contract mismatches (`500`).
- Typed validation for supported path, query, header, cookie, JSON, and
form-urlencoded inputs, plus lazy `ApiError::problem_details()` decoding in
generated clients without replacing documented typed errors.
- Live generated-client/server and independent-client compatibility tests that
verify status codes, stable JSON Pointer locations, redaction, deterministic
error caps, and handler isolation.
### Changed
- Generated servers and exact dependency fragments now target Axum 0.8 and its
`{parameter}` route syntax consistently. Trait implementations use the direct
`async-trait` dependency because Axum 0.8 no longer re-exports the attribute
macro (#38).
- Server request constraints now use `jsonschema` 0.49 with remote file/HTTP
resolution disabled. Model types remain free of validation derives.
- Unsupported aggregate parameter encodings and selected multipart, text, or
octet-stream server bodies fail generation explicitly instead of being
silently omitted.
### Fixed
- OpenAPI schema serialization now omits absent optional keywords while
preserving an explicit `const: null`, preventing missing keywords from
becoming unintended null constraints or otherwise disabling validation.
- Vendor JSON media types are retained end to end, and generated servers match
the media type selected from the operation rather than accepting every
`application/*+json` body.
## [0.8.0] - 2026-07-19
### Added
- An in-browser WASM playground at
[openapi-to-rust.dev/playground](https://openapi-to-rust.dev/playground):
paste a spec or fetch one by URL and get the exact generated file set —
byte-identical to `openapi-to-rust generate <SOURCE>` — with a downloadable
runnable crate.
- A default-on `cli` feature gating clap and reqwest. With
`--no-default-features` the library compiles on `wasm32-unknown-unknown`;
URL policy and spec parsing moved into the shared `spec_source` module.
### Fixed
- `ApiError` display output now bounds large response-body previews and includes
typed error details or typed-body parse failures when available (#29).
## [0.7.0] - 2026-07-17
### Added
- Direct generation from a local OpenAPI document or bounded HTTPS URL:
`openapi-to-rust generate <SOURCE>`.
- `openapi-to-rust init <SOURCE>`, plus deterministic `--dry-run`, `--check`,
`--quiet`, and `--json` generation modes.
- Optional `[client].operations` selection and model pruning shared with the
server operation scope.
- `Default` for all-optional request models, required-field constructors,
fluent optional setters, and opt-in operation builders.
- A complete `REQUIRED_DEPS.toml` for the exact generated output.
- `base64_url_unpadded` as a spec-wide `format: byte` strategy for RFC 7515
URL-safe, unpadded data.
- Contributor, support, security, conduct, issue-form, and pull-request
scaffolding, plus a docs.rs library overview and compile-checked example.
- The public CLI as Cargo's default binary, so plain `cargo run -- ...` works
even though feature-gated internal maintenance binaries are declared.
### Fixed
- Array items with an inline string enum now generate a named enum
(`{Parent}Item`) instead of collapsing to `Vec<String>`, including
`anyOf`-nullable arrays and typeless OpenAPI 3.1 enums (#33).
- README compatibility, corpus, and conformance claims; pull-request and
scheduled full-corpus CI tiers; and release preflight checks.
- Canonical `[generator.types]` configuration parsing, strict unknown-field
rejection, config-relative paths, and actionable migration errors.
- `cargo install --locked openapi-to-rust` packaging: only the public CLI is
installed, packaged inputs are complete, and obsolete duplicate dependency
versions were removed.
- Server query extraction now mirrors generated client serialization for typed
form, repeated-array, comma-delimited, and deep-object query parameters.
- Generated client requests now support non-JSON bodies, optional bodies,
typed headers, path encoding, and collision-safe operation signatures.
## [0.6.0] - 2026-07-13
### Added
- OpenAPI `style`/`explode`-aware client serialization for object and array
query parameters, including form-exploded objects, comma-joined form values,
deep-object parameters, and repeated arrays.
- Shared-target full-corpus compile tooling in `scripts/spec-compile.sh`.
### Changed
- Regenerated client signatures use typed objects and arrays instead of opaque
`Option<impl AsRef<str>>` arguments for the supported query styles. This is a
source-breaking correction for regenerated pre-1.0 clients.
## [0.5.3] - 2026-07-11
- Added working generated serde codecs for `time::Date` and `time::Time`.
## [0.5.2] - 2026-07-11
- Honored integer and number formats for query and path parameters.
## [0.5.1] - 2026-07-07
- Restricted the crates.io package to the source, manifest, README, and license.
## [0.5.0] - 2026-07-07
### Added
- Opt-in Axum server generation with operation selectors, per-tag traits,
typed response enums, router factories, SSE response support, and model
pruning.
- OpenAPI 3.1 modeling and experimental parsing for selected OpenAPI 3.2
fields and methods.
- Typed scalar strategies, typed `additionalProperties`, operation-level typed
errors, strict extension parsing, webhook ingestion, and SSE auto-detection.
- End-to-end OpenAI Responses and Anthropic Messages server examples.
### Fixed
- Numerous real-spec generation failures involving operation identifiers,
signed enum values, recursive unions, parameter collisions, optional request
bodies, range response codes, and path-segment encoding.
[Unreleased]: https://github.com/gpu-cli/openapi-to-rust/compare/v0.12.0...HEAD
[0.12.0]: https://github.com/gpu-cli/openapi-to-rust/compare/v0.11.0...v0.12.0
[0.11.0]: https://github.com/gpu-cli/openapi-to-rust/compare/v0.10.0...v0.11.0
[0.10.0]: https://github.com/gpu-cli/openapi-to-rust/compare/v0.9.1...v0.10.0
[0.9.1]: https://github.com/gpu-cli/openapi-to-rust/compare/v0.9.0...v0.9.1
[0.9.0]: https://github.com/gpu-cli/openapi-to-rust/compare/v0.8.0...v0.9.0
[0.8.0]: https://github.com/gpu-cli/openapi-to-rust/compare/v0.7.0...v0.8.0
[0.7.0]: https://github.com/gpu-cli/openapi-to-rust/compare/v0.6.0...v0.7.0
[0.6.0]: https://github.com/gpu-cli/openapi-to-rust/releases/tag/v0.6.0
[0.5.3]: https://github.com/gpu-cli/openapi-to-rust/compare/v0.5.2...v0.5.3
[0.5.2]: https://github.com/gpu-cli/openapi-to-rust/compare/v0.5.1...v0.5.2
[0.5.1]: https://github.com/gpu-cli/openapi-to-rust/compare/v0.5.0...v0.5.1
[0.5.0]: https://github.com/gpu-cli/openapi-to-rust/tree/v0.5.0