Skip to content

feat: add OpenAPI 3.2 support#479

Open
aaronlippold wants to merge 4 commits into
ahx:mainfrom
aaronlippold:feat/openapi-3.2-support
Open

feat: add OpenAPI 3.2 support#479
aaronlippold wants to merge 4 commits into
ahx:mainfrom
aaronlippold:feat/openapi-3.2-support

Conversation

@aaronlippold
Copy link
Copy Markdown

@aaronlippold aaronlippold commented May 26, 2026

Summary

OpenAPI 3.2.0 support — version acceptance, additionalOperations routing, and rebased on v3.4.3.

Version acceptance

OAS 3.2.0 uses the same JSON Schema dialect as 3.1 (https://spec.openapis.org/oas/3.1/dialect/base). The version regex in Builder#detect_meta_schema now accepts 3.2.x versions and routes them through the existing 3.1 codepath.

additionalOperations support

OAS 3.2.0 adds additionalOperations to the Path Item Object for non-standard HTTP methods (e.g. COPY, LINK). Builder#router now iterates additionalOperations after the standard REQUEST_METHODS loop, registering each operation through a shared register_operation helper extracted from the existing loop (DRY refactor).

Other changes

  • bin/setup: added git submodule update --init --recursive for test fixture setup
  • README: fixed "Openapi" → "OpenAPI" capitalization
  • CHANGELOG: accurate scope with spec references

Verified against the published specification

All changes verified against the published spec at spec.openapis.org/oas/v3.2.0.html. The GitHub release notes describe the full 3.2 line roadmap — some features listed there (discriminator.defaultMapping, multipart itemSchema) are not in the 3.2.0 publication. See comment for the complete 3.2.0 field audit.

Companion PR

json_schemer PR #230 adds all 3.2.0 structural fields to the document meta-schema, so openapi.valid? passes for 3.2.0 documents.

Test plan

  • 570 examples, 0 failures, 100% line + branch coverage
  • 3 new tests for additionalOperations (COPY routed, GET unaffected, undefined LINK rejected)
  • 1 test for 3.2.0 document parsing
  • Rebased on v3.4.3 — includes upstream schema? safe navigation fix
  • No regressions on existing behavior

Fixes #469

@aaronlippold aaronlippold requested a review from ahx as a code owner May 26, 2026 13:14
Copilot AI review requested due to automatic review settings May 26, 2026 13:14
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds OpenAPI 3.2 support by treating 3.2 documents as using the same JSON Schema dialect handling as OpenAPI 3.1, and updates tests/docs accordingly.

Changes:

  • Extend meta-schema/dialect detection to accept openapi: 3.2.x
  • Add a spec asserting a 3.2.0 document parses successfully
  • Update README + changelog to document 3.2 support

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
spec/definition_spec.rb Adds coverage verifying a minimal OpenAPI 3.2 document parses and exposes expected properties
lib/openapi_first/builder.rb Expands version matching so 3.2 uses the OpenAPI 3.1 JSON Schema dialect path
README.md Documents support for OpenAPI 3.2
CHANGELOG.md Notes the new OpenAPI 3.2 support and references the motivating issue

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

version = document['openapi']
case version
when /\A3\.1\.\d+\z/
when /\A3\.[12]\.\d+\z/
Comment thread README.md Outdated
# openapi_first

openapi_first is a Ruby gem for request / response validation and contract-testing against an [OpenAPI](https://www.openapis.org/) 3.0 or 3.1 Openapi API description (OAD). It makes an APIFirst workflow easy and reliable.
openapi_first is a Ruby gem for request / response validation and contract-testing against an [OpenAPI](https://www.openapis.org/) 3.0, 3.1, or 3.2 Openapi API description (OAD). It makes an APIFirst workflow easy and reliable.
Comment thread CHANGELOG.md Outdated

## Unreleased

- Add OpenAPI 3.2 support. OAS 3.2 uses the same JSON Schema dialect as 3.1 (no breaking changes), so the 3.1 codepath handles it correctly. Fixes #469.
@ahx
Copy link
Copy Markdown
Owner

ahx commented May 26, 2026

Hey @aaronlippold, thanks for looking into this. I was always struggling a bit with OAS 3.2, because I did not really understand what changes are included and what openapi_first needs to implement in order to support it. Here are some things from the release page where I think we need to do something:

  1. discriminator and the new field defaultMapping – Does that just work?
  2. "Additions to support multipart media types"
    2.1 New itemSchema field
    2.2 New fields prefixEncoding and itemEncoding
  3. Support for additional HTTP methods – Under an additionalOperations entry in a Path, use any other methods not listed as keys using the correct capitalization, e.g. LINK. Do NOT add HEAD under this, use the existing sibling head.

I have listed these points in the related issue as well.

@aaronlippold
Copy link
Copy Markdown
Author

aaronlippold commented May 26, 2026 via email

OpenAPI 3.2.0 uses the same JSON Schema dialect as 3.1 — no breaking
changes, only additive features (structured tags, streaming, OAuth
device flow). The version regex in Builder#detect_meta_schema now
accepts 3.2.x versions and routes them through the existing 3.1
codepath.

Fixes ahx#469

Authored by: Aaron Lippold<lippold@gmail.com>
bin/setup runs bundle install but doesn't initialize the
spec/data/train-travel-api submodule. Developers cloning the repo
and running bin/setup then bundle exec rake see 6 test failures
from missing fixture files. Adding git submodule update --init
--recursive to bin/setup prevents this.

Authored by: Aaron Lippold<lippold@gmail.com>
Process operations defined under path_item.additionalOperations
(OAS 3.2.0 field for non-standard HTTP methods like COPY, LINK).

Extract register_operation helper from the REQUEST_METHODS loop
to share logic between standard methods and additionalOperations.
Method keys from additionalOperations are downcased to match the
router's internal UPPERCASE convention (router.route_at upcases).

3 tests: COPY method routed, GET still works, undefined LINK rejected.
570 examples, 0 failures, 100% line + branch coverage.

Authored by: Aaron Lippold<lippold@gmail.com>
@aaronlippold aaronlippold force-pushed the feat/openapi-3.2-support branch from d3b5a4d to 090fecb Compare June 3, 2026 16:03
- Fix "Openapi" → "OpenAPI" in README (Copilot caught this)
- Reword CHANGELOG: list version acceptance, additionalOperations
  support, and note that multipart streaming fields and
  discriminator.defaultMapping are NOT in the published 3.2.0 spec
  (they appear in release notes but not the final specification)
- Link issue ahx#469 in CHANGELOG for consistency

Authored by: Aaron Lippold<lippold@gmail.com>
@aaronlippold
Copy link
Copy Markdown
Author

Hey @ahx — sorry for the delay, wanted to do this properly. I went through the published OAS 3.2.0 spec (the HTML is the source of truth per the spec's own statement) and here's what I found for each of your three questions:

1. discriminator and defaultMapping

defaultMapping is not in the published 3.2.0 specification. The Discriminator Object in the published spec still has only two fixed fields: propertyName (REQUIRED) and mapping. The release notes mention defaultMapping as part of the 3.2 line roadmap, but it did not ship in the 3.2.0 publication. So nothing to implement here — the existing discriminator handling is correct for 3.2.0.

I verified this by checking the Discriminator Object section in the published spec and cross-referencing with json_schemer's document meta-schema (which we also updated in json_schemer PR #230 — full 3.2.0 field audit there).

2. Multipart additions (itemSchema, prefixEncoding, itemEncoding)

These are also not in the published 3.2.0 specification. The Media Type Object still has only schema, example, examples, and encoding as fixed fields. The Encoding Object is also unchanged. Same situation as defaultMapping — described in the release notes roadmap but not in the final spec.

3. additionalOperations

This one is in the published spec and I've implemented it in this PR. The Path Item Object now has two new operation fields:

  • query — for the IETF QUERY method (already in REQUEST_METHODS)
  • additionalOperationsMap[string, Operation Object] for non-standard HTTP methods

The implementation iterates additionalOperations after the standard REQUEST_METHODS loop and registers each operation through the same register_operation helper. Keys are downcased since the router upcases internally. Three tests cover it: COPY method routed correctly, standard GET unaffected, undefined LINK returns method_not_allowed.

Summary of all structural changes in OAS 3.2.0

For reference, here's every new field I found in the published spec vs 3.1.0:

Object New Field Type
OpenAPI Object $self string (uri-reference)
Server Object name string
Path Item Object query Operation Object
Path Item Object additionalOperations Map[string, Operation]
Components Object mediaTypes Map[string, Media Type | Reference]
Example Object dataValue Any
Example Object serializedValue string
Parameter in "querystring" new enum value

Everything else (Tag, Response, Security Scheme, OAuth Flows, XML, Encoding, Media Type) is unchanged from 3.1.0 in the published spec.

I've updated the json_schemer document meta-schema with all these fields in PR #230, so openapi.valid? now passes for 3.2.0 documents using any of these new fields.

Let me know if you'd like anything changed or if there's something I missed!

@ahx
Copy link
Copy Markdown
Owner

ahx commented Jun 3, 2026

defaultMapping is not in the published 3.2.0 specification.

I don't understand. defaultMapping is described in the published 3.2.0 spec here: https://spec.openapis.org/oas/v3.2.0.html#fixed-fields-21

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.

OpenAPI 3.2 support

3 participants