Files
clean-architecture-backend-…/docs/adr/ADR-WEB-ADV-003-openapi-32-remains-experimental.md
T

2.8 KiB

ADR-WEB-ADV-003: OpenAPI 3.2 is generated in parallel and stays experimental

  • Status: Accepted
  • Date: 2026-08-25
  • Scope: adapter:inbound:webadvanced.openapi

Context

Advanced Task 17 adds an OpenAPI 3.2 generation lane beside the Stable 3.1.2 snapshot.

Generating 3.2 is cheap. Adopting it is not, and the two get conflated because the generated document looks fine. The value of an API description is entirely in what consumes it, and a document in a version a client generator does not fully understand produces a client that compiles and is wrong — which is worse than no document at all.

Decision

3.1.2 remains the release artifact. OpenApiVersionLane.STABLE_3_1.releaseArtifact() is true and EXPERIMENTAL_3_2's is false. This is a property of the type, not a configuration setting.

Generating 3.2 must not change the 3.1 snapshot. Both are produced from the same model, so a contributor that mutates it on the way to 3.2 changes the artifact that is actually shipped — silently, and only when the experimental lane runs. OpenApi32CompatibilityReport compares the snapshot hash before and after and makes a difference a promotion blocker.

Four kinds of tool are checked separately. A parser reports structural errors; a linter applies style rules and accepts documents a parser rejects; a generator produces client code, and this is where an unsupported construct surfaces — not as an error but as a method with the wrong signature; a compile of that generated code is the only step that catches it. "OpenAPI 3.2 works" is not a statement anybody can make. "This document is read correctly by these four tools at these versions" is.

Promotion requires an accepted ADR regardless of how green the matrix is. promotionBlockers(false) always contains that blocker. A machine-checkable matrix cannot decide whether the consumer population is ready.

Streaming description differences are reported separately. They are the substantive difference between the two versions for this application, and folding them into a pass/fail hides what changed.

Consequences

  • The 3.2 document is published as an artifact of the experimental workflow, never of the release workflow.
  • A client generator that only understands 3.1 is unaffected, which is the point.
  • Adopting 3.2 later is a documented decision with a named consumer matrix behind it.

Alternatives considered

  • Switch to 3.2 and keep a 3.1 downgrade. Rejected: the downgrade is lossy in exactly the constructs 3.2 was wanted for, so it would ship a description that is wrong for both audiences.
  • Generate only 3.2 and let consumers cope. Rejected: the failure mode is a generated client that compiles and misbehaves.
  • Skip the client-compile step in the matrix. Rejected: it is the only one that catches the failure the others miss.