Browse pages
API Compatibility
OpenAPI freshness proves that committed artifacts match source code.
Intent#
OpenAPI freshness proves that committed artifacts match source code. It does not prove that independently deployed consumers can continue using the API.
Activation#
Activation scope: project.
Applicable specification kinds: None.
The consumer enables compat for public APIs, partner clients, mobile clients, or independently deployed consumers. Same-release internal APIs retain litespec/backend/api#treat-openapi-as-a-generated-contract. A project in its pre-production stage defers these rules through the stage extension.
Baseline relationship#
This extension replaces no baseline provision.
This extension switches on no optional record type.
Standards#
Classify independent-consumer changes#
ruleguidancelitespec/ext/compat#classify-independent-consumer-changesAn API change reviewer MUST classify each contract change that affects an independently deployed consumer.
Why
Classification determines whether consumers need a new contract version, review, or no action.
Checka reviewer answers
Does the reviewer classify each independent-consumer contract change?
Marked guidance: a reviewer answers this question.
Classify breaking contract changes#
ruleguidancelitespec/ext/compat#classify-breaking-contract-changesAn API change reviewer MUST classify removal, rename, required input, narrowed value, response, status, or authentication changes as breaking.
Why
Existing consumers can depend on every removed, renamed, narrowed, or retyped contract element.
Checka reviewer answers
Does the reviewer mark each removed, renamed, narrowed, retyped, or authentication change as breaking?
Marked guidance: a reviewer answers this question.
Classify compatible additions#
ruleguidancelitespec/ext/compat#classify-compatible-additionsAn API change reviewer MUST classify an optional field, endpoint, or query parameter as compatible when existing clients retain behavior.
Why
Optional additions do not require existing callers to send or interpret new values.
Checka reviewer answers
Does the reviewer record why each optional addition preserves existing behavior?
Marked guidance: a reviewer answers this question.
Review exhaustive consumer changes#
ruleguidancelitespec/ext/compat#review-exhaustive-consumer-changesAn API change reviewer MUST require consumer review for an added enum value or polymorphic subtype.
Why
Generated exhaustive clients can reject a newly valid enum value or discriminator case.
Checka reviewer answers
Do added enum values and discriminator cases receive consumer review?
Marked guidance: a reviewer answers this question.
Preserve stable error codes#
ruleguidancelitespec/ext/compat#preserve-stable-error-codesAn API change reviewer MUST classify removal or reassignment of a stable Problem Details code as breaking.
Why
A consumer can branch on a stable code even when the HTTP status remains unchanged.
Checka reviewer answers
Does the reviewer classify each removed or reassigned stable code as breaking?
Marked guidance: a reviewer answers this question.
Resolve uncertain classifications safely#
ruleguidancelitespec/ext/compat#resolve-uncertain-classifications-safelyAn API change reviewer MUST classify an unclear contract change as breaking and require consumer review.
Why
A conservative outcome protects consumers when a structural diff cannot prove compatibility.
Checka reviewer answers
Does the reviewer treat each unclear change as breaking with consumer review?
Marked guidance: a reviewer answers this question.
Retain release baselines#
ruleguidancelitespec/ext/compat#retain-release-baselinesAn API owner MUST store each release OpenAPI document as a retained baseline artifact.
Why
A retained document gives later changes an immutable comparison target.
Checka reviewer answers
Does each release retain its OpenAPI document as an immutable baseline?
Marked guidance: a reviewer answers this question.
Diff release contracts#
ruleguidancelitespec/ext/compat#diff-release-contractsThe project MUST compare the current OpenAPI document with the selected supported baseline, both locally and in continuous integration.
Why
The same diff detects structural compatibility changes locally and during continuous integration.
Checka reviewer answers
Do the local run and continuous integration compare against the selected baseline?
Marked guidance: a reviewer answers this question.
Reject unapproved breaking diffs#
ruleguidancelitespec/ext/compat#reject-unapproved-breaking-diffsContinuous integration MUST fail a breaking diff unless a new API version or approved consumer decision authorizes it.
Why
The failure makes a compatibility decision explicit before release.
Checka reviewer answers
Does a breaking diff fail without a new version or an approved decision?
Marked guidance: a reviewer answers this question.
Assign operation IDs#
ruleguidancelitespec/ext/compat#assign-operation-idsEvery operation exposed to an independent consumer MUST have a deliberate operationId, except an endpoint whose shape a specification outside the project fixes.
Why
Generated clients and tools use the identifier as an operation-level contract name.
Example
An OAuth redirect endpoint, an OIDC discovery document, a provider webhook receiver, and a well-known resource each carry a shape the other party defines.
Checka reviewer answers
Does each independent-consumer operation carry a deliberate operationId?
Marked guidance: a reviewer answers this question.
Retain compatible operation IDs#
ruleguidancelitespec/ext/compat#retain-compatible-operation-idsA compatible API change MUST retain the existing operationId.
Why
A changed identifier can break generated client names and operation references.
Checka reviewer answers
Does each compatible change retain the existing operationId?
Marked guidance: a reviewer answers this question.
Assign versioned operation IDs#
ruleguidancelitespec/ext/compat#assign-versioned-operation-idsA new API version MUST assign a new operation ID when its operation contract changes.
Why
A new version can own a contract name without mutating the retained version.
Checka reviewer answers
Does a new version assign a new operation ID for each changed contract?
Marked guidance: a reviewer answers this question.
Version breaking contracts#
ruleguidancelitespec/ext/compat#version-breaking-contractsAn API owner MUST use a new route or documented media-type version for a breaking contract.
Why
A version boundary lets existing and changed contracts coexist.
Checka reviewer answers
Does each breaking contract use a new route or media-type version?
Marked guidance: a reviewer answers this question.
Retain supported versions#
ruleguidancelitespec/ext/compat#retain-supported-versionsAn API owner MUST keep the previous version available for its declared support window.
Why
Independently deployed consumers need the published support interval to adopt a changed contract.
Checka reviewer answers
Does the previous version stay available through its support window?
Marked guidance: a reviewer answers this question.
Record version retirement#
ruleguidancelitespec/ext/compat#record-version-retirementA versioning decision MUST name the owner of each affected consumer, the deadline, and the removal condition, with the decision approved before any removal.
Why
Named ownership makes a future removal reviewable rather than implicit.
Checka reviewer answers
Does the versioning decision name its consumer owners, deadline, removal condition, and ownership?
Marked guidance: a reviewer answers this question.
Signal planned public removal#
ruleguidancelitespec/ext/compat#signal-planned-public-removalA public operation scheduled for removal MUST expose a documented deprecation signal.
Why
Deprecation and Sunset headers are examples of observable deprecation signals.
Checka reviewer answers
Does each operation scheduled for removal expose its deprecation signal?
Marked guidance: a reviewer answers this question.
Publish deprecation context#
ruleguidancelitespec/ext/compat#publish-deprecation-contextA public operation scheduled for removal MUST appear in the consumer CHANGELOG.md.
Why
The CHANGELOG.md gives consumers one release-note location for planned removal.
Checka reviewer answers
Does the consumer CHANGELOG.md name each operation scheduled for removal?
Marked guidance: a reviewer answers this question.
Record deprecation conditions#
ruleguidancelitespec/ext/compat#record-deprecation-conditionsA deprecation decision MUST record the sunset date and replacement operation, with nothing removed while the decision is draft.
Why
Consumers need a fixed end date and a named supported alternative.
Checka reviewer answers
Does the deprecation decision record the sunset date, replacement, and ownership?
Marked guidance: a reviewer answers this question.
Treat errors as contracts#
ruleguidancelitespec/ext/compat#treat-errors-as-contractsAn API owner MUST treat Problem Details type, code, field-error codes, and documented statuses as versioned contract elements.
Why
Consumers can branch on error structures as well as successful response structures.
Checka reviewer answers
Does the owner treat type, code, field codes, and statuses as versioned contract elements?
Marked guidance: a reviewer answers this question.
Gate new error outcomes#
ruleguidancelitespec/ext/compat#gate-new-error-outcomesAn API owner MUST add an error outcome only when existing consumers safely handle an unknown code.
Why
Safe fallback behavior avoids consumer failure on an unseen outcome.
Checka reviewer answers
Do existing consumers safely handle each added unknown code?
Marked guidance: a reviewer answers this question.
Exercise generated consumers#
ruleguidancelitespec/ext/compat#exercise-generated-consumersAn API owner MUST test each first-party generated client against the changed OpenAPI document, with each client compiling and exercising its changed operations.
Why
Generated clients expose exhaustive handling and schema differences that a structural diff can miss.
Checka reviewer answers
Does each first-party client compile and exercise the changed contract?
Marked guidance: a reviewer answers this question.
Conventions#
Store current OpenAPI source#
conventionguidancelitespec/ext/compat#store-current-openapi-sourceStore the current source artifact at apps/api/openapi/{ProjectName}.json.
ReplacementA consumer records a departure from this default as an Exception record with reason and review date.
Why
The path gives source generation and contract review one predictable location.
Checka reviewer answers
Is the generated OpenAPI at the documented path or a recorded Exception?
Marked guidance: a reviewer answers this question.
Keep baseline references immutable#
conventionguidancelitespec/ext/compat#keep-baseline-references-immutableStore each supported baseline beside its contract owner or under an immutable retained-release reference.
ReplacementA consumer records a departure from this default as an Exception record with reason and review date.
Why
Immutable baseline references prevent a diff from comparing against a mutable artifact.
Checka reviewer answers
Are baseline references immutable, or is there a recorded Exception?
Marked guidance: a reviewer answers this question.
Use one diff tool#
conventionguidancelitespec/ext/compat#use-one-diff-toolUse the same OpenAPI diff tool in local verification and continuous integration.
ReplacementA consumer records a departure from this default as an Exception record with reason and review date.
Why
One classifier avoids differences between local and continuous integration outcomes.
Checka reviewer answers
Do the local run and continuous integration invoke the same diff tool?
Marked guidance: a reviewer answers this question.
Keep Problem Details codes stable#
conventionguidancelitespec/ext/compat#keep-problem-details-codes-stableKeep Problem Details error codes stable across compatible versions.
ReplacementA consumer records a departure from this default as an Exception record with reason and review date.
Why
A stable code supports consumer error handling over time.
Checka reviewer answers
Do Problem Details codes stay stable across compatible versions?
Marked guidance: a reviewer answers this question.
Dependencies#
The extension adds no required package. An introduced OpenAPI diff tool needs a manifest pin.
Verification#
| ID | Mark | Evidence |
|---|---|---|
| litespec/ext/compat#classify-independent-consumer-changes | guidance | Does the reviewer classify each independent-consumer contract change? |
| litespec/ext/compat#classify-breaking-contract-changes | guidance | Does the reviewer mark each removed, renamed, narrowed, retyped, or authentication change as breaking? |
| litespec/ext/compat#classify-compatible-additions | guidance | Does the reviewer record why each optional addition preserves existing behavior? |
| litespec/ext/compat#review-exhaustive-consumer-changes | guidance | Do added enum values and discriminator cases receive consumer review? |
| litespec/ext/compat#preserve-stable-error-codes | guidance | Does the reviewer classify each removed or reassigned stable code as breaking? |
| litespec/ext/compat#resolve-uncertain-classifications-safely | guidance | Does the reviewer treat each unclear change as breaking with consumer review? |
| litespec/ext/compat#retain-release-baselines | guidance | Does each release retain its OpenAPI document as an immutable baseline? |
| litespec/ext/compat#diff-release-contracts | guidance | Do the local run and continuous integration compare against the selected baseline? |
| litespec/ext/compat#reject-unapproved-breaking-diffs | guidance | Does a breaking diff fail without a new version or an approved decision? |
| litespec/ext/compat#assign-operation-ids | guidance | Does each independent-consumer operation carry a deliberate operationId? |
| litespec/ext/compat#retain-compatible-operation-ids | guidance | Does each compatible change retain the existing operationId? |
| litespec/ext/compat#assign-versioned-operation-ids | guidance | Does a new version assign a new operation ID for each changed contract? |
| litespec/ext/compat#version-breaking-contracts | guidance | Does each breaking contract use a new route or media-type version? |
| litespec/ext/compat#retain-supported-versions | guidance | Does the previous version stay available through its support window? |
| litespec/ext/compat#record-version-retirement | guidance | Does the versioning decision name its consumer owners, deadline, removal condition, and ownership? |
| litespec/ext/compat#signal-planned-public-removal | guidance | Does each operation scheduled for removal expose its deprecation signal? |
| litespec/ext/compat#publish-deprecation-context | guidance | Does the consumer CHANGELOG.md name each operation scheduled for removal? |
| litespec/ext/compat#record-deprecation-conditions | guidance | Does the deprecation decision record the sunset date, replacement, and ownership? |
| litespec/ext/compat#treat-errors-as-contracts | guidance | Does the owner treat type, code, field codes, and statuses as versioned contract elements? |
| litespec/ext/compat#gate-new-error-outcomes | guidance | Do existing consumers safely handle each added unknown code? |
| litespec/ext/compat#exercise-generated-consumers | guidance | Does each first-party client compile and exercise the changed contract? |
| litespec/ext/compat#store-current-openapi-source | guidance | Is the generated OpenAPI at the documented path or a recorded Exception? |
| litespec/ext/compat#keep-baseline-references-immutable | guidance | Are baseline references immutable, or is there a recorded Exception? |
| litespec/ext/compat#use-one-diff-tool | guidance | Do the local run and continuous integration invoke the same diff tool? |
| litespec/ext/compat#keep-problem-details-codes-stable | guidance | Do Problem Details codes stay stable across compatible versions? |