Rules and severities
apigenie diff rates every change between two versions of a document with a rule: the kind of
node the change is in, the property that changed, and whether the property was added, removed or
modified. Without a configuration, the rules are the recommended ruleset of the standard, listed
below for each of them; a configuration that names
recommended in extends changes some of them. This page says what the severities mean, how a
report names the rule that rated a change, and what makes a breaking change acceptable.
Severities
| Severity | In reports | What it means |
|---|---|---|
breaking |
breaking |
A client built against the old version fails: an operation it calls is gone, a parameter it does not send is required, a value it reads has another type. |
non_breaking |
non-breaking |
Old clients keep working; the change is there for new ones: a new operation, a new optional parameter, a new property in a response. |
non_functional |
non-functional |
Nothing a client sends or receives changes: a description, a summary, an example, a tag. |
none |
none |
The change does not count. The status and the changelog leave it out; the detailed report lists it. |
nested |
The property is an object or a list compared member by member, and the change takes the highest severity found inside: info: nested rates a changed info by its title, version and contact. |
The status of a comparison is the highest severity of its changes. The command exits with status 1
when it is breaking, so a CI job fails on the pull request that would break a client, and with 0
otherwise. --update-version turns the status into a version: a new major version for breaking,
minor for non_breaking, patch for non_functional.
How a rule is written
A rule names a node type, one of its properties, and the severity of a change of that property. The property takes one of these forms:
- A severity alone,
host: breaking, for a property a node always has, which can only be modified, and for a property whose addition, removal and modification weigh the same. add,removeandmodify, each with a severity, for an optional property:license: {add: breaking, remove: non_breaking, modify: nested}.add_item,remove_itemandmodify_itemfor the items of a list or a map, such as the operations of a path item or the properties of a schema.add_first_itemrates the first item of a list that was empty, andremove_last_itemthe last item of a list that becomes empty: the first value of anenumrestricts what was unrestricted, and removing the last one lifts the restriction.- A condition in place of a severity:
{if: CONDITION, then: SEVERITY, else: SEVERITY}, where the conditions are the ones below.
The defaults node type sets what is not named elsewhere: defaults.extensions rates every x-
extension of an OpenAPI, Swagger 2.0 or AsyncAPI document that no node type’s extensions map
names, defaults.options the Protobuf options no node type’s options map names, and
defaults.directives the GraphQL directives no node kind’s directives map names.
Conditions
| Condition | Standards | Holds when |
|---|---|---|
required |
OpenAPI, Swagger 2.0, AsyncAPI, GraphQL | The added or removed item is required: a parameter with required: true, a property listed in the schema’s required, a GraphQL argument or input field of a non-null type without a default value. |
deprecated |
OpenAPI, Swagger 2.0, Protobuf, GraphQL | The item is deprecated: deprecated: true on an operation, a parameter or a schema, an enum value listed in the schema’s x-deprecated-enum, the deprecated = true option of a Protobuf field or enum value, @deprecated in GraphQL. |
sunset_passed |
OpenAPI, Swagger 2.0 | The item is deprecated and its x-sunset date is on or before the date of the comparison, the current date or --today. |
reserved |
Protobuf | The number of the removed field or enum value is reserved in the new file. |
wire_compatible |
Protobuf | The old and the new type of a field are encoded the same way: int32 and int64, string and bytes, a field with and without optional. |
compatible |
GraphQL | The old and the new type are compatible for the direction of the data: a field may become non-null and an argument or input field nullable, a list stays a list. |
true, false |
all | The new value of a boolean property, such as repeatable of a directive or a Protobuf option; the old value when the property was removed. |
Direction
A schema change weighs differently for the data clients send and the data they receive: a new
required property breaks the clients that send the object and not those that receive it, and a
removed property the other way round. The rules of a standard therefore come in layers. For OpenAPI
and Swagger 2.0, rules applies everywhere, request replaces some of them for parameters and
request bodies, and response for responses; inside callbacks and webhooks the directions are
swapped. A component schema takes the direction of the places it is used in, following the
references between schemas in either document; one used both ways, or nowhere, gets the stricter
severity of the two.
For AsyncAPI the directions are those of the application the document describes: receive applies
to the messages of receive operations, which other parties send, and send to the messages of
send operations, which other parties receive. Replies flow the other way than the messages of
their operation, and a message used both ways, or by no operation, gets the stricter severity.
Protobuf files and GraphQL schemas have no direction layers: a GraphQL argument or input field is
always sent and a field always received, and the rules of each node kind say so.
Reading a report
The detailed report (--report detailed) lists every change with the node type and the property
that rated it, and the severity the rule gave:
streetlights.yaml
38 5 breaking Removed asyncapi.servers['mtls-connections']
128 7 non-breaking Added channel.messages['dimLight']
167 7 non-functional Added schema.description
asyncapi.servers['mtls-connections'] is a removed item of the servers property of the
asyncapi node: the rule is asyncapi.servers.remove_item, breaking in the AsyncAPI table
below. A report spells a node type of two words with an underscore, security_scheme or
path_item, where the configuration and the tables write securityScheme and pathItem. The JSON
report carries the same two names in target and config_key. The changelog report, the default,
groups the changes by operation, channel, message or type and lists the rated changes of each one
under it, with the same words.
Accepting a breaking change
A failed check leaves four ways forward, the first two of them without touching the rules.
Announce the removal first. In OpenAPI and Swagger 2.0 documents, the recommended rules let
a deprecated operation, path item, parameter, component schema, response property or request enum
value go once its x-sunset date has passed, the sunset_passed condition. Mark it in one pull
request, which is non_breaking, and remove it in another after the date:
paths:
/v1/orders:
get:
deprecated: true
x-sunset: 2027-01-31
x-sunset is an RFC 3339 date or date-time next to deprecated: true, on the element itself,
next to the $ref that uses it, or where it is defined; an enum value is deprecated when the
schema’s x-deprecated-enum lists it, and goes on the schema’s x-sunset date. --today runs
the comparison as of another date, to see the removal pass before then.
apigenie evolve plan writes the deprecations and the removal in two
waves.
Reserve the number. In a Protobuf file, a removed field or enum value whose number is reserved
is non_breaking, the reserved condition: the removal is deliberate, and no later field can take
the number and misread the data of the old one.
message Customer {
reserved 7;
reserved "telex";
string name = 1;
}
Change the rule. When a change is breaking by the rules and not for the API’s clients, say so
in the commands.diff block of the configuration, starting
from recommended and overriding the rule, the same path as in the tables below. overrides
limits a rule to the locations that match a pattern, and none turns a change off:
version: '1.0'
commands:
diff:
extends: [recommended]
rules:
operation:
# tags are not part of the contract of this API
tags: none
graphql:
extends: [recommended]
rules:
object:
fields:
# fields marked @deprecated may go
remove_item:
if: deprecated
then: non_breaking
else: breaking
overrides:
- where:
location: /paths/~1internal~1*/**
rules:
pathItem:
operations:
remove_item: non_breaking
The sections diff, diff.swagger, diff.asyncapi, diff.protobuf and diff.graphql of the diff reference describe the keys of each standard and the location patterns.
Ship a new major version. When the break is intended, the check records it rather than blocks
it: --update-version writes the major version the changes call for into the document, and the
GitHub Action with fail-on: never, or a job that ignores exit status 1,
reports the changes without failing.
Recommended rules
The tables list the recommended ruleset of each standard as the CLI of this release applies it:
the node type, the property, the rule in the form a configuration writes it, and the reason the
ruleset gives. A standard with directions has a table per direction after its rules.
OpenAPI
| Node type | Property | Rule | Note |
|---|---|---|---|
defaults |
extensions |
non_functional |
|
openapi |
openapi |
breaking |
|
info |
nested |
||
jsonSchemaDialect |
none |
||
servers |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
paths |
nested |
||
webhooks |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
components |
nested |
||
security |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, modify_item: nested |
add_item: Requirements are alternatives: adding one to existing ones is harmless, but requiring authentication where none was required breaks clients. |
|
tags |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
externalDocs |
add: non_breaking, remove: non_breaking, modify: nested |
||
info |
title |
breaking |
|
summary |
non_functional |
||
description |
non_functional |
||
termsOfService |
breaking |
||
contact |
nested |
||
license |
add: breaking, remove: non_breaking, modify: nested |
||
version |
none |
||
contact |
name |
add: non_breaking, remove: breaking, modify: non_breaking |
|
url |
add: non_breaking, remove: breaking, modify: non_breaking |
||
email |
add: non_breaking, remove: breaking, modify: non_breaking |
||
license |
name |
breaking |
|
identifier |
breaking |
||
url |
breaking |
||
server |
url |
breaking |
|
description |
non_functional |
||
variables |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
serverVariable |
description |
non_functional |
|
default |
breaking |
||
enum |
add_item: non_breaking, remove_item: breaking |
||
components |
schemas |
add_item: non_breaking, remove_item: {if: sunset_passed, then: non_breaking, else: breaking}, modify_item: nested |
remove_item: A deprecated schema may go once its x-sunset date has passed. |
responses |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
parameters |
add_item: non_breaking, remove_item: {if: sunset_passed, then: non_breaking, else: breaking}, modify_item: nested |
||
examples |
non_functional |
||
requestBodies |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
headers |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
securitySchemes |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
links |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
callbacks |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
pathItems |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
paths |
add_item: non_breaking, remove_item: {if: sunset_passed, then: non_breaking, else: breaking}, modify_item: nested |
remove_item: A path whose operations are all deprecated may go once their sunset dates have passed. |
|
pathItem |
summary |
non_functional |
|
description |
non_functional |
||
parameters |
add_item: {if: required, then: breaking, else: non_breaking}, remove_item: {if: sunset_passed, then: non_breaking, else: breaking}, modify_item: nested |
remove_item: A deprecated parameter may go once its x-sunset date has passed. |
|
operations |
add_item: non_breaking, remove_item: {if: sunset_passed, then: non_breaking, else: breaking}, modify_item: nested |
remove_item: A deprecated operation may go once its x-sunset date has passed; to allow removing every deprecated operation, use remove_item: { if: deprecated, then: non_breaking, else: breaking }. |
|
servers |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
operation |
tags |
non_breaking |
|
summary |
non_functional |
||
operationId |
breaking |
||
description |
non_functional |
||
externalDocs |
non_functional |
||
deprecated |
non_breaking |
Deprecating announces a removal; the removal itself is the breaking change. | |
parameters |
add_item: {if: required, then: breaking, else: non_breaking}, remove_item: {if: sunset_passed, then: non_breaking, else: breaking}, modify_item: nested |
remove_item: A deprecated parameter may go once its x-sunset date has passed. |
|
requestBody |
nested |
||
responses |
nested |
||
callbacks |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
security |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, modify_item: nested |
||
servers |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
externalDocumentation |
description |
non_functional |
|
url |
non_functional |
||
parameter |
name |
breaking |
|
in |
breaking |
||
description |
non_functional |
||
required |
modify: {if: true, then: breaking, else: non_breaking} |
||
deprecated |
non_breaking |
||
allowEmptyValue |
modify: {if: true, then: non_breaking, else: breaking} |
||
style |
breaking |
||
explode |
breaking |
||
allowReserved |
modify: {if: true, then: non_breaking, else: breaking} |
||
schema |
add: breaking, remove: breaking, modify: nested |
||
content |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
example |
non_functional |
||
examples |
non_functional |
||
requestBody |
description |
non_functional |
|
required |
add: {if: true, then: breaking, else: non_breaking}, remove: breaking, modify: {if: true, then: breaking, else: non_breaking} |
||
content |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
mediaType |
schema |
add: breaking, remove: breaking, modify: nested |
|
encoding |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
example |
non_functional |
||
examples |
non_functional |
||
encoding |
contentType |
breaking |
|
headers |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
style |
breaking |
||
explode |
breaking |
||
allowReserved |
breaking |
||
responses |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
response |
description |
non_functional |
|
headers |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
content |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
links |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
callback |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
example |
summary |
non_functional |
|
description |
non_functional |
||
value |
non_functional |
||
externalValue |
non_functional |
||
link |
description |
non_functional |
|
server |
non_breaking |
||
operationRef |
non_breaking |
||
operationId |
non_breaking |
||
parameters |
non_breaking |
||
requestBody |
non_breaking |
||
header |
name |
breaking |
|
description |
non_functional |
||
required |
modify: {if: true, then: breaking, else: non_breaking} |
||
deprecated |
non_breaking |
||
allowEmptyValue |
breaking |
||
explode |
breaking |
||
allowReserved |
breaking |
||
schema |
add: breaking, remove: breaking, modify: nested |
||
content |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
example |
non_functional |
||
examples |
non_functional |
||
tag |
name |
breaking |
|
description |
non_functional |
||
externalDocs |
non_functional |
||
reference |
$ref |
breaking |
|
summary |
non_breaking |
||
description |
non_functional |
||
schema |
id |
breaking |
|
title |
non_breaking |
||
description |
non_functional |
||
type |
breaking |
||
format |
breaking |
||
const |
breaking |
||
enum |
add_item: breaking, remove_item: {if: sunset_passed, then: non_breaking, else: breaking} |
remove_item: A value listed in x-deprecated-enum may go once the schema’s x-sunset date has passed. |
|
deprecated |
non_breaking |
||
readOnly |
non_functional |
||
writeOnly |
non_functional |
||
minimum |
breaking |
||
exclusiveMinimum |
breaking |
||
maximum |
breaking |
||
exclusiveMaximum |
breaking |
||
multipleOf |
breaking |
||
minLength |
breaking |
||
maxLength |
breaking |
||
pattern |
breaking |
||
items |
add: breaking, remove: non_breaking, modify: nested |
||
contains |
add: breaking, remove: breaking, modify: nested |
||
minContains |
breaking |
||
maxContains |
breaking |
||
prefixItems |
breaking |
||
minItems |
breaking |
||
maxItems |
breaking |
||
uniqueItems |
breaking |
||
unevaluatedItems |
add: breaking, remove: breaking, modify: nested |
||
required |
breaking |
||
properties |
add_item: non_breaking, remove_item: non_breaking, modify_item: nested |
||
patternProperties |
add_item: non_breaking, remove_item: non_breaking, modify_item: nested |
||
propertyNames |
non_breaking |
||
additionalProperties |
breaking |
||
minProperties |
breaking |
||
maxProperties |
breaking |
||
unevaluatedProperties |
add: breaking, remove: breaking, modify: nested |
||
allOf |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
oneOf |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
anyOf |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
not |
add: breaking, remove: breaking, modify: nested |
||
if |
add: breaking, remove: breaking, modify: nested |
||
then |
add: breaking, remove: breaking, modify: nested |
||
else |
add: breaking, remove: breaking, modify: nested |
||
anchor |
none |
||
dynamicAnchor |
none |
||
dynamicRef |
none |
||
vocabulary |
breaking |
||
contentEncoding |
breaking |
||
contentMediaType |
breaking |
||
contentSchema |
nested |
||
discriminator |
add: breaking, remove: non_breaking, modify: nested |
||
xml |
nested |
||
externalDocs |
non_functional |
||
examples |
non_functional |
||
default |
breaking |
||
dialect |
breaking |
||
discriminator |
propertyName |
breaking |
|
mapping |
breaking |
||
xml |
name |
breaking |
|
namespace |
breaking |
||
prefix |
breaking |
||
attribute |
breaking |
||
wrapped |
breaking |
||
securityScheme |
name |
breaking |
|
description |
non_functional |
||
type |
breaking |
||
in |
breaking |
||
scheme |
breaking |
||
bearerFormat |
breaking |
||
flows |
add: breaking, remove: breaking, modify: nested |
||
openIdConnectUrl |
breaking |
||
oauthFlows |
implicit |
add: breaking, remove: breaking, modify: nested |
|
password |
add: breaking, remove: breaking, modify: nested |
||
clientCredentials |
add: breaking, remove: breaking, modify: nested |
||
authorizationCode |
add: breaking, remove: breaking, modify: nested |
||
oauthFlow |
authorizationUrl |
breaking |
|
tokenUrl |
breaking |
||
refreshUrl |
breaking |
||
scopes |
add_item: breaking, remove_item: breaking, modify_item: non_functional |
||
securityRequirement |
breaking |
Severities that depend on the direction of data flow. They override rules in requests (parameters, request bodies; sent by API consumers) and responses (sent by API providers). Inside callbacks and webhooks the directions are swapped, as the API provider sends the requests there. Changes in places shared by both (e.g. component schemas) get the stricter of the request and the response severity.
These defaults assume that servers and clients ignore unknown properties. For clients that reject them, set response.schema.properties.add_item to breaking.
The request layer, for the parameters and the request bodies, replaces these rules of the layer above:
| Node type | Property | Rule | Note |
|---|---|---|---|
schema |
properties |
add_item: {if: required, then: breaking, else: non_breaking}, remove_item: non_breaking |
add_item: Existing clients don’t send new required properties. |
required |
add_item: breaking, remove_item: non_breaking |
||
enum |
add_item: non_breaking, add_first_item: breaking, remove_item: {if: sunset_passed, then: non_breaking, else: breaking}, remove_last_item: non_breaking |
add_first_item: Restricting a value to a set of values. remove_item: A value listed in x-deprecated-enum may go once the schema’s x-sunset date has passed. |
The response layer, for the responses, replaces these:
| Node type | Property | Rule | Note |
|---|---|---|---|
schema |
properties |
add_item: non_breaking, remove_item: {if: sunset_passed, then: non_breaking, else: breaking} |
remove_item: Existing clients may rely on the removed property, unless it was deprecated and its x-sunset date has passed. |
required |
add_item: non_breaking, remove_item: {if: sunset_passed, then: non_breaking, else: breaking} |
remove_item: The item of a deprecated property goes with the property, once its x-sunset date has passed. |
|
enum |
add_item: breaking, add_first_item: non_breaking, remove_item: non_breaking, remove_last_item: breaking |
add_item: Existing clients may not handle new values. |
Swagger 2.0
The recommended severities of changes of Swagger 2.0 documents. A severity is one of none (not reported), non_functional, non_breaking, breaking and nested (the highest severity of the nested changes).
| Node type | Property | Rule | Note |
|---|---|---|---|
defaults |
extensions |
non_functional |
|
swagger |
swagger |
breaking |
|
info |
nested |
||
host |
breaking |
Where the API is served. | |
basePath |
breaking |
||
schemes |
add_item: non_breaking, remove_item: breaking |
||
consumes |
add_item: non_breaking, remove_item: breaking |
Media types the API accepts; clients may send the removed ones. | |
produces |
add_item: breaking, remove_item: non_breaking |
Media types the API returns; clients may not accept the new ones. | |
paths |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
definitions |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
parameters |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
responses |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
securityDefinitions |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
security |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, modify_item: nested |
add_item: Requirements are alternatives: adding one to existing ones is harmless, but requiring authentication where none was required breaks clients. |
|
tags |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
externalDocs |
add: non_breaking, remove: non_breaking, modify: nested |
||
info |
title |
breaking |
|
description |
non_functional |
||
termsOfService |
breaking |
||
contact |
nested |
||
license |
add: breaking, remove: non_breaking, modify: nested |
||
version |
none |
||
contact |
name |
add: non_breaking, remove: breaking, modify: non_breaking |
|
url |
add: non_breaking, remove: breaking, modify: non_breaking |
||
email |
add: non_breaking, remove: breaking, modify: non_breaking |
||
license |
name |
breaking |
|
url |
breaking |
||
pathItem |
$ref |
breaking |
|
parameters |
add_item: {if: required, then: breaking, else: non_breaking}, remove_item: breaking, modify_item: nested |
||
operations |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
remove_item: To allow removing deprecated operations, use remove_item: { if: deprecated, then: non_breaking, else: breaking }. |
|
operation |
tags |
non_breaking |
|
summary |
non_functional |
||
description |
non_functional |
||
externalDocs |
non_functional |
||
operationId |
breaking |
||
consumes |
add_item: non_breaking, remove_item: breaking |
||
produces |
add_item: breaking, remove_item: non_breaking |
||
parameters |
add_item: {if: required, then: breaking, else: non_breaking}, remove_item: breaking, modify_item: nested |
||
responses |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
schemes |
add_item: non_breaking, remove_item: breaking |
||
deprecated |
modify: {if: true, then: breaking, else: non_breaking} |
||
security |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, modify_item: nested |
||
parameter |
name |
breaking |
|
in |
breaking |
||
description |
non_functional |
||
required |
modify: {if: true, then: breaking, else: non_breaking} |
||
schema |
add: breaking, remove: breaking, modify: nested |
The schema of a body parameter. | |
type |
breaking |
||
format |
breaking |
||
allowEmptyValue |
modify: {if: true, then: non_breaking, else: breaking} |
||
items |
add: breaking, remove: breaking, modify: nested |
||
collectionFormat |
breaking |
||
default |
breaking |
||
multipleOf |
breaking |
||
maximum |
breaking |
||
exclusiveMaximum |
breaking |
||
minimum |
breaking |
||
exclusiveMinimum |
breaking |
||
maxLength |
breaking |
||
minLength |
breaking |
||
pattern |
breaking |
||
maxItems |
breaking |
||
minItems |
breaking |
||
uniqueItems |
breaking |
||
enum |
add_item: breaking, remove_item: breaking |
||
response |
description |
non_functional |
|
schema |
add: breaking, remove: breaking, modify: nested |
||
headers |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
examples |
non_functional |
||
header |
description |
non_functional |
|
type |
breaking |
||
format |
breaking |
||
items |
add: breaking, remove: breaking, modify: nested |
||
collectionFormat |
breaking |
||
default |
breaking |
||
multipleOf |
breaking |
||
maximum |
breaking |
||
exclusiveMaximum |
breaking |
||
minimum |
breaking |
||
exclusiveMinimum |
breaking |
||
maxLength |
breaking |
||
minLength |
breaking |
||
pattern |
breaking |
||
maxItems |
breaking |
||
minItems |
breaking |
||
uniqueItems |
breaking |
||
enum |
add_item: breaking, remove_item: breaking |
||
items |
type |
breaking |
|
format |
breaking |
||
items |
add: breaking, remove: breaking, modify: nested |
||
collectionFormat |
breaking |
||
default |
breaking |
||
multipleOf |
breaking |
||
maximum |
breaking |
||
exclusiveMaximum |
breaking |
||
minimum |
breaking |
||
exclusiveMinimum |
breaking |
||
maxLength |
breaking |
||
minLength |
breaking |
||
pattern |
breaking |
||
maxItems |
breaking |
||
minItems |
breaking |
||
uniqueItems |
breaking |
||
enum |
add_item: breaking, remove_item: breaking |
||
schema |
title |
non_breaking |
|
description |
non_functional |
||
type |
breaking |
||
format |
breaking |
||
default |
breaking |
||
multipleOf |
breaking |
||
maximum |
breaking |
||
exclusiveMaximum |
breaking |
||
minimum |
breaking |
||
exclusiveMinimum |
breaking |
||
maxLength |
breaking |
||
minLength |
breaking |
||
pattern |
breaking |
||
maxItems |
breaking |
||
minItems |
breaking |
||
uniqueItems |
breaking |
||
enum |
add_item: breaking, remove_item: breaking |
||
items |
add: breaking, remove: non_breaking, modify: nested |
||
allOf |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
properties |
add_item: non_breaking, remove_item: non_breaking, modify_item: nested |
||
required |
breaking |
||
maxProperties |
breaking |
||
minProperties |
breaking |
||
additionalProperties |
add: breaking, remove: breaking, modify: nested |
add when additional properties become allowed, remove when they become forbidden, modify for changes of the schema of additional properties. |
|
discriminator |
breaking |
||
readOnly |
non_functional |
||
xml |
nested |
||
externalDocs |
non_functional |
||
example |
non_functional |
||
xml |
name |
breaking |
|
namespace |
breaking |
||
prefix |
breaking |
||
attribute |
breaking |
||
wrapped |
breaking |
||
securityScheme |
type |
breaking |
|
description |
non_functional |
||
name |
breaking |
||
in |
breaking |
||
flow |
breaking |
||
authorizationUrl |
breaking |
||
tokenUrl |
breaking |
||
scopes |
add_item: breaking, remove_item: breaking, modify_item: non_functional |
||
securityRequirement |
scopes |
add_item: breaking, remove_item: non_breaking |
Clients may not have tokens with the new scopes. |
tag |
name |
breaking |
|
description |
non_functional |
||
externalDocs |
non_functional |
||
externalDocumentation |
description |
non_functional |
|
url |
non_functional |
Severities that depend on the direction of data flow. They override rules in requests (parameters, including body parameters; sent by API clients) and responses (sent by the API). Changes in places shared by both (e.g. definitions) get the stricter of the request and the response severity.
These defaults assume that servers and clients ignore unknown properties. For clients that reject them, set response.schema.properties.add_item to breaking.
The request layer, for the parameters, replaces these rules of the layer above:
| Node type | Property | Rule | Note |
|---|---|---|---|
schema |
properties |
add_item: {if: required, then: breaking, else: non_breaking}, remove_item: non_breaking |
add_item: Existing clients don’t send new required properties. |
required |
add_item: breaking, remove_item: non_breaking |
||
enum |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, remove_last_item: non_breaking |
add_first_item: Restricting a value to a set of values. |
|
additionalProperties |
add: non_breaking, remove: breaking |
||
parameter |
enum |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, remove_last_item: non_breaking |
|
items |
enum |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, remove_last_item: non_breaking |
The response layer, for the responses, replaces these:
| Node type | Property | Rule | Note |
|---|---|---|---|
schema |
properties |
add_item: non_breaking, remove_item: breaking |
remove_item: Existing clients may rely on the removed property. |
required |
add_item: non_breaking, remove_item: breaking |
||
enum |
add_item: breaking, add_first_item: non_breaking, remove_item: non_breaking, remove_last_item: breaking |
add_item: Existing clients may not handle new values. |
|
additionalProperties |
add: non_breaking, remove: non_breaking |
||
header |
enum |
add_item: breaking, add_first_item: non_breaking, remove_item: non_breaking, remove_last_item: breaking |
|
items |
enum |
add_item: breaking, add_first_item: non_breaking, remove_item: non_breaking, remove_last_item: breaking |
AsyncAPI
| Node type | Property | Rule | Note |
|---|---|---|---|
defaults |
extensions |
non_functional |
|
asyncapi |
asyncapi |
non_breaking |
The specification version; minor versions of AsyncAPI 3 are compatible. |
id |
breaking |
||
info |
nested |
||
servers |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
defaultContentType |
breaking |
||
channels |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
operations |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
components |
nested |
||
info |
title |
non_functional |
|
version |
none |
||
description |
non_functional |
||
termsOfService |
non_breaking |
||
contact |
nested |
||
license |
add: breaking, remove: non_breaking, modify: nested |
||
tags |
non_functional |
||
externalDocs |
non_functional |
||
contact |
name |
non_functional |
|
url |
non_functional |
||
email |
non_functional |
||
license |
name |
breaking |
|
url |
breaking |
||
server |
host |
breaking |
|
protocol |
breaking |
||
protocolVersion |
breaking |
||
pathname |
breaking |
||
description |
non_functional |
||
title |
non_functional |
||
summary |
non_functional |
||
variables |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
security |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, modify_item: nested |
add_item: Security schemes are alternatives: adding one to existing ones is harmless, but requiring authentication where none was required breaks clients. |
|
tags |
non_functional |
||
externalDocs |
non_functional |
||
bindings |
nested |
||
serverVariable |
enum |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, remove_last_item: non_breaking |
|
default |
breaking |
||
description |
non_functional |
||
examples |
non_functional |
||
channel |
address |
breaking |
|
messages |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
title |
non_functional |
||
summary |
non_functional |
||
description |
non_functional |
||
servers |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, remove_last_item: non_breaking |
add_item: A channel without servers is available on all servers. |
|
parameters |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
tags |
non_functional |
||
externalDocs |
non_functional |
||
bindings |
nested |
||
parameter |
enum |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, remove_last_item: non_breaking |
|
default |
breaking |
||
description |
non_functional |
||
examples |
non_functional |
||
location |
breaking |
||
operation |
action |
breaking |
|
channel |
breaking |
||
title |
non_functional |
||
summary |
non_functional |
||
description |
non_functional |
||
security |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, modify_item: nested |
||
tags |
non_functional |
||
externalDocs |
non_functional |
||
bindings |
nested |
||
traits |
nested |
Traits are applied to the operation, so their changes are the operation’s changes. | |
messages |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, remove_last_item: non_breaking |
add_item: An operation without messages uses all messages of its channel. |
|
reply |
add: breaking, remove: breaking, modify: nested |
||
operationTrait |
title |
non_functional |
|
summary |
non_functional |
||
description |
non_functional |
||
security |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, modify_item: nested |
||
tags |
non_functional |
||
externalDocs |
non_functional |
||
bindings |
nested |
||
operationReply |
address |
nested |
|
channel |
breaking |
||
messages |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, remove_last_item: non_breaking |
||
operationReplyAddress |
description |
non_functional |
|
location |
breaking |
||
message |
headers |
add: breaking, remove: breaking, modify: nested |
|
payload |
add: breaking, remove: breaking, modify: nested |
||
correlationId |
add: non_breaking, remove: breaking, modify: nested |
||
contentType |
breaking |
||
name |
non_breaking |
||
title |
non_functional |
||
summary |
non_functional |
||
description |
non_functional |
||
tags |
non_functional |
||
externalDocs |
non_functional |
||
bindings |
nested |
||
examples |
non_functional |
||
traits |
nested |
Traits are applied to the message, so their changes are the message’s changes. | |
messageTrait |
headers |
add: breaking, remove: breaking, modify: nested |
|
correlationId |
add: non_breaking, remove: breaking, modify: nested |
||
contentType |
breaking |
||
name |
non_breaking |
||
title |
non_functional |
||
summary |
non_functional |
||
description |
non_functional |
||
tags |
non_functional |
||
externalDocs |
non_functional |
||
bindings |
nested |
||
examples |
non_functional |
||
messageExample |
headers |
non_functional |
|
payload |
non_functional |
||
name |
non_functional |
||
summary |
non_functional |
||
correlationId |
description |
non_functional |
|
location |
breaking |
||
tag |
name |
non_functional |
|
description |
non_functional |
||
externalDocs |
non_functional |
||
externalDocumentation |
description |
non_functional |
|
url |
non_functional |
||
components |
schemas |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
|
servers |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
channels |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
operations |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
messages |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
securitySchemes |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
serverVariables |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
parameters |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
correlationIds |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
replies |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
replyAddresses |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
externalDocs |
non_functional |
||
tags |
non_functional |
||
operationTraits |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
messageTraits |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
serverBindings |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
channelBindings |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
operationBindings |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
messageBindings |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
schema |
id |
breaking |
|
dialect |
breaking |
||
comment |
none |
||
title |
non_functional |
||
description |
non_functional |
||
type |
breaking |
||
enum |
add_item: breaking, remove_item: breaking |
||
const |
breaking |
||
default |
breaking |
||
examples |
non_functional |
||
readOnly |
non_functional |
||
writeOnly |
non_functional |
||
deprecated |
non_breaking |
||
format |
breaking |
||
contentEncoding |
breaking |
||
contentMediaType |
breaking |
||
multipleOf |
breaking |
||
maximum |
breaking |
||
exclusiveMaximum |
breaking |
||
minimum |
breaking |
||
exclusiveMinimum |
breaking |
||
maxLength |
breaking |
||
minLength |
breaking |
||
pattern |
breaking |
||
items |
add: breaking, remove: non_breaking, modify: nested |
||
tupleItems |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
additionalItems |
add: breaking, remove: breaking, modify: nested |
||
maxItems |
breaking |
||
minItems |
breaking |
||
uniqueItems |
breaking |
||
contains |
add: breaking, remove: breaking, modify: nested |
||
maxProperties |
breaking |
||
minProperties |
breaking |
||
required |
breaking |
||
properties |
add_item: non_breaking, remove_item: non_breaking, modify_item: nested |
||
patternProperties |
add_item: non_breaking, remove_item: non_breaking, modify_item: nested |
||
additionalProperties |
breaking |
||
dependencies |
breaking |
||
propertyNames |
non_breaking |
||
if |
add: breaking, remove: breaking, modify: nested |
||
then |
add: breaking, remove: breaking, modify: nested |
||
else |
add: breaking, remove: breaking, modify: nested |
||
allOf |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
anyOf |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
oneOf |
add_item: breaking, remove_item: breaking, modify_item: nested |
||
not |
add: breaking, remove: breaking, modify: nested |
||
discriminator |
breaking |
||
externalDocs |
non_functional |
||
multiFormatSchema |
schemaFormat |
breaking |
|
schema |
nested |
||
untypedSchema |
breaking |
Schemas in formats without a typed model, e.g. Avro, are compared as whole values. | |
reference |
ref |
breaking |
A reference the document can’t follow (to another file or a URL) is compared by its $ref: another one may lead to anything. |
securityScheme |
type |
breaking |
|
description |
non_functional |
||
name |
breaking |
||
in |
breaking |
||
scheme |
breaking |
||
bearerFormat |
breaking |
||
flows |
add: breaking, remove: breaking, modify: nested |
||
openIdConnectUrl |
breaking |
||
scopes |
add_item: breaking, remove_item: non_breaking |
add_item: The scopes a server or an operation requires. |
|
oauthFlows |
implicit |
add: breaking, remove: breaking, modify: nested |
|
password |
add: breaking, remove: breaking, modify: nested |
||
clientCredentials |
add: breaking, remove: breaking, modify: nested |
||
authorizationCode |
add: breaking, remove: breaking, modify: nested |
||
oauthFlow |
authorizationUrl |
breaking |
|
tokenUrl |
breaking |
||
refreshUrl |
breaking |
||
availableScopes |
add_item: breaking, remove_item: breaking, modify_item: non_functional |
||
serverBindings |
protocols |
add_item: breaking, remove_item: breaking, modify_item: nested |
|
untyped |
breaking |
Bindings of protocols without a typed model are compared as a whole. | |
channelBindings |
protocols |
add_item: breaking, remove_item: breaking, modify_item: nested |
|
untyped |
breaking |
||
operationBindings |
protocols |
add_item: breaking, remove_item: breaking, modify_item: nested |
|
untyped |
breaking |
||
messageBindings |
protocols |
add_item: breaking, remove_item: breaking, modify_item: nested |
|
untyped |
breaking |
||
httpOperationBinding |
bindingVersion |
non_breaking |
|
method |
breaking |
||
query |
add: breaking, remove: breaking, modify: nested |
||
httpMessageBinding |
bindingVersion |
non_breaking |
|
headers |
add: breaking, remove: breaking, modify: nested |
||
statusCode |
breaking |
||
webSocketsChannelBinding |
bindingVersion |
non_breaking |
|
method |
breaking |
||
query |
add: breaking, remove: breaking, modify: nested |
||
headers |
add: breaking, remove: breaking, modify: nested |
||
kafkaServerBinding |
bindingVersion |
non_breaking |
|
schemaRegistryUrl |
breaking |
||
schemaRegistryVendor |
breaking |
||
kafkaChannelBinding |
bindingVersion |
non_breaking |
|
topic |
breaking |
||
partitions |
breaking |
||
replicas |
breaking |
||
topicConfiguration |
add: breaking, remove: breaking, modify: nested |
||
kafkaTopicConfiguration |
cleanupPolicy |
breaking |
|
retentionMs |
breaking |
||
retentionBytes |
breaking |
||
deleteRetentionMs |
breaking |
||
maxMessageBytes |
breaking |
||
confluentKeySchemaValidation |
breaking |
||
confluentKeySubjectNameStrategy |
breaking |
||
confluentValueSchemaValidation |
breaking |
||
confluentValueSubjectNameStrategy |
breaking |
||
kafkaOperationBinding |
bindingVersion |
non_breaking |
|
groupId |
add: breaking, remove: breaking, modify: nested |
||
clientId |
add: breaking, remove: breaking, modify: nested |
||
kafkaMessageBinding |
bindingVersion |
non_breaking |
|
key |
add: breaking, remove: breaking, modify: nested |
||
schemaIdLocation |
breaking |
||
schemaIdPayloadEncoding |
breaking |
||
schemaLookupStrategy |
breaking |
||
amqpChannelBinding |
bindingVersion |
non_breaking |
|
is |
breaking |
||
exchange |
add: breaking, remove: breaking, modify: nested |
||
queue |
add: breaking, remove: breaking, modify: nested |
||
amqpExchange |
name |
breaking |
|
type |
breaking |
||
durable |
breaking |
||
autoDelete |
breaking |
||
vhost |
breaking |
||
amqpQueue |
name |
breaking |
|
durable |
breaking |
||
exclusive |
breaking |
||
autoDelete |
breaking |
||
vhost |
breaking |
||
amqpOperationBinding |
bindingVersion |
non_breaking |
|
expiration |
breaking |
||
userId |
breaking |
||
cc |
breaking |
||
priority |
breaking |
||
deliveryMode |
breaking |
||
mandatory |
breaking |
||
bcc |
breaking |
||
timestamp |
breaking |
||
ack |
breaking |
||
amqpMessageBinding |
bindingVersion |
non_breaking |
|
contentEncoding |
breaking |
||
messageType |
breaking |
||
mqttServerBinding |
bindingVersion |
non_breaking |
|
clientId |
breaking |
||
cleanSession |
breaking |
||
lastWill |
add: breaking, remove: breaking, modify: nested |
||
keepAlive |
breaking |
||
sessionExpiryInterval |
breaking |
||
maximumPacketSize |
breaking |
||
mqttLastWill |
topic |
breaking |
|
qos |
breaking |
||
message |
breaking |
||
retain |
breaking |
||
mqttOperationBinding |
bindingVersion |
non_breaking |
|
qos |
breaking |
||
retain |
breaking |
||
messageExpiryInterval |
breaking |
||
mqttMessageBinding |
bindingVersion |
non_breaking |
|
payloadFormatIndicator |
breaking |
||
correlationData |
add: breaking, remove: breaking, modify: nested |
||
contentType |
breaking |
||
responseTopic |
breaking |
Severities that depend on the direction in which messages flow, from the point of view of the application the document describes. They override rules for messages the application receives (used by receive operations; sent by other parties) and for messages it sends (used by send operations; received by other parties). Replies flow the other way than the messages of their operation. Messages used in both directions, or by no operation (e.g. component messages), get the stricter of the receive and the send severity.
These defaults assume that applications ignore unknown message properties. For receivers that reject them, set send.schema.properties.add_item to breaking.
The receive layer, for the messages of receive operations, replaces these rules of the layer above:
| Node type | Property | Rule | Note |
|---|---|---|---|
message |
correlationId |
add: breaking |
add: Senders don’t provide the new correlation ID yet. |
schema |
properties |
add_item: {if: required, then: breaking, else: non_breaking}, remove_item: non_breaking |
add_item: Existing senders don’t send new required properties. |
required |
add_item: breaking, remove_item: non_breaking |
||
enum |
add_item: non_breaking, add_first_item: breaking, remove_item: breaking, remove_last_item: non_breaking |
add_first_item: Restricting a value to a set of values. |
The send layer, for the messages of send operations, replaces these:
| Node type | Property | Rule | Note |
|---|---|---|---|
message |
correlationId |
add: non_breaking |
|
schema |
properties |
add_item: non_breaking, remove_item: breaking |
remove_item: Existing receivers may rely on the removed property. |
required |
add_item: non_breaking, remove_item: breaking |
||
enum |
add_item: breaking, add_first_item: non_breaking, remove_item: non_breaking, remove_last_item: breaking |
add_item: Existing receivers may not handle new values. |
Protobuf
Severities of changes between two versions of a Protobuf (proto3) file.
A change is breaking when it breaks the programs that use the file: those exchanging encoded messages (the binary or the JSON encoding) and those compiled with the code generated from it.
| Node type | Property | Rule | Note |
|---|---|---|---|
defaults |
options |
non_breaking |
An option may change the behaviour of the generated code or of the tools that read it; options known to break their users are listed per node type below. |
file |
package |
breaking |
The package is a part of the names of all types and of the paths of gRPC methods. |
imports |
add_item: non_functional, remove_item: non_functional, modify_item: nested |
||
messages |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
enums |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
services |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
extends |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
Extend blocks, by the extended type. | |
comment |
non_functional |
The comment of the syntax statement. | |
options.cc_enable_arenas |
breaking |
These decide the names and the layout of the generated code. | |
options.cc_generic_services |
breaking |
||
options.csharp_namespace |
breaking |
||
options.go_package |
breaking |
||
options.java_generic_services |
breaking |
||
options.java_multiple_files |
breaking |
||
options.java_outer_classname |
breaking |
||
options.java_package |
breaking |
||
options.java_string_check_utf8 |
breaking |
||
options.objc_class_prefix |
breaking |
||
options.optimize_for |
breaking |
||
options.php_class_prefix |
breaking |
||
options.php_generic_services |
breaking |
||
options.php_metadata_namespace |
breaking |
||
options.php_namespace |
breaking |
||
options.py_generic_services |
breaking |
||
options.ruby_package |
breaking |
||
options.swift_prefix |
breaking |
||
import |
kind |
breaking |
Files that import this one see the types of its public imports. |
message |
fields |
add_item: non_breaking, remove_item: {if: reserved, then: non_breaking, else: breaking}, modify_item: nested |
remove_item: A removed field breaks the code that uses it, unless its number is reserved: then the removal is deliberate, and the number can’t be taken by another field, which would misread the data of the old one. |
oneofs |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
messages |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
enums |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
extends |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
reservedNumbers |
add_item: non_breaking, remove_item: breaking |
A number or a name that is no longer reserved can be taken by a new field. | |
reservedNames |
add_item: non_breaking, remove_item: breaking |
||
comment |
non_functional |
||
options.message_set_wire_format |
breaking |
||
options.no_standard_descriptor_accessor |
breaking |
||
field |
name |
breaking |
The name is used by the JSON encoding and by the generated code. |
type |
breaking |
Some types are encoded the same way, e.g. int32 and int64; to accept such changes, use type: { modify: { if: wire_compatible, then: non_breaking, else: breaking } }. |
|
label |
breaking |
optional and repeated. |
|
oneof |
breaking |
Moving a field into or out of a oneof. | |
comment |
non_functional |
||
options.ctype |
breaking |
||
options.jstype |
breaking |
||
options.json_name |
breaking |
||
oneof |
comment |
non_functional |
|
enum |
values |
add_item: non_breaking, remove_item: {if: reserved, then: non_breaking, else: breaking}, modify_item: nested |
|
reservedNumbers |
add_item: non_breaking, remove_item: breaking |
||
reservedNames |
add_item: non_breaking, remove_item: breaking |
||
comment |
non_functional |
||
enumValue |
name |
breaking |
The name is used by the JSON encoding and by the generated code. |
comment |
non_functional |
||
service |
methods |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
|
comment |
non_functional |
||
method |
inputType |
breaking |
|
outputType |
breaking |
||
clientStreaming |
breaking |
||
serverStreaming |
breaking |
||
comment |
non_functional |
||
options.idempotency_level |
breaking |
||
options.(google.api.http) |
breaking |
The HTTP mapping of the method. | |
extend |
fields |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
|
comment |
non_functional |
GraphQL
Severities of changes between two versions of a GraphQL schema.
A change is breaking when operations that were valid for the old schema become invalid, or when clients can’t read their results any more. The rules follow graphql-js’s findBreakingChanges(); its “dangerous” changes, e.g. a new enum value or a changed default value, are non-breaking here.
| Node type | Property | Rule | Note |
|---|---|---|---|
defaults |
directives |
non_breaking |
Directives are mostly read by servers and tools; those known to change the meaning of the schema for clients are listed per node kind below. |
schema |
query |
add: non_breaking, remove: breaking, modify: breaking |
The root operation types. |
mutation |
add: non_breaking, remove: breaking, modify: breaking |
||
subscription |
add: non_breaking, remove: breaking, modify: breaking |
||
types |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
directiveDefinitions |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
description |
non_functional |
||
type |
kind |
breaking |
E.g. an object type that becomes an interface. |
scalar |
description |
non_functional |
|
directives.specifiedBy |
non_functional |
||
object |
interfaces |
add_item: non_breaking, remove_item: breaking |
Fragments on an interface no longer match the type. |
fields |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
description |
non_functional |
||
interface |
interfaces |
add_item: non_breaking, remove_item: breaking |
|
fields |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
||
description |
non_functional |
||
union |
members |
add_item: non_breaking, remove_item: breaking |
|
description |
non_functional |
||
enum |
values |
add_item: non_breaking, remove_item: breaking, modify_item: nested |
|
description |
non_functional |
||
enumValue |
description |
non_functional |
|
inputObject |
fields |
add_item: {if: required, then: breaking, else: non_breaking}, remove_item: breaking, modify_item: nested |
add_item: Operations that don’t give a value for a new required field become invalid. |
description |
non_functional |
||
directives.oneOf |
breaking |
Values of a @oneOf input object have exactly one field. | |
field |
type |
modify: {if: compatible, then: non_breaking, else: breaking} |
A field may become non-null, but not nullable; lists must stay lists. |
arguments |
add_item: {if: required, then: breaking, else: non_breaking}, remove_item: breaking, modify_item: nested |
||
description |
non_functional |
||
argument |
type |
modify: {if: compatible, then: non_breaking, else: breaking} |
An argument may become nullable, but not non-null. |
defaultValue |
add: non_breaking, remove: {if: required, then: breaking, else: non_breaking}, modify: non_breaking |
Operations that relied on the default value of a non-null argument become invalid. | |
description |
non_functional |
||
inputField |
type |
modify: {if: compatible, then: non_breaking, else: breaking} |
|
defaultValue |
add: non_breaking, remove: {if: required, then: breaking, else: non_breaking}, modify: non_breaking |
||
description |
non_functional |
||
directive |
arguments |
add_item: {if: required, then: breaking, else: non_breaking}, remove_item: breaking, modify_item: nested |
|
repeatable |
modify: {if: false, then: breaking, else: non_breaking} |
Documents that use the directive more than once at a location become invalid. | |
locations |
add_item: non_breaking, remove_item: breaking |
||
description |
non_functional |
See also
- diff: Every option of the command, the node types and keys of each standard, and the JSON report.
- Catch breaking changes in CI: The check in a pull request, and retiring an operation on a schedule.
- changelog: The changes between the revisions of a file in git, with the same rules.