Skip to content

Fix #357: ignore changes inside readOnly properties in requests - #934

Open
Inf1mum wants to merge 2 commits into
OpenAPITools:masterfrom
Inf1mum:fix/357-readonly-requestbody-schema
Open

Inf1mum wants to merge 2 commits into
OpenAPITools:masterfrom
Inf1mum:fix/357-readonly-requestbody-schema

Conversation

@Inf1mum

@Inf1mum Inf1mum commented Nov 7, 2026 •

Copy link
Copy Markdown

Summary

Fixes #357.

Per the OpenAPI spec, readOnly properties are only sent in responses, never in requests. Changes nested inside a readOnly property of a requestBody therefore cannot affect the request contract and must not be reported as breaking.

Previously the property-level diff already filtered added/removed readOnly properties (isPropertyApplicable in SchemaDiffResult), but changes inside a shared readOnly property were still diffed: the nested ChangedSchema entries ended up in ChangedOpenApi#getChangedSchemas and flagged the whole diff backward incompatible, while the rendered report showed nothing ("broke backward compatibility" with an empty change log).

Change

In SchemaDiffResult.diff, the shared-property loop now skips the schema diff for properties marked readOnly on both sides in a request context, mirroring how the existing isPropertyApplicable pattern treats readOnly/writeOnly for added/removed properties:

  • The readOnly flag itself is still compared: when it differs between old and new, one side is not readOnly and the property is recursed into as before, so the existing REQUEST_READONLY_INCREASED / REQUEST_READONLY_REQUIRED_DECREASED back-compat checks (covered by ReadOnlyBCTest) keep working.
  • Response-side behavior is unchanged: a readOnly property in a response and a writeOnly property in a response are still reported (locked with tests).
  • Nested readOnly objects are covered: skipping the diff at the outermost readOnly property prunes the whole subtree, so no recursion is added.

Repro from the issue (before/after)

Before:

==========================================================================
==                            API CHANGE LOG                            ==
==========================================================================
                                   API                                    
--------------------------------------------------------------------------
--                                Result                                --
--------------------------------------------------------------------------
                 API changes broke backward compatibility                 
--------------------------------------------------------------------------

After:

No differences. Specifications are equivalent

Tests

New Issue357Test (fixtures from the issue):

  • changesInsideReadOnlyPropertyInRequestAreIgnored — the issue's old/new specs now produce no changed operations, no changed schemas, and an unchanged result.
  • changesInsideWriteOnlyPropertyInResponseAreStillReported — counter-case locking current behavior: a change inside a writeOnly property of a response schema is still reported and flagged incompatible.
  • changesInsideReadOnlyPropertyInResponseAreStillReported — guards the response side: a change inside a readOnly property of a response schema is still reported.

Full core module: mvn -pl core test — 273 tests, 0 failures (2 pre-existing skips in Swagger2CompatibilityTest).


Summary by cubic

Fixes #357 by ignoring changes nested inside readOnly properties in request bodies, which per the OpenAPI spec are never sent by clients and therefore can't affect the request contract.

  • Skips schema diffing for shared properties marked readOnly on both sides in a request context, resolving $ref wrappers before checking the flag.
  • Also drops the skipped property from the parent required diff, so adding a response-only field to required no longer flags the request as breaking.
  • When the readOnly flag itself differs between old and new, the property is still recursed into so the existing back-compat checks keep working.
  • Response-side behavior is unchanged: changes inside readOnly or writeOnly response properties are still reported.
  • Adds Issue357Test covering the issue repro, required/$ref variants, readOnly flag transitions, and response counter-cases.

Written for commit 97990c1. Summary will update on new commits.

View guided diff

…quests

Clients never send readOnly properties, so changes nested inside a
readOnly property of a requestBody cannot affect the request contract.
The property-level diff already filtered added/removed readOnly
properties (isPropertyApplicable), but changes inside a shared readOnly
property were still diffed: the nested changed schemas were reported in
ChangedOpenApi#getChangedSchemas and flagged the diff backward
incompatible, while the rendered report showed nothing.

Skip the schema diff for shared properties that are marked readOnly on
both sides in a request context, mirroring the writeOnly handling for
responses. A change of the readOnly flag itself still recurses so the
existing REQUEST_READONLY_* back-compat checks keep working. Response
side behavior is unchanged.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 8 files

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

…efs in requests

Address cubic review feedback on OpenAPITools#934:

- Remove the skipped readOnly property from the parent `required` diff
  (both increased and missing entries) so adding a response-only field to
  `required` can no longer flag the request as breaking.
- Resolve `$ref`-referenced shared properties before checking the
  readOnly flag; the unresolved wrapper carries no readOnly flag, so
  changes inside referenced readOnly component schemas were still
  reported in request diffs.
- Add fixtures/tests: readOnly property added to parent `required`,
  readOnly property referenced via `$ref`, and readOnly flag transitions
  (true -> false and false -> true) asserting the flag change and nested
  changes are still reported and never swallowed by the skip logic.

Signed-off-by: Inf1mum <vadimlazuk5@gmail.com>
@Inf1mum

Inf1mum commented Nov 7, 2026

Copy link
Copy Markdown
Author

Addressed all three review threads (answers posted in each thread); pushed to fix/357-readonly-requestbody-schema in 97990c1.

  1. Parent required leak for skipped readOnly properties — when a shared property is skipped in request context (readOnly on both sides), its name is now removed from the increased and missing entries of the parent required diff, so adding a response-only property to required no longer flags the request as breaking. Test: requiredChangeForReadOnlyPropertyInRequestIsIgnored.

  2. Unresolved `` wrappers bypassing the readOnly check — shared properties are now resolved via RefPointer (same resolution the rest of the codebase uses) before testing `readOnly`. Test: `changesInsideReferencedReadOnlyPropertyInRequestAreIgnored` (includes the parent `required` increase, which was the actual remaining leak — red on the previous head, green now).

  3. readOnly flag transition coverage — new request fixtures/tests for true → false (readOnlyFlagRemovedInRequestStillReportsNestedChanges) and false → true (readOnlyFlagAddedInRequestStillReportsNestedChanges), asserting the flag change and the nested change are still reported and backward-incompatible. The skip only applies when readOnly is true on both sides, so transitions are never swallowed.

Full core suite green: 277 tests, 0 failures, 2 skipped (pre-existing).

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.

ChangedSchema in a readOnly property for requestBody is not filtered out from the result.

1 participant