Skip to content

OpenAPI 3.1 / 3.2 Conformance: master tracking issue #14

@lightsofapollo

Description

@lightsofapollo

OpenAPI 3.1 / 3.2 Conformance — Master Tracking Issue

This is the single source-of-truth issue for getting the generator to honestly support OpenAPI 3.1 and 3.2. We will comment on this issue as work progresses rather than filing 50+ child issues.

Background

Six parallel audit agents reviewed the codebase against the OpenAPI 3.1.2 (2025-09-19) and OpenAPI 3.2.0 (2025-09-19) specs. Reports live under tmp/openapi-specs/reports/ (and 00-SUMMARY.md consolidates).

Headline finding: the README claims OpenAPI 3.1 support; in practice the generator is OpenAPI 3.0-shaped with a thin 3.1 veneer. A 3.1- or 3.2-only spec parses without error and silently drops most semantics. Architectural root cause: every parsing struct ends with #[serde(flatten)] extra: BTreeMap<String, Value> and there is no deny_unknown_fields anywhere.

Conformance harness

The repo now contains a self-validating conformance harness:

  • tests/conformance/specs/ — committed copies of OAS 3.1.2 and 3.2.0 markdown.
  • tests/conformance/catalog.yaml — generated from the 3.2.0 spec by cargo run --bin catalog-gen. 30 OAS Objects, 141 fields, 57 JSON Schema 2020-12 keywords, 7 parameter-style combos. This is the denominator for "100% coverage".
  • tests/conformance/fixtures/ — atomic fixtures, each tagged with coverage: entries from the catalog and a fails_at: L0|L1|L3|... marker. The harness (tests/conformance.rs) only enforces ACTIVE_LAYERS; later layers light up as they are implemented.
  • tests/conformance/external/json-schema-test-suite/ — git submodule of the canonical JSON Schema 2020-12 corpus. Run via tests/conformance_json_schema.rs.
  • tests/conformance/external/apis-guru-sync.sh — lazy-clones the APIs.guru openapi-directory for nightly real-world smoke (APIS_GURU_SMOKE=1).
  • tests/conformance/status.toml — honest support claims, derived from harness results. README will pull from this.

Beads — units of independently-mergeable work

All 51 beads + 4 epics are described in tests/conformance/beads.yaml. The tables below are a rendered view; edit beads.yaml as the source of truth.

Parallelization rule: two beads may run concurrently iff their files sets are disjoint AND neither is in the other's depends_on closure.

Phase 0

ID Title Area Files Depends on
[ ] F1 Add #[serde(deny_unknown_fields)] across spec structs + version validator foundation src/openapi.rs src/cli.rs
[ ] F2 Schema enum supports type as array (3.1 canonical nullability) schema src/openapi.rs src/analysis.rs F1
[ ] F3 Reference Object as sum type for non-Schema reusable objects refs src/openapi.rs src/analysis.rs F1
[ ] F4 Accept paths-less specs (components-only and webhooks-only) components src/analysis.rs F1

Phase 1

ID Title Area Files Depends on
[ ] T1 Wire header request parameters through codegen codegen src/client_generator.rs src/analysis.rs F1
[ ] T2 Emit operations for options/head/patch/trace HTTP methods codegen src/client_generator.rs src/registry_generator.rs F1
[ ] T3 Honor auth_config ApiKey + Custom variants security src/client_generator.rs src/config.rs README.md F1
[ ] T4 Walk webhooks: in analysis webhooks src/openapi.rs src/analysis.rs src/client_generator.rs F1, F3
[ ] T5 Path templating percent-encoding codegen src/client_generator.rs F1
[ ] T6 Detect operationId collisions codegen src/analysis.rs F1
[ ] T7 Handle non-JSON success response bodies bodies src/analysis.rs src/client_generator.rs F1
[ ] T8 Wire range status codes (2XX/4XX/5XX) bodies src/client_generator.rs src/analysis.rs F1
[ ] T9 Model Response Header object (typed response headers) bodies src/openapi.rs src/client_generator.rs F1, F3
[ ] T10 Resolve $ref-typed parameter types refs src/client_generator.rs src/analysis.rs F1, F3
[ ] T11 requestBody required:false → Option bodies src/client_generator.rs src/analysis.rs F1
[ ] T12 additionalProperties: → BTreeMap<String, T> schema src/analysis.rs F1
[ ] T13 Surface description/summary/deprecated/tags into rustdoc + module structure codegen src/client_generator.rs src/registry_generator.rs F1
[ ] T14 Implement parameter style/explode matrix (RFC6570) paths src/openapi.rs src/analysis.rs src/client_generator.rs F1
[ ] T15 SSE streaming auto-detection from text/event-stream responses bodies src/streaming.rs src/analysis.rs F1

Phase 2

ID Title Area Files Depends on
[ ] H1 Model Server Object + Server Variable + multi-server runtime security src/openapi.rs src/client_generator.rs src/cli.rs F1
[ ] H2 Model SecurityScheme (apiKey/http/oauth2/openIdConnect/mutualTLS) security src/openapi.rs src/client_generator.rs src/streaming.rs F1, T3
[ ] H3 Model SecurityRequirement (AND/OR + per-op + empty) security src/openapi.rs src/client_generator.rs H2
[ ] H4 Model Encoding Object (multipart + form-urlencoded) bodies src/openapi.rs src/client_generator.rs F1
[ ] H5 Model Header Object as request and response bodies src/openapi.rs F1, F3
[ ] H6 Model Example Object (object map; remove deprecated singular example) bodies src/openapi.rs F1, F3
[ ] H7 Model Link Object + runtime expressions components src/openapi.rs F1, F3
[ ] H8 Model Callback Object components src/openapi.rs src/analysis.rs F1, F3, T4
[ ] H9 Model Tag Object + tag-based module organization tags src/openapi.rs src/client_generator.rs src/analysis.rs F1, T13
[ ] H10 Model ExternalDocs components src/openapi.rs F1
[ ] H11 Path Item $ref + components/pathItems bucket components src/openapi.rs src/analysis.rs F1, F3
[ ] H12 Discriminator allOf-parent polymorphism + not keyword schema src/openapi.rs src/analysis.rs F1

Phase 2b

ID Title Area Files Depends on
[ ] J1 $dynamicRef / $dynamicAnchor (replace $recursiveRef) schema src/openapi.rs src/analysis.rs F1
[ ] J2 $defs enumeration in extract_schemas schema src/analysis.rs F1
[ ] J3 Validation keywords as runtime checks (validator crate) schema src/openapi.rs src/generator.rs F1
[ ] J4 prefixItems (tuple types) schema src/openapi.rs src/analysis.rs F1
[ ] J5 patternProperties + propertyNames schema src/openapi.rs src/analysis.rs F1
[ ] J6 unevaluatedProperties / unevaluatedItems schema src/openapi.rs src/analysis.rs F1
[ ] J7 dependentSchemas / dependentRequired schema src/openapi.rs src/analysis.rs F1
[ ] J8 contains / minContains / maxContains; contentEncoding/MediaType/Schema schema src/openapi.rs src/analysis.rs F1
[ ] J9 format coverage: date-time, uuid, byte, binary, email, uri schema src/analysis.rs F1
[ ] J10 jsonSchemaDialect at root; remove 3.0 nullable schema src/openapi.rs src/analysis.rs F1, F2

Phase 3

ID Title Area Files Depends on
[ ] D1 PathItem.additionalOperations + query method paths src/openapi.rs src/analysis.rs src/client_generator.rs F1, T2
[ ] D2 Parameter in: querystring paths src/openapi.rs src/analysis.rs src/client_generator.rs F1
[ ] D3 MediaType.itemSchema / prefixEncoding / itemEncoding bodies src/openapi.rs src/analysis.rs src/client_generator.rs F1, H4
[ ] D4 OAuth deviceAuthorization flow + oauth2MetadataUrl security src/openapi.rs F1, H2
[ ] D5 Tag.kind / parent / summary tags src/openapi.rs src/client_generator.rs F1, H9
[ ] D6 $self keyword + Appendix F/G base URI rules refs src/openapi.rs src/analysis.rs F1
[ ] D7 Components.mediaTypes bucket components src/openapi.rs src/analysis.rs F1
[ ] D8 Server.name field security src/openapi.rs F1, H1
[ ] D9 Discriminator.defaultMapping schema src/openapi.rs src/analysis.rs F1, H12
[ ] D10 SecurityScheme.deprecated security src/openapi.rs src/client_generator.rs F1, H2

Parallel-execution batches

Beads grouped by dependency depth. Within a depth tier, beads with disjoint file sets can be worked in parallel; beads sharing files must serialize.

Tier 0

  • Batch 0.1: F1 (touches src/cli.rs, src/openapi.rs)

Tier 1

  • Batch 1.1: F2, T2 (touches src/analysis.rs, src/client_generator.rs, src/openapi.rs, src/registry_generator.rs)
  • Batch 1.2: F3, T3 (touches README.md, src/analysis.rs, src/client_generator.rs, src/config.rs, src/openapi.rs)
  • Batch 1.3: F4, T5, H10 (touches src/analysis.rs, src/client_generator.rs, src/openapi.rs)
  • Batch 1.4: T1, J3 (touches src/analysis.rs, src/client_generator.rs, src/generator.rs, src/openapi.rs)
  • Batch 1.5: T6, T13 (touches src/analysis.rs, src/client_generator.rs, src/registry_generator.rs)
  • Batch 1.6: T7 (touches src/analysis.rs, src/client_generator.rs)
  • Batch 1.7: T8 (touches src/analysis.rs, src/client_generator.rs)
  • Batch 1.8: T11 (touches src/analysis.rs, src/client_generator.rs)
  • Batch 1.9: T12, H1 (touches src/analysis.rs, src/cli.rs, src/client_generator.rs, src/openapi.rs)
  • Batch 1.10: T14 (touches src/analysis.rs, src/client_generator.rs, src/openapi.rs)
  • Batch 1.11: T15, H4 (touches src/analysis.rs, src/client_generator.rs, src/openapi.rs, src/streaming.rs)
  • Batch 1.12: H12 (touches src/analysis.rs, src/openapi.rs)
  • Batch 1.13: J1 (touches src/analysis.rs, src/openapi.rs)
  • Batch 1.14: J2 (touches src/analysis.rs)
  • Batch 1.15: J4 (touches src/analysis.rs, src/openapi.rs)
  • Batch 1.16: J5 (touches src/analysis.rs, src/openapi.rs)
  • Batch 1.17: J6 (touches src/analysis.rs, src/openapi.rs)
  • Batch 1.18: J7 (touches src/analysis.rs, src/openapi.rs)
  • Batch 1.19: J8 (touches src/analysis.rs, src/openapi.rs)
  • Batch 1.20: J9 (touches src/analysis.rs)
  • Batch 1.21: D2 (touches src/analysis.rs, src/client_generator.rs, src/openapi.rs)
  • Batch 1.22: D6 (touches src/analysis.rs, src/openapi.rs)
  • Batch 1.23: D7 (touches src/analysis.rs, src/openapi.rs)

Tier 2

  • Batch 2.1: T4 (touches src/analysis.rs, src/client_generator.rs, src/openapi.rs)
  • Batch 2.2: T9 (touches src/client_generator.rs, src/openapi.rs)
  • Batch 2.3: T10, H5 (touches src/analysis.rs, src/client_generator.rs, src/openapi.rs)
  • Batch 2.4: H2 (touches src/client_generator.rs, src/openapi.rs, src/streaming.rs)
  • Batch 2.5: H6 (touches src/openapi.rs)
  • Batch 2.6: H7 (touches src/openapi.rs)
  • Batch 2.7: H9 (touches src/analysis.rs, src/client_generator.rs, src/openapi.rs)
  • Batch 2.8: H11 (touches src/analysis.rs, src/openapi.rs)
  • Batch 2.9: J10 (touches src/analysis.rs, src/openapi.rs)
  • Batch 2.10: D1 (touches src/analysis.rs, src/client_generator.rs, src/openapi.rs)
  • Batch 2.11: D3 (touches src/analysis.rs, src/client_generator.rs, src/openapi.rs)
  • Batch 2.12: D8 (touches src/openapi.rs)
  • Batch 2.13: D9 (touches src/analysis.rs, src/openapi.rs)

Tier 3

  • Batch 3.1: H3 (touches src/client_generator.rs, src/openapi.rs)
  • Batch 3.2: H8 (touches src/analysis.rs, src/openapi.rs)
  • Batch 3.3: D4 (touches src/openapi.rs)
  • Batch 3.4: D5 (touches src/client_generator.rs, src/openapi.rs)
  • Batch 3.5: D10 (touches src/client_generator.rs, src/openapi.rs)

How we'll work

  1. Phase 0 lands first as a single PR (or as F1, F2, F3, F4 in sequence). Without deny_unknown_fields, every later fix is unverifiable.
  2. Each subsequent bead is a focused PR, scoped to its files set, with a conformance fixture flipping from fails_at: failing to passing.
  3. Progress is tracked in this issue's comments: one comment per merged bead with the bead ID, PR link, and which status.toml entries flipped.
  4. We don't stage 50 child issues — the granularity lives in beads.yaml and PR titles. This issue is the dashboard.
  5. Honesty gate: tests/conformance/status.toml is regenerated by the harness; the README's support claims will be derived from it. Drift fails CI.

References

  • Audit reports: tmp/openapi-specs/reports/00-SUMMARY.md and per-area files (01-schema, 02-paths-parameters, 03-bodies-media, 04-servers-security, 05-components-refs-webhooks, 06-three-two-deltas).
  • Spec: tests/conformance/specs/openapi-3.2.0.md, openapi-3.1.2.md.
  • Catalog: tests/conformance/catalog.yaml.
  • Beads source-of-truth: tests/conformance/beads.yaml.

Metadata

Metadata

Assignees

No one assigned

    Labels

    epicTracking issue for a phase or initiative

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions