fix: treat a required request body becoming optional as compatible
Fixes #329
What
Diffing a spec where an operation's request body changed from required: true to optional (required: false or the key removed) now reports a compatible change instead of an incompatible one. The reverse direction, optional to required, stays incompatible.
Why
Making a required request body optional cannot break existing clients: they keep sending the body, and the server must keep accepting it under the new spec. Reporting that as breaking is a false positive that blocks CI pipelines relying on --fail-on-incompatible.
How
ChangedRequestBody.isCoreChanged() now short-circuits to COMPATIBLE when both the old and new request bodies exist and only the required flag decreases, mirroring the directional checks already used by ChangedRequired (schema properties) and ChangedReadOnly:
- required -> optional: compatible, still listed under "What's Changed" as a non-breaking change
- optional -> required: incompatible, now gated by the previously unused
incompatible.request.body.increasedproperty (REQUEST_BODY_REQUIRED_INCREASED) instead ofincompatible.openapi.endpoints.decreased, which the request body check had been borrowing as a placeholder. Wiring the intended property also brings the request body in line with every other backward-incompatibility check, which gates on its own property. - a removed request body whose old body was required: still incompatible (both bodies must exist for the compatible short-circuit to apply)
Tests
RequestBodyBCTestnow covers both directions:requiredIncreased(incompatible whenincompatible.request.body.increasedis enabled, compatible when disabled) andrequiredDecreasedButCompatible(always compatible)RequestDiffTestgains model-level assertions for both directions, checking the operation and spec-level verdicts- Full
./mvnw testis green
CLI check
For required: true -> required: false on the same operation:
$ openapi-diff old.yaml new.yaml --state
compatible
and the reverse pair still reports incompatible.
Summary by cubic
Fixes #329: a request body changing from required: true to optional (required: false or the key removed) is now reported as a compatible change instead of an incompatible one. Optional to required stays incompatible.
- Making a required body optional cannot break existing clients that keep sending the body, so the change shows under "What's Changed" as non-breaking.
- The optional-to-required check now gates on the intended
incompatible.request.body.increasedproperty instead of borrowingincompatible.openapi.endpoints.decreased. - A removed request body whose old body was required stays incompatible.