Skip to content

Server smoke-test fixes: typed parameters, sequential JSON, undocumented success, external security schemes - #108

Merged
tanmaykm merged 3 commits into
mainfrom
tan/smoketest-fixes
Aug 29, 2026
Merged

Server smoke-test fixes: typed parameters, sequential JSON, undocumented success, external security schemes#108
tanmaykm merged 3 commits into
mainfrom
tan/smoketest-fixes

Conversation

@tanmaykm

Copy link
Copy Markdown
Member

Fixes from the live server-path smoke test that #104 called for before tagging v1.0.0: generated servers ran as real processes serving the classic petstore (driven by both the new generated client and the unmodified openapi-generator 0.2 client on OpenAPI v0.2.8), a purpose-built gap-fixture spec, and the real JuliaHub Job Secrets REST API document. Three commits, one per finding.

1. Typed parameters failed on every request (cbadad4) — bug fix

Server-side, any parameter whose planned Julia type is a generated value struct (string enums above all) was decoded twice: the emitted _typed_scalar/_typed_array helpers construct the typed value, then _finish_parameter re-decoded it, validating the Julia struct itself against its raw JSON schema. Every request carrying such a parameter failed with 400 — petstore's GET /pet/findByStatus was dead on arrival. _finish_parameter now decodes from the encoded wire form.

The same commit fixes buffered sequential-JSON handling: ndjson/json-seq responses can be documented with an array schema covering the whole sequence (planned as a vector type) or with the schema of one record (planned as the item type — Kubernetes-watch style, which the streaming path already supports via _stream_plan). The emitted server response encoder and the buffered client decoder only handled the array form; both now discriminate on the planned type, mirroring _stream_plan.

2. Operations documenting no success response answered 500 (d3649b3) — behavior change

Classic petstore documents no 2xx at all for 7 of its 20 operations (only 4xx entries); generated servers 500'd at response-encoding time after the handler had already run. Per the OAS Responses Object text (identical in 3.0.4/3.1.1/3.2.0), such documents violate only a SHOULD, and response documentation is explicitly non-exhaustive — a server answering with an undocumented success code is spec-consistent (the generated client already tolerates undocumented 2xx). Now:

  • serverplan emits a :missing_success_response warning per affected operation at planning time.
  • The generated server answers a handler's nothing with an empty 200 — the status 0.2-lane clients assert. A typed return value still errors (no documented media to encode against); HTTP.Response passthrough remains for full control.

3. Dangling security-scheme references rejected real documents outright (469e897) — behavior change

The real JuliaHub secrets document names openId/bearerAuth in operation security while declaring no schemes — a common production shape where auth lives in a gateway. The loader failed in strict and permissive mode, making the document unprocessable (the 0.2 lane accepted it). The Security Requirement name rule is a hard MUST, so strict mode still rejects; but the specification's multi-document pattern explicitly endorses a referenced document naming schemes its entry document declares ("treated as an interface for referenced documents to access"). Under strict=false, :unknown_security_scheme is now a warning and the scheme is treated as externally declared: generation excludes it from operation security descriptors (the runtime cannot construct credentials for a scheme it cannot see), a requirement group naming only external schemes becomes an anonymous alternative, and callers supply gateway auth explicitly (e.g. request_headers).

Validation

  • Full package test suite passes with all three commits.
  • New regression coverage: externally-declared-scheme testset in test/semantics.jl (strict rejection, permissive warning, descriptor filtering); the parameter and sequential fixes are exercised by the existing suite plus the live smoke tiers below.
  • Live smoke tiers (session harness, not committed): petstore same-lane 27/27; cross-lane with the unmodified 0.2 petstore client 25/25 (with fix(client): keep form-style CSV separators literal in query strings #107 on release-0.2); gap fixtures (oneOf unions, deepObject/pipeDelimited/enum/header/cookie params, security AND/OR, 204, passthrough, ndjson buffered+streamed) 19/19; the unmodified JuliaHub secrets document generated permissively, implemented, and driven end to end 21/21.

Closes out the server smoke-test item from #104.

…ctly

Smoke-test findings against live generated servers:

- Emitted _finish_parameter re-decoded already-constructed generated value
  types (string enums and other named scalar types), validating the Julia
  struct against its raw JSON schema; every request with such a parameter
  failed with 400. Decode from the encoded wire form instead.
- Sequential JSON media (ndjson, json-seq) can be documented either with an
  array schema covering the whole sequence (planned as a vector type) or
  with the schema of one record (planned as the item type, as the streaming
  path already supports via _stream_plan). The emitted server response
  encoder and the buffered client decoder only handled the array form:
  per-record declarations failed schema validation on both sides, and the
  client would then mis-decode the vector as a single item. Discriminate on
  the planned type and handle both, mirroring _stream_plan.
The OAS Responses Object MUST only contain one response code and merely
SHOULD cover a successful response; common documents (petstore's addPet,
updatePet, and five more) list only error codes. Generated servers
previously answered such operations with a 500 at response-encoding time,
after the handler had already run.

Following the specification's stance that response documentation is
non-exhaustive:

- serverplan now emits a :missing_success_response warning per affected
  operation at planning time, instead of the failure surfacing per-request.
- The emitted _server_response answers a handler's `nothing` with an empty
  200 (matching what 0.2-lane clients expect); a typed return value still
  errors since there is no documented media to encode it against, and
  handlers can return a framework response for full control.
…sively

The Security Requirement Object's names MUST correspond to schemes
declared under Components, and strict mode continues to enforce that.
But the specification's multi-document pattern explicitly supports a
referenced document naming schemes its entry document declares (implicit
connections are resolved from the entry document, 'treated as an
interface for referenced documents to access'). Real service documents
regularly ship this shape with the schemes held by a gateway; the
previous behavior made such documents unprocessable even permissively.

Under strict=false, :unknown_security_scheme is now a warning and the
scheme is treated as externally declared: generation excludes it from
operation security descriptors (the runtime cannot construct credentials
for a scheme it cannot see), leaving a requirement group that named only
external schemes as an anonymous alternative. Callers supply external
auth explicitly, e.g. via request_headers.

Verified live against the JuliaHub Job Secrets REST API document, which
names openId/bearerAuth without declaring them: permissive client and
server generation now succeed and the full lifecycle passes end to end.
@tanmaykm
tanmaykm merged commit ab8b804 into main Aug 29, 2026
3 checks passed
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