v0.7.0
v0.7.0 — generator coverage + richer error typing
v0.7.0 widens what wavefront expresses on both ends of the contract. The
generator bundles a broader range of real FastAPI/OpenAPI surfaces — empty
objects, typed and open dictionaries, and polymorphic unions — and the proxy
stops collapsing every non-success into one envelope: a declared (route, status)
is now a typed, status-preserving contract response. Generator output stays
byte-reproducible — the well-known-type descriptors are embedded in a layer only
when a schema actually uses them.
-
Empty object schemas bundle as zero-field messages. A component that is an
explicitly-empty object ({"type":"object","properties":{}}) — the shape
FastAPI emits for a fieldless model — bundles as a zero-field proto message
instead of being rejected. A bare {"type":"object"} with no properties key is
still a hard error, the open/untyped-object boundary (#118 closed). -
Typed additionalProperties lowers to a proto3 map. A typed dictionary
(additionalProperties: <scalar|$ref>, no declared properties of its own)
lowers to map<string, V> (#119 closed). -
Open objects and untagged unions lower to well-known types. An open object
(additionalProperties: true | {}) lowers to google.protobuf.Struct; an untagged
anyOf/oneOf union or an unconstrained {} schema lowers to google.protobuf.Value
(repeated as array items). google/protobuf/struct.proto is embedded in the
layer only when used, so bundles that need neither stay byte-identical. This
types FastAPI's HTTPValidationError.loc: list[str | int] (#121). -
Discriminated unions lower to Struct. A tagged anyOf/oneOf (one carrying a
discriminator) serializes flattened — the discriminator is a sibling property
and the member's fields sit at the top level — which a proto3 oneof cannot
carry (protojson encodes a oneof wrapped under the member key). It lowers to
google.protobuf.Struct, which relays the object verbatim (#129 closed). -
Upstream-origin status codes and typed error bodies. wavefront no longer
collapses every non-success to a fixed wavefront.v0.Error envelope. A declared
(route, status) is a first-class typed contract response: the upstream status
is preserved and no X-Wavefront-Error header is set. Undeclared statuses fall
to the graceful aid envelope. wavefront honors whatever status the upstream
sends except a hard capability ceiling — 206/207/208/226 and any 3xx map to
502. A per-route strict: true flips the undeclared-status default to a hard
502. resolution.yaml field transforms (rename/default/optionalize/coerce) fire
per (status, message) pair, not only on 2xx (#53 closed). -
fix: accept empty object schemas as zero-field messages (#122)
-
feat: lower a typed-dict additionalProperties to map<string,V> (#123)
-
feat: bind per-status error_messages and strict in the bundle loader (#124)
-
feat: collect and bind declared error response types in the generator (#125)
-
feat: honor upstream status, type declared errors, relay the rest (#126)
-
feat: apply field transforms per declared error status (#127)
-
test: exercise per-status error transforms across a version chain (#128)
-
feat: lower untagged unions and open objects to well-known types (#130)
-
feat: lower discriminated unions to google.protobuf.Struct (#131)