56 lines
2.8 KiB
Markdown
56 lines
2.8 KiB
Markdown
# ADR-WEB-ADV-003: OpenAPI 3.2 is generated in parallel and stays experimental
|
|
|
|
- Status: Accepted
|
|
- Date: 2026-08-25
|
|
- Scope: `adapter:inbound:web` — `advanced.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.
|