---
title: Rules Reference
description: Complete catalogue of all 45 rules that Specdiff uses to classify changes, including direction-dependent severity and override options.
url: https://pr-1-b9e16090e83d.thally.app/specdiff/rules
---

# Rules Reference

Complete catalogue of all 45 rules that Specdiff uses to classify changes, including direction-dependent severity and override options.

Specdiff ships a fixed catalogue of 45 rules. Each rule has a stable code, a default severity (`breaking`, `warning`, or `info`), and a human-readable title. Rules are split into two groups: JSON Schema rules that also fire inside OpenAPI schemas, and OpenAPI-specific rules.

## JSON Schema rules

These 24 rules apply to both standalone JSON Schema diffs and to schemas embedded inside OpenAPI documents. Their `appliesTo` value is `"both"`.

| Code | Default Severity | Title |
|---|---|---|
| `type-changed` | breaking | Type changed |
| `property-removed` | breaking | Property removed |
| `property-added` | info | Optional property added |
| `required-property-added` | breaking | Required property added |
| `required-added` | breaking | Existing property became required |
| `required-removed` | info | Property no longer required |
| `enum-value-removed` | breaking | Enum value removed |
| `enum-value-added` | info | Enum value added |
| `additional-properties-restricted` | breaking | Additional properties restricted |
| `additional-properties-relaxed` | info | Additional properties relaxed |
| `constraint-tightened` | breaking | Constraint tightened |
| `constraint-relaxed` | info | Constraint relaxed |
| `format-changed` | warning | Format changed |
| `nullable-removed` | breaking | Null no longer accepted |
| `nullable-added` | info | Null now accepted |
| `default-changed` | warning | Default changed |
| `description-changed` | info | Description changed |
| `composition-variant-removed` | breaking | Composition variant removed |
| `composition-variant-added` | info | Composition variant added |
| `items-changed` | breaking | Array items definition changed shape |
| `const-changed` | breaking | Constant changed |
| `deprecated-added` | warning | Marked deprecated |
| `readonly-writeonly-changed` | warning | readOnly/writeOnly changed |
| `unresolved-ref` | warning | Unresolved $ref |

## OpenAPI rules

These 21 rules fire only when comparing OpenAPI 3.x documents. Their `appliesTo` value is `"openapi"`.

| Code | Default Severity | Title |
|---|---|---|
| `endpoint-removed` | breaking | Endpoint removed |
| `endpoint-added` | info | Endpoint added |
| `operation-removed` | breaking | Operation removed |
| `operation-added` | info | Operation added |
| `operation-id-changed` | warning | operationId changed |
| `parameter-removed` | breaking | Parameter removed |
| `required-parameter-added` | breaking | Required parameter added |
| `optional-parameter-added` | info | Optional parameter added |
| `parameter-required-changed` | breaking | Parameter required flag changed |
| `request-body-required-added` | breaking | Request body became required |
| `request-body-media-type-removed` | breaking | Request media type removed |
| `request-body-media-type-added` | info | Request media type added |
| `response-removed` | breaking | Response removed |
| `response-added` | info | Response added |
| `response-media-type-removed` | breaking | Response media type removed |
| `response-media-type-added` | info | Response media type added |
| `security-requirement-added` | breaking | Security requirement added |
| `security-requirement-removed` | info | Security requirement removed |
| `server-removed` | warning | Server removed |
| `server-added` | info | Server added |
| `deprecated-operation` | warning | Operation deprecated |

## Direction-dependent severity

Twelve rules produce different severities depending on whether a schema appears on the request side or the response side of an API. A change that restricts what a consumer can send (request) has a different impact than a change that restricts what a server returns (response).

| Rule | Request | Response | Neutral (default) |
|---|---|---|---|
| `required-added` | breaking | info | breaking |
| `required-property-added` | breaking | info | breaking |
| `required-removed` | info | breaking | info |
| `enum-value-added` | info | warning | info |
| `enum-value-removed` | breaking | info | breaking |
| `constraint-tightened` | breaking | info | breaking |
| `constraint-relaxed` | info | warning | info |
| `additional-properties-restricted` | breaking | info | breaking |
| `nullable-added` | info | breaking | info |
| `nullable-removed` | breaking | info | breaking |
| `composition-variant-added` | info | warning | info |
| `composition-variant-removed` | breaking | info | breaking |

All other rules use their default severity regardless of direction. For example, `type-changed`, `property-removed`, and `const-changed` are always breaking.

### How direction is applied

The `DiffOptions.direction` field controls which severity column is used:

- **JSON Schema diffs** (`diffJsonSchema`): direction defaults to `"neutral"`. You can set it to `"request"` or `"response"` to match the context where the schema is used.
- **OpenAPI diffs** (`diffOpenApi` and `diffDocuments` with OpenAPI input): direction is automatically derived per location. Parameters and request bodies use `"request"` severity. Responses use `"response"` severity. The `DiffOptions.direction` option is ignored.

```ts
import { diffJsonSchema } from "@specdiff/core";

// Request-side schema: restricting inputs is breaking
const result = diffJsonSchema(before, after, { direction: "request" });
```

## Overriding rule severity

Use `DiffOptions.overrides` to change the effective severity of any rule. Overrides take precedence over both the default severity and direction-dependent severity.

```ts
import { diffDocuments } from "@specdiff/core";

const result = diffDocuments(before, after, {
  overrides: {
    "default-changed": "breaking",
    "format-changed": "info",
  },
});
```

In the CLI, there is no direct override flag, but you can suppress rules entirely with `--ignore-rule`.

## Suppressing rules

Use `DiffOptions.ignoreRules` (library) or `--ignore-rule` (CLI) to remove all changes produced by specific rules from the result.

```ts
const result = diffDocuments(before, after, {
  ignoreRules: ["description-changed", "deprecated-added"],
});
```

```sh
npx specdiff before.yaml after.yaml --ignore-rule description-changed --ignore-rule deprecated-added
```

The `--ignore-rule` flag is repeatable. Passing an unknown rule code produces a usage error (exit code 2).

## Inspecting rules at runtime

The library and CLI both provide ways to explore the catalogue.

List all rules from the library:

```ts
import { listRules, explainRule, severityFor } from "@specdiff/core";

// Full catalogue
const allRules = listRules();

// Single rule lookup
const rule = explainRule("enum-value-removed");

// Direction-aware severity
const sev = severityFor("enum-value-removed", "response"); // "info"
```

From the CLI:

```sh
# Print all rules as a table
npx specdiff rules

# Print rules as JSON
npx specdiff rules --json

# Describe a single rule
npx specdiff explain enum-value-removed
```