diff --git a/.circleci/config.yml b/.circleci/config.yml
index 9ef615cc7..f7e564a85 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -5,7 +5,7 @@ jobs:
     working_directory: ~/openapi-diff
 
     docker:
-      - image: circleci/openjdk:8-jdk-node-browsers
+      - image: cimg/openjdk:8.0.442
 
     steps:
 
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 000000000..92322c4e0
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,2 @@
+.idea/
+target/
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 14e42bac9..2319723d5 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -34,11 +34,11 @@ jobs:
         java-version: ${{ matrix.java_version }}
         cache: 'maven'
         # Value of the distributionManagement/repository/id field of the pom.xml
-        server-id: sonatype-nexus-snapshots
+        server-id: central
         server-username: OSS_USERNAME
         server-password: OSS_PASSWORD
     - name: Cache SonarCloud packages
-      uses: actions/cache@v3
+      uses: actions/cache@v4
       if: ${{ env.SONAR_TOKEN != null && env.SONAR_TOKEN != '' && matrix.java_version == '17' }}
       env:
         SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index bdb76839f..d3a0a7bb7 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -29,7 +29,7 @@ jobs:
           java-version: ${{ matrix.java_version }}
           cache: 'maven'
       - name: Cache SonarCloud packages
-        uses: actions/cache@v3
+        uses: actions/cache@v4
         if: ${{ env.SONAR_TOKEN != null && env.SONAR_TOKEN != '' && matrix.java_version == '17' }}
         env:
           SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 58eb8973c..bf6474814 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -3,10 +3,10 @@ on:
   workflow_dispatch:
     inputs:
       releaseVersion:
-        description: 'Default version to use when preparing a release or a branch.'
+        description: 'Release version to tag (e.g., 2.1.0). Will be used for release artifacts and git tag.'
         required: true
       developmentVersion:
-        description: 'Default version to use for new local working copy.'
+        description: 'Next development version (e.g., 2.2.0-SNAPSHOT). Will be used for continuing development after release.'
         required: true
 env:
   OSS_USERNAME: ${{ secrets.OSS_USERNAME }}
@@ -24,7 +24,7 @@ jobs:
           java-version: 11
           cache: 'maven'
           # Value of the distributionManagement/repository/id field of the pom.xml
-          server-id: sonatype-nexus-staging
+          server-id: central
           gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
           server-username: OSS_USERNAME
           server-password: OSS_PASSWORD
@@ -59,7 +59,7 @@ jobs:
           username: ${{ secrets.DOCKER_HUB_USERNAME }}
           password: ${{ secrets.DOCKER_HUB_PASSWORD }}
       - name: Build & Push Docker image
-        uses: docker/build-push-action@v5
+        uses: docker/build-push-action@v6
         with:
           context: .
           push: true
diff --git a/.gitignore b/.gitignore
index 7956bcbd3..ae6375959 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,10 +2,11 @@
 
 .classpath
 .project
-.settings/*
-.idea
 *.iml
 
+# Maven configuration
+.mvn/maven.config
+
 # Mobile Tools for Java (J2ME)
 .mtj.tmp/
 
@@ -17,3 +18,9 @@
 # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
 hs_err_pid*
 target/
+
+# IDE files
+.settings
+.idea
+.vscode
+.mvn/maven.config
diff --git a/Dockerfile b/Dockerfile
index 72bd50130..b07fd3dda 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,10 +1,16 @@
-FROM openjdk:8-jdk-slim AS build
+FROM eclipse-temurin:21-jdk-alpine AS build
 WORKDIR /build
 COPY ./ /build
 RUN ./mvnw -V -B -ff -P docker package -q
 
-FROM openjdk:8-jre-slim
+FROM eclipse-temurin:21-jre-alpine
 WORKDIR /app
-COPY --from=build /build/cli/target/openapi-diff-cli-*-all.jar /app/openapi-diff.jar
-ENTRYPOINT ["java", "-jar", "/app/openapi-diff.jar"]
+COPY --from=build /build/cli/target/openapi-diff.jar /app/openapi-diff.jar
+COPY --from=build /build/core/src/test/resources/petstore_v2_* /tmp
+RUN java -XX:ArchiveClassesAtExit=/app/appcds.jsa \
+    -jar /app/openapi-diff.jar \
+    /tmp/petstore_v2_1.yaml \
+    /tmp/petstore_v2_2.yaml \
+    && rm -f /tmp/petstore_v2_*
+ENTRYPOINT ["java", "-Xshare:on", "-XX:SharedArchiveFile=/app/appcds.jsa", "-jar", "/app/openapi-diff.jar"]
 CMD ["--help"]
diff --git a/README.md b/README.md
index 60d722e7f..019cca0b5 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,16 @@
 # OpenAPI-diff 
 
-Compare two OpenAPI specifications (3.x) and render the difference to HTML plaintext, or Markdown files.
+Compare two OpenAPI specifications (3.x) and render the difference to HTML plaintext, Markdown files, or JSON files.
 
 [![Build](https://github.com/OpenAPITools/openapi-diff/workflows/Main%20Build/badge.svg)](https://github.com/OpenAPITools/openapi-diff/actions?query=branch%3Amaster+workflow%3A"Main+Build")
 [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=OpenAPITools_openapi-diff&metric=alert_status)](https://sonarcloud.io/dashboard?id=OpenAPITools_openapi-diff)
+
 [![Maven Central](https://img.shields.io/maven-central/v/org.openapitools.openapidiff/openapi-diff-core)](https://search.maven.org/artifact/org.openapitools.openapidiff/openapi-diff-core)
 
 [![Contribute with Gitpod](https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/OpenAPITools/openapi-diff)
-[![Join the Slack chat room](https://img.shields.io/badge/Slack-Join%20the%20chat%20room-orange)](https://join.slack.com/t/openapi-generator/shared_invite/enQtNzAyNDMyOTU0OTE1LTY5ZDBiNDI5NzI5ZjQ1Y2E5OWVjMjZkYzY1ZGM2MWQ4YWFjMzcyNDY5MGI4NjQxNDBiMTlmZTc5NjY2ZTQ5MGM)
+[![Join the Slack chat room](https://img.shields.io/badge/Slack-Join%20the%20chat%20room-orange)](https://join.slack.com/t/openapi-generator/shared_invite/zt-12jxxd7p2-XUeQM~4pzsU9x~eGLQqX2g)
 
-[![Docker Cloud Automated build](https://img.shields.io/docker/cloud/automated/openapitools/openapi-diff)](https://hub.docker.com/r/openapitools/openapi-diff)
-[![Docker Cloud Build Status](https://img.shields.io/docker/cloud/build/openapitools/openapi-diff)](https://hub.docker.com/r/openapitools/openapi-diff)
+[![Docker Automated build](https://img.shields.io/docker/automated/openapitools/openapi-diff)](https://hub.docker.com/r/openapitools/openapi-diff)
 [![Docker Image Version](https://img.shields.io/docker/v/openapitools/openapi-diff?sort=semver)](https://hub.docker.com/r/openapitools/openapi-diff/tags)
 
 # Requirements
@@ -23,7 +23,7 @@ Compare two OpenAPI specifications (3.x) and render the difference to HTML plain
 * Depth comparison of parameters, responses, endpoint, http method (GET,POST,PUT,DELETE...)
 * Supports swagger api Authorization
 * Render difference of property with Expression Language
-* HTML, Markdown & JSON render
+* HTML, Markdown, Asciidoc & JSON render
 
 # Maven
 
@@ -37,6 +37,14 @@ Available on [Maven Central](https://search.maven.org/artifact/org.openapitools.
 </dependency>
 ```
 
+# Homebrew
+Available for Mac users on [brew](https://formulae.brew.sh/formula/openapi-diff)
+
+```bash
+brew install openapi-diff
+```
+Usage instructions in [Usage -> Command line](#command-line)
+
 # Docker
 
 Available on [Docker Hub](https://hub.docker.com/r/openapitools/openapi-diff/) as `openapitools/openapi-diff`.
@@ -44,12 +52,15 @@ Available on [Docker Hub](https://hub.docker.com/r/openapitools/openapi-diff/) a
 ```bash
 # docker run openapitools/openapi-diff:latest
 usage: openapi-diff <old> <new>
+    --asciidoc <file>           export diff as asciidoc in given file
     --debug                     Print debugging information
     --error                     Print error information
     --fail-on-changed           Fail if API changed but is backward
                                 compatible
     --fail-on-incompatible      Fail only if API changes broke backward
                                 compatibility
+    --config-file               Config file to override default behavior. Supported file formats: .yaml
+    --config-prop               Config property to override default behavior with key:value format (e.g. my.prop:true)
  -h,--help                      print this message
     --header <property=value>   use given header for authorisation
     --html <file>               export diff as html in given file
@@ -68,7 +79,6 @@ usage: openapi-diff <old> <new>
     --warn                      Print warning information
 ```
 
-
 ## Build the image
 
 This is only required if you want to try new changes in the Dockerfile of this project.
@@ -101,6 +111,7 @@ openapi-diff can read OpenAPI specs from JSON files or HTTP URLs.
 ```bash
 $ openapi-diff --help
 usage: openapi-diff <old> <new>
+    --asciidoc <file>           export diff as asciidoc in given file
     --debug                     Print debugging information
     --error                     Print error information
  -h,--help                      print this message
@@ -117,6 +128,8 @@ usage: openapi-diff <old> <new>
                                 incompatible, compatible
     --fail-on-incompatible      Fail only if API changes broke backward compatibility
     --fail-on-changed           Fail if API changed but is backward compatible
+    --config-file               Config file to override default behavior. Supported file formats: .yaml
+    --config-prop               Config property to override default behavior with key:value format (e.g. my.prop:true)
     --trace                     be extra verbose
     --version                   print the version information and exit
     --warn                      Print warning information
@@ -151,6 +164,14 @@ Add openapi-diff to your POM to show diffs when you test your Maven project. You
         <jsonOutputFileName>${project.basedir}/../maven/target/diff.json</jsonOutputFileName>
         <!-- Supply file path for markdown output to file if desired. -->
         <markdownOutputFileName>${project.basedir}/../maven/target/diff.md</markdownOutputFileName>
+        <!-- Supply config file(s), e.g. to disable incompatibility checks. Later files override earlier files -->
+        <configFiles>
+          <configFile>my/config-file.yaml</configFile>
+        </configFiles>
+        <!-- Supply config properties, e.g. to disable incompatibility checks. Overrides configFiles. -->
+        <configProps>
+          <incompatible.response.enum.increased>false</incompatible.response.enum.increased>
+        </configProps>
       </configuration>
     </execution>
   </executions>
@@ -178,44 +199,37 @@ public class Main {
 #### HTML
 
 ```java
-String html = new HtmlRender("Changelog",
-        "http://deepoove.com/swagger-diff/stylesheets/demo.css")
-                .render(diff);
-
-try {
-    FileWriter fw = new FileWriter("testNewApi.html");
-    fw.write(html);
-    fw.close();
-} catch (IOException e) {
-    e.printStackTrace();
-}
+HtmlRender htmlRender = new HtmlRender("Changelog", "http://deepoove.com/swagger-diff/stylesheets/demo.css");
+FileOutputStream outputStream = new FileOutputStream("testDiff.html");
+OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+htmlRender.render(diff, outputStreamWriter);
 ```
 
 #### Markdown
 
 ```java
-String render = new MarkdownRender().render(diff);
-try {
-    FileWriter fw = new FileWriter("testDiff.md");
-    fw.write(render);
-    fw.close();
-} catch (IOException e) {
-    e.printStackTrace();
-}
+MarkdownRender markdownRender = new MarkdownRender();
+FileOutputStream outputStream = new FileOutputStream("testDiff.md");
+OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+markdownRender.render(diff, outputStreamWriter);
 ```
 
+#### Asciidoc
+
+```java
+AsciidocRender asciidocRender = new AsciidocRender();
+FileOutputStream outputStream = new FileOutputStream("testDiff.adoc");
+OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+asciidocRender.render(diff, outputStreamWriter);
+```
 
 #### JSON
 
 ```java
-String render = new JsonRender().render(diff);
-try {
-    FileWriter fw = new FileWriter("testDiff.json");
-    fw.write(render);
-    fw.close();
-} catch (IOException e) {
-    e.printStackTrace();
-}
+JsonRender jsonRender = new JsonRender();
+FileOutputStream outputStream = new FileOutputStream("testDiff.json");
+OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+jsonRender.render(diff, outputStreamWriter);
 ```
 
 ### Extensions
diff --git a/cli/pom.xml b/cli/pom.xml
index 6f11bc038..f2bec76a8 100644
--- a/cli/pom.xml
+++ b/cli/pom.xml
@@ -4,7 +4,7 @@
     <parent>
         <groupId>org.openapitools.openapidiff</groupId>
         <artifactId>openapi-diff-parent</artifactId>
-        <version>2.1.0-SNAPSHOT</version>
+        <version>2.2.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>openapi-diff-cli</artifactId>
@@ -13,6 +13,10 @@
     <name>openapi-diff-cli</name>
     <description>CLI for openapi-diff</description>
 
+    <properties>
+        <mainClass>org.openapitools.openapidiff.cli.Main</mainClass>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>org.openapitools.openapidiff</groupId>
@@ -52,7 +56,7 @@
                             <shadedClassifierName>all</shadedClassifierName>
                             <transformers>
                                 <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
-                                    <mainClass>org.openapitools.openapidiff.cli.Main</mainClass>
+                                    <mainClass>${mainClass}</mainClass>
                                 </transformer>
                               <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                               <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer" />
@@ -64,4 +68,41 @@
             </plugin>
         </plugins>
     </build>
+
+    <profiles>
+        <profile>
+            <id>docker</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-shade-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>package</phase>
+                                <goals>
+                                    <goal>shade</goal>
+                                </goals>
+                                <configuration>
+                                    <createDependencyReducedPom>false</createDependencyReducedPom>
+                                    <finalName>openapi-diff</finalName>
+                                    <transformers>
+                                        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                                            <mainClass>${mainClass}</mainClass>
+                                            <manifestEntries>
+                                                <Implementation-Version>${project.version}</Implementation-Version>
+                                            </manifestEntries>
+                                        </transformer>
+                                        <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
+                                        <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer" />
+                                        <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer" />
+                                    </transformers>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
 </project>
diff --git a/cli/src/main/java/org/openapitools/openapidiff/cli/Main.java b/cli/src/main/java/org/openapitools/openapidiff/cli/Main.java
index f19826a93..a9e223d27 100644
--- a/cli/src/main/java/org/openapitools/openapidiff/cli/Main.java
+++ b/cli/src/main/java/org/openapitools/openapidiff/cli/Main.java
@@ -3,6 +3,7 @@
 import ch.qos.logback.classic.Level;
 import io.swagger.v3.parser.core.models.AuthorizationValue;
 import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.FileOutputStream;
 import java.io.OutputStreamWriter;
 import java.util.Collections;
@@ -16,7 +17,9 @@
 import org.apache.commons.cli.ParseException;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.openapitools.openapidiff.core.OpenApiCompare;
+import org.openapitools.openapidiff.core.compare.OpenApiDiffOptions;
 import org.openapitools.openapidiff.core.model.ChangedOpenApi;
+import org.openapitools.openapidiff.core.output.AsciidocRender;
 import org.openapitools.openapidiff.core.output.ConsoleRender;
 import org.openapitools.openapidiff.core.output.HtmlRender;
 import org.openapitools.openapidiff.core.output.JsonRender;
@@ -32,7 +35,10 @@ public static void main(String... args) {
     Options options = new Options();
     options.addOption(Option.builder("h").longOpt("help").desc("print this message").build());
     options.addOption(
-        Option.builder().longOpt("version").desc("print the version information and exit").build());
+        Option.builder("v")
+            .longOpt("version")
+            .desc("print the version information and exit")
+            .build());
     options.addOption(
         Option.builder()
             .longOpt("state")
@@ -48,6 +54,19 @@ public static void main(String... args) {
             .longOpt("fail-on-changed")
             .desc("Fail if API changed but is backward compatible")
             .build());
+    options.addOption(
+        Option.builder()
+            .longOpt("config-file")
+            .hasArg()
+            .desc("Config file to override default behavior. Supported file formats: .yaml")
+            .build());
+    options.addOption(
+        Option.builder()
+            .longOpt("config-prop")
+            .hasArg()
+            .desc(
+                "Config property to override default behavior. Arg in format of [propKey]:[propVal]")
+            .build());
     options.addOption(Option.builder().longOpt("trace").desc("be extra verbose").build());
     options.addOption(
         Option.builder().longOpt("debug").desc("Print debugging information").build());
@@ -56,6 +75,7 @@ public static void main(String... args) {
     options.addOption(Option.builder().longOpt("warn").desc("Print warning information").build());
     options.addOption(Option.builder().longOpt("error").desc("Print error information").build());
     options.addOption(Option.builder().longOpt("off").desc("No information printed").build());
+    options.addOption(Option.builder().longOpt("off").desc("No information printed").build());
     options.addOption(
         Option.builder("l")
             .longOpt("log")
@@ -88,12 +108,26 @@ public static void main(String... args) {
             .argName("file")
             .desc("export diff as markdown in given file")
             .build());
+    options.addOption(
+        Option.builder()
+            .longOpt("asciidoc")
+            .hasArg()
+            .argName("file")
+            .desc("export diff as asciidoc in given file")
+            .build());
     options.addOption(
         Option.builder()
             .longOpt("html")
             .hasArg()
             .argName("file")
-            .desc("export diff as html in given file")
+            .desc("export diff as html in given file with incompatible changes")
+            .build());
+    options.addOption(
+        Option.builder()
+            .longOpt("html-detailed")
+            .hasArg()
+            .argName("file")
+            .desc("export diff as html in given file with all changes")
             .build());
     options.addOption(
         Option.builder()
@@ -119,6 +153,11 @@ public static void main(String... args) {
         printHelp(options);
         System.exit(0);
       }
+      if (line.hasOption("version") || line.hasOption("v")) {
+        String version = Main.class.getPackage().getImplementationVersion();
+        System.out.println("openapi-diff version: " + (version != null ? version : "DEV"));
+        System.exit(0);
+      }
       String logLevel = "ERROR";
       if (line.hasOption("off")) {
         logLevel = "OFF";
@@ -171,7 +210,27 @@ public static void main(String... args) {
         auths = Collections.singletonList(new AuthorizationValue(headers[0], headers[1], "header"));
       }
 
-      ChangedOpenApi result = OpenApiCompare.fromLocations(oldPath, newPath, auths);
+      OpenApiDiffOptions.Builder optionBuilder = OpenApiDiffOptions.builder();
+      String[] configFilePaths = line.getOptionValues("config-file");
+      if (configFilePaths != null) {
+        for (String configFilePath : configFilePaths) {
+          optionBuilder.configYaml(new File(configFilePath));
+        }
+      }
+
+      String[] configProps = line.getOptionValues("config-prop");
+      if (configProps != null) {
+        for (String propKeyAndVal : configProps) {
+          String[] split = propKeyAndVal.split(":");
+          if (split.length != 2 || split[0].isEmpty() || split[1].isEmpty()) {
+            throw new IllegalArgumentException("--config-prop unexpected format: " + propKeyAndVal);
+          }
+          optionBuilder.configProperty(split[0], split[1]);
+        }
+      }
+      OpenApiDiffOptions compareOpts = optionBuilder.build();
+
+      ChangedOpenApi result = OpenApiCompare.fromLocations(oldPath, newPath, auths, compareOpts);
       ConsoleRender consoleRender = new ConsoleRender();
       if (!logLevel.equals("OFF")) {
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
@@ -185,12 +244,24 @@ public static void main(String... args) {
         OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
         htmlRender.render(result, outputStreamWriter);
       }
+      if (line.hasOption("html-detailed")) {
+        HtmlRender htmlRender = new HtmlRender(true);
+        FileOutputStream outputStream = new FileOutputStream(line.getOptionValue("html-detailed"));
+        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+        htmlRender.render(result, outputStreamWriter);
+      }
       if (line.hasOption("markdown")) {
         MarkdownRender mdRender = new MarkdownRender();
         FileOutputStream outputStream = new FileOutputStream(line.getOptionValue("markdown"));
         OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
         mdRender.render(result, outputStreamWriter);
       }
+      if (line.hasOption("asciidoc")) {
+        AsciidocRender adocRender = new AsciidocRender();
+        FileOutputStream outputStream = new FileOutputStream(line.getOptionValue("asciidoc"));
+        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+        adocRender.render(result, outputStreamWriter);
+      }
       if (line.hasOption("text")) {
         FileOutputStream outputStream = new FileOutputStream(line.getOptionValue("text"));
         OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
diff --git a/core/pom.xml b/core/pom.xml
index 50b8ce87d..ca3b59d86 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -4,7 +4,7 @@
     <parent>
         <groupId>org.openapitools.openapidiff</groupId>
         <artifactId>openapi-diff-parent</artifactId>
-        <version>2.1.0-SNAPSHOT</version>
+        <version>2.2.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>openapi-diff-core</artifactId>
@@ -40,6 +40,10 @@
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-collections4</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-configuration2</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/OpenApiCompare.java b/core/src/main/java/org/openapitools/openapidiff/core/OpenApiCompare.java
index 4564733a5..daa3af9b1 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/OpenApiCompare.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/OpenApiCompare.java
@@ -7,6 +7,7 @@
 import java.io.File;
 import java.util.List;
 import org.openapitools.openapidiff.core.compare.OpenApiDiff;
+import org.openapitools.openapidiff.core.compare.OpenApiDiffOptions;
 import org.openapitools.openapidiff.core.model.ChangedOpenApi;
 
 public class OpenApiCompare {
@@ -40,7 +41,25 @@ public static ChangedOpenApi fromContents(String oldContent, String newContent)
    */
   public static ChangedOpenApi fromContents(
       String oldContent, String newContent, List<AuthorizationValue> auths) {
-    return fromSpecifications(readContent(oldContent, auths), readContent(newContent, auths));
+    return fromContents(oldContent, newContent, auths, OpenApiDiffOptions.builder().build());
+  }
+
+  /**
+   * compare two openapi doc
+   *
+   * @param oldContent old api-doc location:Json or Http
+   * @param newContent new api-doc location:Json or Http
+   * @param auths
+   * @param options
+   * @return Comparison result
+   */
+  public static ChangedOpenApi fromContents(
+      String oldContent,
+      String newContent,
+      List<AuthorizationValue> auths,
+      OpenApiDiffOptions options) {
+    return fromSpecifications(
+        readContent(oldContent, auths), readContent(newContent, auths), options);
   }
 
   /**
@@ -64,7 +83,21 @@ public static ChangedOpenApi fromFiles(File oldFile, File newFile) {
    */
   public static ChangedOpenApi fromFiles(
       File oldFile, File newFile, List<AuthorizationValue> auths) {
-    return fromLocations(oldFile.getAbsolutePath(), newFile.getAbsolutePath(), auths);
+    return fromFiles(oldFile, newFile, auths, OpenApiDiffOptions.builder().build());
+  }
+
+  /**
+   * compare two openapi doc
+   *
+   * @param oldFile old api-doc file
+   * @param newFile new api-doc file
+   * @param auths
+   * @param options
+   * @return Comparison result
+   */
+  public static ChangedOpenApi fromFiles(
+      File oldFile, File newFile, List<AuthorizationValue> auths, OpenApiDiffOptions options) {
+    return fromLocations(oldFile.getAbsolutePath(), newFile.getAbsolutePath(), auths, options);
   }
 
   /**
@@ -88,7 +121,25 @@ public static ChangedOpenApi fromLocations(String oldLocation, String newLocatio
    */
   public static ChangedOpenApi fromLocations(
       String oldLocation, String newLocation, List<AuthorizationValue> auths) {
-    return fromSpecifications(readLocation(oldLocation, auths), readLocation(newLocation, auths));
+    return fromLocations(oldLocation, newLocation, auths, OpenApiDiffOptions.builder().build());
+  }
+
+  /**
+   * compare two openapi doc
+   *
+   * @param oldLocation old api-doc location (local or http)
+   * @param newLocation new api-doc location (local or http)
+   * @param auths
+   * @param options
+   * @return Comparison result
+   */
+  public static ChangedOpenApi fromLocations(
+      String oldLocation,
+      String newLocation,
+      List<AuthorizationValue> auths,
+      OpenApiDiffOptions options) {
+    return fromSpecifications(
+        readLocation(oldLocation, auths), readLocation(newLocation, auths), options);
   }
 
   /**
@@ -99,7 +150,20 @@ public static ChangedOpenApi fromLocations(
    * @return Comparison result
    */
   public static ChangedOpenApi fromSpecifications(OpenAPI oldSpec, OpenAPI newSpec) {
-    return OpenApiDiff.compare(notNull(oldSpec, "old"), notNull(newSpec, "new"));
+    return fromSpecifications(oldSpec, newSpec, OpenApiDiffOptions.builder().build());
+  }
+
+  /**
+   * compare two openapi doc
+   *
+   * @param oldSpec old api-doc specification
+   * @param newSpec new api-doc specification
+   * @param options
+   * @return Comparison result
+   */
+  public static ChangedOpenApi fromSpecifications(
+      OpenAPI oldSpec, OpenAPI newSpec, OpenApiDiffOptions options) {
+    return OpenApiDiff.compare(notNull(oldSpec, "old"), notNull(newSpec, "new"), options);
   }
 
   private static OpenAPI notNull(OpenAPI spec, String type) {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/ContentDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/ContentDiff.java
index b647172db..7cf27dca7 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/compare/ContentDiff.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/ContentDiff.java
@@ -5,7 +5,9 @@
 
 import io.swagger.v3.oas.models.media.Content;
 import io.swagger.v3.oas.models.media.MediaType;
-import java.util.*;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 import org.openapitools.openapidiff.core.model.Changed;
 import org.openapitools.openapidiff.core.model.ChangedContent;
 import org.openapitools.openapidiff.core.model.ChangedMediaType;
@@ -34,22 +36,15 @@ public DeferredChanged<ChangedContent> diff(Content left, Content right, DiffCon
               MediaType oldMediaType = left.get(mediaTypeKey);
               MediaType newMediaType = right.get(mediaTypeKey);
 
-              ChangedMediaType changedMediaType =
-                  new ChangedMediaType(oldMediaType.getSchema(), newMediaType.getSchema(), context);
-
               builder
                   .with(
                       openApiDiff
-                          .getSchemaDiff()
-                          .diff(
-                              oldMediaType.getSchema(),
-                              newMediaType.getSchema(),
-                              context.copyWithRequired(true)))
+                          .getMediaTypeDiff()
+                          .diff(oldMediaType, newMediaType, context.copyWithRequired(true)))
                   .ifPresent(
                       value -> {
-                        changedMediaType.setSchema(value);
-                        if (!isUnchanged(changedMediaType)) {
-                          changedMediaTypes.put(mediaTypeKey, changedMediaType);
+                        if (!isUnchanged(value)) {
+                          changedMediaTypes.put(mediaTypeKey, value);
                         }
                       });
             });
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/HeaderDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/HeaderDiff.java
index ecdfd5878..593c29df1 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/compare/HeaderDiff.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/HeaderDiff.java
@@ -4,8 +4,9 @@
 import io.swagger.v3.oas.models.headers.Header;
 import java.util.HashSet;
 import java.util.Objects;
-import java.util.Optional;
 import org.openapitools.openapidiff.core.model.Changed;
+import org.openapitools.openapidiff.core.model.ChangedExample;
+import org.openapitools.openapidiff.core.model.ChangedExamples;
 import org.openapitools.openapidiff.core.model.ChangedHeader;
 import org.openapitools.openapidiff.core.model.DiffContext;
 import org.openapitools.openapidiff.core.model.deferred.DeferredBuilder;
@@ -44,12 +45,12 @@ protected DeferredChanged<ChangedHeader> computeDiff(
     DeferredBuilder<Changed> builder = new DeferredBuilder<>();
     ChangedHeader changedHeader =
         new ChangedHeader(left, right, context)
-            .setRequired(getBooleanDiff(left.getRequired(), right.getRequired()))
-            .setDeprecated(
-                !Boolean.TRUE.equals(left.getDeprecated())
-                    && Boolean.TRUE.equals(right.getDeprecated()))
+            .setRequired(!Objects.equals(left.getRequired(), right.getRequired()))
+            .setDeprecated(!Objects.equals(left.getDeprecated(), right.getDeprecated()))
             .setStyle(!Objects.equals(left.getStyle(), right.getStyle()))
-            .setExplode(getBooleanDiff(left.getExplode(), right.getExplode()));
+            .setExplode(!Objects.equals(left.getExplode(), right.getExplode()))
+            .setExamples(new ChangedExamples(left.getExamples(), right.getExamples()))
+            .setExample(new ChangedExample(left.getExample(), right.getExample()));
     builder
         .with(
             openApiDiff
@@ -73,10 +74,4 @@ protected DeferredChanged<ChangedHeader> computeDiff(
         .ifPresent(changedHeader::setExtensions);
     return builder.buildIsChanged(changedHeader);
   }
-
-  private boolean getBooleanDiff(Boolean left, Boolean right) {
-    boolean leftRequired = Optional.ofNullable(left).orElse(Boolean.FALSE);
-    boolean rightRequired = Optional.ofNullable(right).orElse(Boolean.FALSE);
-    return leftRequired != rightRequired;
-  }
 }
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/MediaTypeDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/MediaTypeDiff.java
new file mode 100644
index 000000000..a80324a92
--- /dev/null
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/MediaTypeDiff.java
@@ -0,0 +1,40 @@
+package org.openapitools.openapidiff.core.compare;
+
+import static org.openapitools.openapidiff.core.utils.ChangedUtils.isChanged;
+
+import io.swagger.v3.oas.models.media.MediaType;
+import org.openapitools.openapidiff.core.model.Changed;
+import org.openapitools.openapidiff.core.model.ChangedExample;
+import org.openapitools.openapidiff.core.model.ChangedExamples;
+import org.openapitools.openapidiff.core.model.ChangedMediaType;
+import org.openapitools.openapidiff.core.model.DiffContext;
+import org.openapitools.openapidiff.core.model.deferred.DeferredBuilder;
+import org.openapitools.openapidiff.core.model.deferred.DeferredChanged;
+
+public class MediaTypeDiff {
+
+  private final OpenApiDiff openApiDiff;
+
+  public MediaTypeDiff(OpenApiDiff openApiDiff) {
+    this.openApiDiff = openApiDiff;
+  }
+
+  public DeferredChanged<ChangedMediaType> diff(
+      MediaType left, MediaType right, DiffContext context) {
+    DeferredBuilder<Changed> builder = new DeferredBuilder<>();
+
+    ChangedMediaType changedMediaType =
+        new ChangedMediaType(left.getSchema(), right.getSchema(), context)
+            .setExample(new ChangedExample(left.getExample(), right.getExample()))
+            .setExamples(new ChangedExamples(left.getExamples(), right.getExamples()));
+
+    builder
+        .with(
+            openApiDiff
+                .getSchemaDiff()
+                .diff(left.getSchema(), right.getSchema(), context.copyWithRequired(true)))
+        .ifPresent(changedMediaType::setSchema);
+
+    return builder.build().mapOptional(value -> isChanged(changedMediaType));
+  }
+}
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/OAuthFlowDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/OAuthFlowDiff.java
index 48e5e0447..8dd404f5b 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/compare/OAuthFlowDiff.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/OAuthFlowDiff.java
@@ -8,6 +8,7 @@
 import java.util.Objects;
 import java.util.Optional;
 import org.openapitools.openapidiff.core.model.ChangedOAuthFlow;
+import org.openapitools.openapidiff.core.model.DiffContext;
 
 public class OAuthFlowDiff {
   private final OpenApiDiff openApiDiff;
@@ -20,8 +21,8 @@ private static Map<String, Object> getExtensions(OAuthFlow oAuthFlow) {
     return ofNullable(oAuthFlow).map(OAuthFlow::getExtensions).orElse(null);
   }
 
-  public Optional<ChangedOAuthFlow> diff(OAuthFlow left, OAuthFlow right) {
-    ChangedOAuthFlow changedOAuthFlow = new ChangedOAuthFlow(left, right);
+  public Optional<ChangedOAuthFlow> diff(OAuthFlow left, OAuthFlow right, DiffContext context) {
+    ChangedOAuthFlow changedOAuthFlow = new ChangedOAuthFlow(left, right, context);
     if (left != null && right != null) {
       changedOAuthFlow
           .setAuthorizationUrl(
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/OAuthFlowsDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/OAuthFlowsDiff.java
index 98ceb509f..2b1136618 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/compare/OAuthFlowsDiff.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/OAuthFlowsDiff.java
@@ -7,6 +7,7 @@
 import java.util.Map;
 import java.util.Optional;
 import org.openapitools.openapidiff.core.model.ChangedOAuthFlows;
+import org.openapitools.openapidiff.core.model.DiffContext;
 
 public class OAuthFlowsDiff {
   private final OpenApiDiff openApiDiff;
@@ -19,24 +20,24 @@ private static Map<String, Object> getExtensions(OAuthFlows oAuthFlow) {
     return ofNullable(oAuthFlow).map(OAuthFlows::getExtensions).orElse(null);
   }
 
-  public Optional<ChangedOAuthFlows> diff(OAuthFlows left, OAuthFlows right) {
+  public Optional<ChangedOAuthFlows> diff(OAuthFlows left, OAuthFlows right, DiffContext context) {
     ChangedOAuthFlows changedOAuthFlows = new ChangedOAuthFlows(left, right);
     if (left != null && right != null) {
       openApiDiff
           .getOAuthFlowDiff()
-          .diff(left.getImplicit(), right.getImplicit())
+          .diff(left.getImplicit(), right.getImplicit(), context)
           .ifPresent(changedOAuthFlows::setImplicitOAuthFlow);
       openApiDiff
           .getOAuthFlowDiff()
-          .diff(left.getPassword(), right.getPassword())
+          .diff(left.getPassword(), right.getPassword(), context)
           .ifPresent(changedOAuthFlows::setPasswordOAuthFlow);
       openApiDiff
           .getOAuthFlowDiff()
-          .diff(left.getClientCredentials(), right.getClientCredentials())
+          .diff(left.getClientCredentials(), right.getClientCredentials(), context)
           .ifPresent(changedOAuthFlows::setClientCredentialOAuthFlow);
       openApiDiff
           .getOAuthFlowDiff()
-          .diff(left.getAuthorizationCode(), right.getAuthorizationCode())
+          .diff(left.getAuthorizationCode(), right.getAuthorizationCode(), context)
           .ifPresent(changedOAuthFlows::setAuthorizationCodeOAuthFlow);
     }
     openApiDiff
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/OpenApiDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/OpenApiDiff.java
index 1f0fe03bf..c1bb414d8 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/compare/OpenApiDiff.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/OpenApiDiff.java
@@ -24,6 +24,7 @@ public class OpenApiDiff {
   private PathDiff pathDiff;
   private SchemaDiff schemaDiff;
   private ContentDiff contentDiff;
+  private MediaTypeDiff mediaTypeDiff;
   private ParametersDiff parametersDiff;
   private ParameterDiff parameterDiff;
   private RequestBodyDiff requestBodyDiff;
@@ -41,6 +42,7 @@ public class OpenApiDiff {
   private MetadataDiff metadataDiff;
   private final OpenAPI oldSpecOpenApi;
   private final OpenAPI newSpecOpenApi;
+  private final OpenApiDiffOptions options;
   private List<Endpoint> newEndpoints;
   private List<Endpoint> missingEndpoints;
   private List<ChangedOperation> changedOperations;
@@ -50,18 +52,24 @@ public class OpenApiDiff {
   /*
    * @param oldSpecOpenApi
    * @param newSpecOpenApi
+   * @param diffOptions
    */
-  private OpenApiDiff(OpenAPI oldSpecOpenApi, OpenAPI newSpecOpenApi) {
+  private OpenApiDiff(OpenAPI oldSpecOpenApi, OpenAPI newSpecOpenApi, OpenApiDiffOptions options) {
     this.oldSpecOpenApi = oldSpecOpenApi;
     this.newSpecOpenApi = newSpecOpenApi;
+    this.options = options;
     if (null == oldSpecOpenApi || null == newSpecOpenApi) {
       throw new RuntimeException("one of the old or new object is null");
     }
+    if (null == options) {
+      throw new IllegalArgumentException("options parameter is null but is required");
+    }
     initializeFields();
   }
 
-  public static ChangedOpenApi compare(OpenAPI oldSpec, OpenAPI newSpec) {
-    return new OpenApiDiff(oldSpec, newSpec).compare();
+  public static ChangedOpenApi compare(
+      OpenAPI oldSpec, OpenAPI newSpec, OpenApiDiffOptions diffOptions) {
+    return new OpenApiDiff(oldSpec, newSpec, diffOptions).compare();
   }
 
   private void initializeFields() {
@@ -69,6 +77,7 @@ private void initializeFields() {
     this.pathDiff = new PathDiff(this);
     this.schemaDiff = new SchemaDiff(this);
     this.contentDiff = new ContentDiff(this);
+    this.mediaTypeDiff = new MediaTypeDiff(this);
     this.parametersDiff = new ParametersDiff(this);
     this.parameterDiff = new ParameterDiff(this);
     this.requestBodyDiff = new RequestBodyDiff(this);
@@ -87,6 +96,10 @@ private void initializeFields() {
     this.deferredSchemaCache = new DeferredSchemaCache(this);
   }
 
+  public OpenApiDiffOptions getOptions() {
+    return options;
+  }
+
   private ChangedOpenApi compare() {
     preProcess(oldSpecOpenApi);
     preProcess(newSpecOpenApi);
@@ -163,7 +176,7 @@ private void preProcess(OpenAPI openApi) {
   }
 
   private ChangedOpenApi getChangedOpenApi() {
-    return new ChangedOpenApi()
+    return new ChangedOpenApi(options)
         .setMissingEndpoints(missingEndpoints)
         .setNewEndpoints(newEndpoints)
         .setNewSpecOpenApi(newSpecOpenApi)
@@ -193,6 +206,10 @@ public ContentDiff getContentDiff() {
     return this.contentDiff;
   }
 
+  public MediaTypeDiff getMediaTypeDiff() {
+    return this.mediaTypeDiff;
+  }
+
   public ParametersDiff getParametersDiff() {
     return this.parametersDiff;
   }
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/OpenApiDiffOptions.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/OpenApiDiffOptions.java
new file mode 100644
index 000000000..23f4e1c37
--- /dev/null
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/OpenApiDiffOptions.java
@@ -0,0 +1,49 @@
+package org.openapitools.openapidiff.core.compare;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import org.apache.commons.configuration2.CompositeConfiguration;
+import org.apache.commons.configuration2.YAMLConfiguration;
+import org.apache.commons.configuration2.ex.ConfigurationException;
+
+public class OpenApiDiffOptions {
+  private final CompositeConfiguration config;
+
+  private OpenApiDiffOptions(CompositeConfiguration config) {
+    this.config = config;
+  }
+
+  public CompositeConfiguration getConfig() {
+    return config;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder {
+    private OpenApiDiffOptions built = new OpenApiDiffOptions(new CompositeConfiguration());
+
+    public Builder configYaml(File file) {
+      YAMLConfiguration yamlConfig = new YAMLConfiguration();
+      try {
+        yamlConfig.read(new FileReader(file));
+      } catch (ConfigurationException | FileNotFoundException e) {
+        throw new IllegalArgumentException("Problem loading config. file=" + file, e);
+      }
+      // Ideally immutable, but since it isn't, we just modify the config directly
+      built.getConfig().addConfigurationFirst(yamlConfig);
+      return this;
+    }
+
+    public Builder configProperty(String propKey, String propVal) {
+      built.getConfig().setProperty(propKey, propVal);
+      return this;
+    }
+
+    public OpenApiDiffOptions build() {
+      return built;
+    }
+  }
+}
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/OperationDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/OperationDiff.java
index 8d960ba31..b44093263 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/compare/OperationDiff.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/OperationDiff.java
@@ -57,8 +57,7 @@ public DeferredChanged<ChangedOperation> diff(
                 .diff(oldOperation.getOperationId(), newOperation.getOperationId(), context))
         .ifPresent(changedOperation::setOperationId);
     changedOperation.setDeprecated(
-        !Boolean.TRUE.equals(oldOperation.getDeprecated())
-            && Boolean.TRUE.equals(newOperation.getDeprecated()));
+        !Objects.equals(oldOperation.getDeprecated(), newOperation.getDeprecated()));
 
     if (oldOperation.getRequestBody() != null || newOperation.getRequestBody() != null) {
       builder
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/ParameterDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/ParameterDiff.java
index 6652b0bc4..3a8389d16 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/compare/ParameterDiff.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/ParameterDiff.java
@@ -4,8 +4,9 @@
 import io.swagger.v3.oas.models.parameters.Parameter;
 import java.util.HashSet;
 import java.util.Objects;
-import java.util.Optional;
 import org.openapitools.openapidiff.core.model.Changed;
+import org.openapitools.openapidiff.core.model.ChangedExample;
+import org.openapitools.openapidiff.core.model.ChangedExamples;
 import org.openapitools.openapidiff.core.model.ChangedParameter;
 import org.openapitools.openapidiff.core.model.DiffContext;
 import org.openapitools.openapidiff.core.model.deferred.DeferredBuilder;
@@ -49,14 +50,14 @@ protected DeferredChanged<ChangedParameter> computeDiff(
         new ChangedParameter(right.getName(), right.getIn(), context)
             .setOldParameter(left)
             .setNewParameter(right)
-            .setChangeRequired(getBooleanDiff(left.getRequired(), right.getRequired()))
-            .setDeprecated(
-                !Boolean.TRUE.equals(left.getDeprecated())
-                    && Boolean.TRUE.equals(right.getDeprecated()))
+            .setChangeRequired(!Objects.equals(left.getRequired(), right.getRequired()))
+            .setDeprecated(!Objects.equals(left.getDeprecated(), right.getDeprecated()))
             .setChangeAllowEmptyValue(
-                getBooleanDiff(left.getAllowEmptyValue(), right.getAllowEmptyValue()))
+                !Objects.equals(left.getAllowEmptyValue(), right.getAllowEmptyValue()))
             .setChangeStyle(!Objects.equals(left.getStyle(), right.getStyle()))
-            .setChangeExplode(getBooleanDiff(left.getExplode(), right.getExplode()));
+            .setChangeExplode(!Objects.equals(left.getExplode(), right.getExplode()))
+            .setExamples(new ChangedExamples(left.getExamples(), right.getExamples()))
+            .setExample(new ChangedExample(left.getExample(), right.getExample()));
     builder
         .with(
             openApiDiff
@@ -80,10 +81,4 @@ protected DeferredChanged<ChangedParameter> computeDiff(
         .ifPresent(changedParameter::setExtensions);
     return builder.buildIsChanged(changedParameter);
   }
-
-  private boolean getBooleanDiff(Boolean left, Boolean right) {
-    boolean leftRequired = Optional.ofNullable(left).orElse(Boolean.FALSE);
-    boolean rightRequired = Optional.ofNullable(right).orElse(Boolean.FALSE);
-    return leftRequired != rightRequired;
-  }
 }
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/ParametersDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/ParametersDiff.java
index 352be4bf1..6de3b4c28 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/compare/ParametersDiff.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/ParametersDiff.java
@@ -114,7 +114,9 @@ public boolean pathUnchangedParametersChanged(
       boolean samePathDifferentParameter = !newParameterRealized.equals(parameter);
       newParameterRealized.setName(
           newParameterName); // Important:: MUST Reset the name as this is not a copy
-      return samePathDifferentParameter;
+      if (samePathDifferentParameter) {
+        return true;
+      }
     }
     return false;
   }
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/PathsDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/PathsDiff.java
index cb969f4fa..8b4f459b8 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/compare/PathsDiff.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/PathsDiff.java
@@ -40,7 +40,7 @@ public DeferredChanged<ChangedPaths> diff(
       final Map<String, PathItem> left, final Map<String, PathItem> right) {
     DeferredBuilder<Changed> builder = new DeferredBuilder<>();
 
-    ChangedPaths changedPaths = new ChangedPaths(left, right);
+    ChangedPaths changedPaths = new ChangedPaths(left, right, openApiDiff.getOptions());
     changedPaths.getIncreased().putAll(right);
 
     left.keySet()
@@ -82,7 +82,7 @@ public DeferredChanged<ChangedPaths> diff(
                     params.put(oldParams.get(i), newParams.get(i));
                   }
                 }
-                DiffContext context = new DiffContext();
+                DiffContext context = new DiffContext(openApiDiff.getOptions());
                 context.setUrl(url);
                 context.setParameters(params);
                 context.setLeftAndRightUrls(url, rightUrl);
@@ -125,6 +125,8 @@ private static boolean methodsAndParametersIntersect(PathItem a, PathItem b) {
   }
 
   /**
+   * Checks if provided parameter pairs are equal by type and format
+   *
    * @param left parameters from the first compared method
    * @param right parameters from the second compared method
    * @return <code>true</code> in case each parameter pair is of the same type; <code>false</code>
@@ -134,9 +136,21 @@ private static boolean parametersIntersect(List<Parameter> left, List<Parameter>
     int parametersSize = left.size();
     long intersectedParameters =
         IntStream.range(0, left.size())
-            .filter(
-                i -> left.get(i).getSchema().getType().equals(right.get(i).getSchema().getType()))
+            .filter(i -> parametersTypeEquals(left.get(i), right.get(i)))
             .count();
     return parametersSize == intersectedParameters;
   }
+
+  /**
+   * Checks if provided parameter pair is equal by type and format
+   *
+   * @param left parameter from the first compared method
+   * @param right parameter from the second compared method
+   * @return <code>true</code> in case parameter pair is of the same type; <code>false</code>
+   *     otherwise
+   */
+  private static boolean parametersTypeEquals(Parameter left, Parameter right) {
+    return Objects.equals(left.getSchema().getType(), right.getSchema().getType())
+        && Objects.equals(left.getSchema().getFormat(), right.getSchema().getFormat());
+  }
 }
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/SchemaDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/SchemaDiff.java
index 1d1961bf7..295cd9c6c 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/compare/SchemaDiff.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/SchemaDiff.java
@@ -96,7 +96,7 @@ protected static Schema<?> resolveComposedSchema(
             updatedVisitedRefs.add(composed.get$ref());
             composed = refPointer.resolveRef(components, composed, composed.get$ref());
             composed = resolveComposedSchema(components, composed, updatedVisitedRefs);
-            schema = addSchema(schema, composed);
+            addSchema(schema, composed);
           }
         }
         composedSchema.setAllOf(null);
@@ -106,7 +106,7 @@ protected static Schema<?> resolveComposedSchema(
     return schema;
   }
 
-  protected static Schema<?> addSchema(Schema<?> schema, Schema<?> fromSchema) {
+  protected static <T, U> Schema<T> addSchema(Schema<T> schema, Schema<U> fromSchema) {
     if (fromSchema.getProperties() != null) {
       if (schema.getProperties() == null) {
         schema.setProperties(new LinkedHashMap<>());
@@ -206,6 +206,9 @@ protected static Schema<?> addSchema(Schema<?> schema, Schema<?> fromSchema) {
     if (fromSchema.getExample() != null) {
       schema.setExample(fromSchema.getExample());
     }
+    if (fromSchema.getExamples() != null) {
+      schema.setExamples((List<T>) fromSchema.getExamples());
+    }
     if (fromSchema.getExternalDocs() != null) {
       if (schema.getExternalDocs() == null) {
         schema.setExternalDocs(new ExternalDocumentation());
@@ -337,8 +340,8 @@ public DeferredChanged<ChangedSchema> computeDiffForReal(
     left = refPointer.resolveRef(this.leftComponents, left, getSchemaRef(left));
     right = refPointer.resolveRef(this.rightComponents, right, getSchemaRef(right));
 
-    left = resolveComposedSchema(leftComponents, left, new HashSet<>());
-    right = resolveComposedSchema(rightComponents, right, new HashSet<>());
+    left = resolveComposedSchema(leftComponents, left, refSet.getLeftKeys());
+    right = resolveComposedSchema(rightComponents, right, refSet.getRightKeys());
 
     // If type of schemas are different, just set old & new schema, set changedType to true in
     // SchemaDiffResult and
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementDiff.java
index 237e7815f..76b51a5d0 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementDiff.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementDiff.java
@@ -66,7 +66,7 @@ public DeferredChanged<ChangedSecurityRequirement> diff(
     DeferredBuilder<Changed> builder = new DeferredBuilder<>();
 
     ChangedSecurityRequirement changedSecurityRequirement =
-        new ChangedSecurityRequirement(left, right != null ? getCopy(right) : null);
+        new ChangedSecurityRequirement(left, right != null ? getCopy(right) : null, context);
 
     SecurityRequirement leftRequirement = left == null ? new SecurityRequirement() : left;
     SecurityRequirement rightRequirement = right == null ? new SecurityRequirement() : right;
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementsDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementsDiff.java
index 291dd5c65..324bf0017 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementsDiff.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/SecurityRequirementsDiff.java
@@ -88,7 +88,7 @@ protected DeferredChanged<ChangedSecurityRequirements> diff(
     right = right == null ? new ArrayList<>() : getCopy(right);
 
     ChangedSecurityRequirements changedSecurityRequirements =
-        new ChangedSecurityRequirements(left, right);
+        new ChangedSecurityRequirements(left, right, context);
 
     for (SecurityRequirement leftSecurity : left) {
       Optional<SecurityRequirement> rightSecOpt = contains(right, leftSecurity);
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/SecuritySchemeDiff.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/SecuritySchemeDiff.java
index a27edb374..f68d638d3 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/compare/SecuritySchemeDiff.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/SecuritySchemeDiff.java
@@ -51,8 +51,8 @@ public DeferredChanged<ChangedSecurityScheme> diff(
         changedSecuritySchemeOptional -> {
           ChangedSecurityScheme changedSecurityScheme =
               changedSecuritySchemeOptional.orElse(
-                  new ChangedSecurityScheme(leftSecurityScheme, rightSecurityScheme));
-          changedSecurityScheme = getCopyWithoutScopes(changedSecurityScheme);
+                  new ChangedSecurityScheme(leftSecurityScheme, rightSecurityScheme, context));
+          changedSecurityScheme = getCopyWithoutScopes(changedSecurityScheme, context);
 
           if (changedSecurityScheme != null
               && leftSecurityScheme.getType() == SecurityScheme.Type.OAUTH2) {
@@ -71,7 +71,7 @@ protected DeferredChanged<ChangedSecurityScheme> computeDiff(
       SecurityScheme rightSecurityScheme,
       DiffContext context) {
     ChangedSecurityScheme changedSecurityScheme =
-        new ChangedSecurityScheme(leftSecurityScheme, rightSecurityScheme);
+        new ChangedSecurityScheme(leftSecurityScheme, rightSecurityScheme, context);
 
     openApiDiff
         .getMetadataDiff()
@@ -87,7 +87,7 @@ protected DeferredChanged<ChangedSecurityScheme> computeDiff(
       case OAUTH2:
         openApiDiff
             .getOAuthFlowsDiff()
-            .diff(leftSecurityScheme.getFlows(), rightSecurityScheme.getFlows())
+            .diff(leftSecurityScheme.getFlows(), rightSecurityScheme.getFlows(), context)
             .ifPresent(changedSecurityScheme::setOAuthFlows);
         break;
 
@@ -114,9 +114,10 @@ protected DeferredChanged<ChangedSecurityScheme> computeDiff(
     return new RealizedChanged<>(changedSecurityScheme);
   }
 
-  private ChangedSecurityScheme getCopyWithoutScopes(ChangedSecurityScheme original) {
+  private ChangedSecurityScheme getCopyWithoutScopes(
+      ChangedSecurityScheme original, DiffContext context) {
     return new ChangedSecurityScheme(
-            original.getOldSecurityScheme(), original.getNewSecurityScheme())
+            original.getOldSecurityScheme(), original.getNewSecurityScheme(), context)
         .setChangedType(original.isChangedType())
         .setChangedIn(original.isChangedIn())
         .setChangedScheme(original.isChangedScheme())
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/ComposedSchemaDiffResult.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/ComposedSchemaDiffResult.java
index e76aa0155..2f86318eb 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/ComposedSchemaDiffResult.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/ComposedSchemaDiffResult.java
@@ -12,13 +12,13 @@
 import org.apache.commons.collections4.CollectionUtils;
 import org.openapitools.openapidiff.core.compare.MapKeyDiff;
 import org.openapitools.openapidiff.core.compare.OpenApiDiff;
-import org.openapitools.openapidiff.core.model.ChangedOneOfSchema;
 import org.openapitools.openapidiff.core.model.ChangedSchema;
 import org.openapitools.openapidiff.core.model.DiffContext;
 import org.openapitools.openapidiff.core.model.deferred.DeferredBuilder;
 import org.openapitools.openapidiff.core.model.deferred.DeferredChanged;
 import org.openapitools.openapidiff.core.model.deferred.RealizedChanged;
 import org.openapitools.openapidiff.core.model.deferred.RecursiveSchemaSet;
+import org.openapitools.openapidiff.core.model.schema.ChangedOneOfSchema;
 import org.openapitools.openapidiff.core.utils.RefPointer;
 import org.openapitools.openapidiff.core.utils.RefType;
 
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/SchemaDiffResult.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/SchemaDiffResult.java
index 6886f8c54..dd3c8ab32 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/SchemaDiffResult.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/SchemaDiffResult.java
@@ -11,12 +11,20 @@
 import org.openapitools.openapidiff.core.compare.OpenApiDiff;
 import org.openapitools.openapidiff.core.model.Change;
 import org.openapitools.openapidiff.core.model.Changed;
+import org.openapitools.openapidiff.core.model.ChangedExample;
+import org.openapitools.openapidiff.core.model.ChangedExamples;
 import org.openapitools.openapidiff.core.model.ChangedSchema;
 import org.openapitools.openapidiff.core.model.DiffContext;
 import org.openapitools.openapidiff.core.model.deferred.DeferredBuilder;
 import org.openapitools.openapidiff.core.model.deferred.DeferredChanged;
 import org.openapitools.openapidiff.core.model.deferred.RecursiveSchemaSet;
 import org.openapitools.openapidiff.core.model.schema.*;
+import org.openapitools.openapidiff.core.model.schema.ChangedMaxItems;
+import org.openapitools.openapidiff.core.model.schema.ChangedMinItems;
+import org.openapitools.openapidiff.core.model.schema.ChangedPattern;
+import org.openapitools.openapidiff.core.model.schema.ChangedReadOnly;
+import org.openapitools.openapidiff.core.model.schema.ChangedRequired;
+import org.openapitools.openapidiff.core.model.schema.ChangedUniqueItems;
 
 public class SchemaDiffResult {
   protected ChangedSchema changedSchema;
@@ -48,9 +56,7 @@ public <V extends Schema<X>, X> DeferredChanged<ChangedSchema> diff(
         .setContext(context)
         .setOldSchema(left)
         .setNewSchema(right)
-        .setChangeDeprecated(
-            !Boolean.TRUE.equals(left.getDeprecated())
-                && Boolean.TRUE.equals(right.getDeprecated()))
+        .setChangeDeprecated(!Objects.equals(left.getDeprecated(), right.getDeprecated()))
         .setChangeTitle(!Objects.equals(left.getTitle(), right.getTitle()))
         .setRequired(
             ListDiff.diff(new ChangedRequired(left.getRequired(), right.getRequired(), context)))
@@ -70,7 +76,19 @@ public <V extends Schema<X>, X> DeferredChanged<ChangedSchema> diff(
                 right.getExclusiveMinimum(),
                 left.getExclusiveMaximum(),
                 right.getExclusiveMaximum(),
-                context));
+                context))
+        .setMultipleOf(new ChangedMultipleOf(left.getMultipleOf(), right.getMultipleOf()))
+        .setNullable(new ChangedNullable(left.getNullable(), right.getNullable()))
+        .setPattern(new ChangedPattern(left.getPattern(), right.getPattern(), context))
+        .setUniqueItems(new ChangedUniqueItems(left.getUniqueItems(), right.getUniqueItems()))
+        .setExamples(new ChangedExamples(left.getExamples(), right.getExamples()))
+        .setExample(new ChangedExample(left.getExample(), right.getExample()))
+        .setMaxItems(new ChangedMaxItems(left.getMaxItems(), right.getMaxItems(), context))
+        .setMinItems(new ChangedMinItems(left.getMinItems(), right.getMinItems(), context))
+        .setMaxProperties(
+            new ChangedMaxProperties(left.getMaxProperties(), right.getMaxProperties(), context))
+        .setMinProperties(
+            new ChangedMinProperties(left.getMinProperties(), right.getMinProperties(), context));
     builder
         .with(
             openApiDiff
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/BackwardIncompatibleProp.java b/core/src/main/java/org/openapitools/openapidiff/core/model/BackwardIncompatibleProp.java
new file mode 100644
index 000000000..f05a72f75
--- /dev/null
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/BackwardIncompatibleProp.java
@@ -0,0 +1,82 @@
+package org.openapitools.openapidiff.core.model;
+
+import static org.apache.commons.lang3.ArrayUtils.isEmpty;
+
+import org.apache.commons.configuration2.Configuration;
+
+// Properties to enable/disable backward incompatibility checks
+// Note: order is not programmatically significant but keep alphabetical for maintainability
+public enum BackwardIncompatibleProp {
+  EXTENSION_CONTENT_TYPES_DECREASED("incompatible.extension.content.types.decreased", false),
+  EXTENSION_CONTENT_TYPE_DELETED("incompatible.extension.content.type.%s.deleted", false),
+  OPENAPI_ENDPOINTS_DECREASED("incompatible.openapi.endpoints.decreased", true),
+  REQUEST_BODY_REQUIRED_INCREASED("incompatible.request.body.increased", true),
+  REQUEST_CONTENT_DECREASED("incompatible.request.content.decreased", true),
+  REQUEST_ENUM_DECREASED("incompatible.request.enum.decreased", true),
+  REQUEST_MAX_LENGTH_DECREASED("incompatible.request.max.length.decreased", true),
+  REQUEST_NUMERIC_RANGE_DECREASED("incompatible.request.numeric.range.decreased", true),
+  REQUEST_ONEOF_DECREASED("incompatible.request.oneof.decreased", true),
+  REQUEST_PARAM_ALLOWEMPTY_DECREASED("incompatible.request.param.allowempty.decreased", true),
+  REQUEST_PARAM_EXPLODE_CHANGED("incompatible.request.param.explode.changed", true),
+  REQUEST_PARAM_STYLE_CHANGED("incompatible.request.param.style.changed", true),
+  REQUEST_PARAMS_DECREASED("incompatible.request.params.decreased", true),
+  REQUEST_PARAMS_REQUIRED_INCREASED("incompatible.request.params.required.increased", true),
+  REQUEST_READONLY_INCREASED("incompatible.request.readonly.increased", true),
+  REQUEST_READONLY_REQUIRED_DECREASED("incompatible.request.readonly.required.decreased", true),
+  REQUEST_REQUIRED_INCREASED("incompatible.request.required.increased", true),
+  RESPONSE_CONTENT_DECREASED("incompatible.response.content.decreased", true),
+  RESPONSE_ENUM_INCREASED("incompatible.response.enum.increased", true),
+  RESPONSE_HEADER_EXPLODE_CHANGED("incompatible.response.header.explode.changed", true),
+  RESPONSE_HEADER_REQUIRED_DECREASED("incompatible.response.header.required.decreased", true),
+  RESPONSE_HEADER_REQUIRED_INCREASED("incompatible.response.header.required.increased", true),
+  RESPONSE_HEADERS_DECREASED("incompatible.response.headers.decreased", true),
+  RESPONSE_MAX_LENGTH_INCREASED("incompatible.response.max.length.increased", true),
+  RESPONSE_NUMERIC_RANGE_INCREASED("incompatible.response.numeric.range.increased", false),
+  RESPONSE_ONEOF_INCREASED("incompatible.response.oneof.increased", true),
+  RESPONSE_REQUIRED_DECREASED("incompatible.response.required.decreased", true),
+  RESPONSE_RESPONSES_DECREASED("incompatible.response.responses.decreased", true),
+  RESPONSE_WRITEONLY_INCREASED("incompatible.response.writeonly.increased", true),
+  RESPONSE_WRITEONLY_REQUIRED_DECREASED("incompatible.response.writeonly.required.decreased", true),
+  SECURITY_REQUIREMENT_SCHEMES_INCREASED(
+      "incompatible.security.requirement.schemes.increased", true),
+  SECURITY_REQUIREMENTS_DECREASED("incompatible.security.requirements.decreased", true),
+  SECURITY_SCHEME_BEARER_FORMAT_CHANGED("incompatible.security.scheme.bearer.format.changed", true),
+  SECURITY_SCHEME_OAUTH2_AUTH_URL_CHANGED(
+      "incompatible.security.scheme.oauth2.auth.url.changed", true),
+  SECURITY_SCHEME_OAUTH2_REFRESH_URL_CHANGED(
+      "incompatible.security.scheme.oauth2.refresh.url.changed", true),
+  SECURITY_SCHEME_OAUTH2_TOKEN_URL_CHANGED(
+      "incompatible.security.scheme.oauth2.token.url.changed", true),
+  SECURITY_SCHEME_OPENIDCONNECT_URL_CHANGED(
+      "incompatible.security.scheme.openidconnect.url.changed", true),
+  SECURITY_SCHEME_SCHEME_CHANGED("incompatible.security.scheme.scheme.changed", true),
+  SECURITY_SCHEME_SCOPES_INCREASED("incompatible.security.scheme.scopes.increased", true),
+  SCHEMA_DISCRIMINATOR_CHANGED("incompatible.schema.discriminator.changed", true),
+  SCHEMA_TYPE_CHANGED("incompatible.schema.type.changed", true),
+  ;
+
+  private final String propertyName;
+  private final boolean enabledByDefault;
+
+  BackwardIncompatibleProp(String propertyName, boolean enabledByDefault) {
+    this.propertyName = propertyName;
+    this.enabledByDefault = enabledByDefault;
+  }
+
+  public String getPropertyName() {
+    return propertyName;
+  }
+
+  public boolean isEnabledByDefault() {
+    return enabledByDefault;
+  }
+
+  public boolean enabled(DiffContext context, Object... formatArgs) {
+    return enabled(context.getConfig(), formatArgs);
+  }
+
+  public boolean enabled(Configuration cfg, Object... formatArgs) {
+    String propName = isEmpty(formatArgs) ? propertyName : String.format(propertyName, formatArgs);
+    return cfg.getBoolean(propName, enabledByDefault);
+  }
+}
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedApiResponse.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedApiResponse.java
index e496f7a71..0b12a0ead 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedApiResponse.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedApiResponse.java
@@ -1,5 +1,7 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_RESPONSES_DECREASED;
+
 import io.swagger.v3.oas.models.responses.ApiResponse;
 import io.swagger.v3.oas.models.responses.ApiResponses;
 import java.util.LinkedHashMap;
@@ -39,10 +41,12 @@ public DiffResult isCoreChanged() {
     if (increased.isEmpty() && missing.isEmpty()) {
       return DiffResult.NO_CHANGES;
     }
-    if (!increased.isEmpty() && missing.isEmpty()) {
-      return DiffResult.COMPATIBLE;
+    if (!missing.isEmpty()) {
+      if (RESPONSE_RESPONSES_DECREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
     }
-    return DiffResult.INCOMPATIBLE;
+    return DiffResult.COMPATIBLE;
   }
 
   public ApiResponses getOldApiResponses() {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedContent.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedContent.java
index 192b49e66..472803ffd 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedContent.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedContent.java
@@ -1,5 +1,8 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_CONTENT_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_CONTENT_DECREASED;
+
 import io.swagger.v3.oas.models.media.Content;
 import io.swagger.v3.oas.models.media.MediaType;
 import java.util.*;
@@ -31,10 +34,15 @@ public DiffResult isCoreChanged() {
     if (increased.isEmpty() && missing.isEmpty()) {
       return DiffResult.NO_CHANGES;
     }
-    if (context.isRequest() && missing.isEmpty() || context.isResponse() && missing.isEmpty()) {
-      return DiffResult.COMPATIBLE;
+    if (!missing.isEmpty()) {
+      if (context.isRequest() && REQUEST_CONTENT_DECREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+      if (context.isResponse() && RESPONSE_CONTENT_DECREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
     }
-    return DiffResult.INCOMPATIBLE;
+    return DiffResult.COMPATIBLE;
   }
 
   public Content getOldContent() {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedExample.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedExample.java
new file mode 100644
index 000000000..4e540eca3
--- /dev/null
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedExample.java
@@ -0,0 +1,66 @@
+package org.openapitools.openapidiff.core.model;
+
+import java.util.Objects;
+
+public class ChangedExample implements Changed {
+
+  private Object leftExample;
+  private Object rightExample;
+
+  public ChangedExample(Object leftExample, Object rightExample) {
+    this.leftExample = leftExample;
+    this.rightExample = rightExample;
+  }
+
+  public Object getLeftExample() {
+    return leftExample;
+  }
+
+  public void setLeftExample(Object leftExample) {
+    this.leftExample = leftExample;
+  }
+
+  public Object getRightExample() {
+    return rightExample;
+  }
+
+  public void setRightExample(Object rightExample) {
+    this.rightExample = rightExample;
+  }
+
+  @Override
+  public DiffResult isChanged() {
+    if (!Objects.equals(leftExample, rightExample)) {
+      return DiffResult.METADATA;
+    }
+    return DiffResult.NO_CHANGES;
+  }
+
+  @Override
+  public boolean equals(Object object) {
+    if (this == object) {
+      return true;
+    }
+    if (object == null || getClass() != object.getClass()) {
+      return false;
+    }
+    ChangedExample that = (ChangedExample) object;
+    return Objects.equals(leftExample, that.leftExample)
+        && Objects.equals(rightExample, that.rightExample);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(leftExample, rightExample);
+  }
+
+  @Override
+  public String toString() {
+    return "ChangedExample{"
+        + "leftExample="
+        + leftExample
+        + ", rightExample="
+        + rightExample
+        + '}';
+  }
+}
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedExamples.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedExamples.java
new file mode 100644
index 000000000..c1a00bbbc
--- /dev/null
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedExamples.java
@@ -0,0 +1,66 @@
+package org.openapitools.openapidiff.core.model;
+
+import java.util.Objects;
+
+public class ChangedExamples implements Changed {
+
+  private Object leftExamples;
+  private Object rightExamples;
+
+  public ChangedExamples(Object leftExamples, Object rightExamples) {
+    this.leftExamples = leftExamples;
+    this.rightExamples = rightExamples;
+  }
+
+  public Object getLeftExamples() {
+    return leftExamples;
+  }
+
+  public void setLeftExamples(Object leftExamples) {
+    this.leftExamples = leftExamples;
+  }
+
+  public Object getRightExamples() {
+    return rightExamples;
+  }
+
+  public void setRightExamples(Object rightExamples) {
+    this.rightExamples = rightExamples;
+  }
+
+  @Override
+  public DiffResult isChanged() {
+    if (!Objects.equals(leftExamples, rightExamples)) {
+      return DiffResult.METADATA;
+    }
+    return DiffResult.NO_CHANGES;
+  }
+
+  @Override
+  public boolean equals(Object object) {
+    if (this == object) {
+      return true;
+    }
+    if (object == null || getClass() != object.getClass()) {
+      return false;
+    }
+    ChangedExamples that = (ChangedExamples) object;
+    return Objects.equals(leftExamples, that.leftExamples)
+        && Objects.equals(rightExamples, that.rightExamples);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(leftExamples, rightExamples);
+  }
+
+  @Override
+  public String toString() {
+    return "ChangedExamples{"
+        + ", leftExamples="
+        + leftExamples
+        + ", rightExamples="
+        + rightExamples
+        + '}';
+  }
+}
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedExtensions.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedExtensions.java
index cde3b1511..f189b3e8c 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedExtensions.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedExtensions.java
@@ -1,5 +1,8 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.EXTENSION_CONTENT_TYPES_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.EXTENSION_CONTENT_TYPE_DELETED;
+
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -32,7 +35,20 @@ public List<Changed> getChangedElements() {
 
   @Override
   public DiffResult isCoreChanged() {
-    return DiffResult.NO_CHANGES;
+    if (increased.isEmpty() && missing.isEmpty()) {
+      return DiffResult.NO_CHANGES;
+    }
+    if (!missing.isEmpty()) {
+      if (EXTENSION_CONTENT_TYPES_DECREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+      for (String key : missing.keySet()) {
+        if (EXTENSION_CONTENT_TYPE_DELETED.enabled(context, key)) {
+          return DiffResult.INCOMPATIBLE;
+        }
+      }
+    }
+    return DiffResult.COMPATIBLE;
   }
 
   public Map<String, Object> getOldExtensions() {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedHeader.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedHeader.java
index 8ec56568f..0c9e3384f 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedHeader.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedHeader.java
@@ -1,5 +1,9 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_HEADER_EXPLODE_CHANGED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_HEADER_REQUIRED_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_HEADER_REQUIRED_INCREASED;
+
 import io.swagger.v3.oas.models.headers.Header;
 import java.util.Arrays;
 import java.util.List;
@@ -14,6 +18,8 @@ public class ChangedHeader implements ComposedChanged {
   private boolean style;
   private boolean explode;
   private ChangedMetadata description;
+  private ChangedExamples examples;
+  private ChangedExample example;
   private ChangedSchema schema;
   private ChangedContent content;
   private ChangedExtensions extensions;
@@ -26,7 +32,7 @@ public ChangedHeader(Header oldHeader, Header newHeader, DiffContext context) {
 
   @Override
   public List<Changed> getChangedElements() {
-    return Arrays.asList(description, schema, content, extensions);
+    return Arrays.asList(description, example, examples, schema, content, extensions);
   }
 
   @Override
@@ -34,10 +40,30 @@ public DiffResult isCoreChanged() {
     if (!required && !deprecated && !style && !explode) {
       return DiffResult.NO_CHANGES;
     }
-    if (!required && !style && !explode) {
-      return DiffResult.COMPATIBLE;
+    if (explode) {
+      if (RESPONSE_HEADER_EXPLODE_CHANGED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    if (required) {
+      boolean requiredOld = oldHeader.getRequired() != null ? oldHeader.getRequired() : false;
+      boolean requiredNew = newHeader.getRequired() != null ? newHeader.getRequired() : false;
+      if (requiredOld && !requiredNew) {
+        if (RESPONSE_HEADER_REQUIRED_DECREASED.enabled(context)) {
+          return DiffResult.INCOMPATIBLE;
+        }
+      }
+      if (!requiredOld && requiredNew) {
+        // TODO: Document why desired or remove support. Client will just ignore new header?
+        if (RESPONSE_HEADER_REQUIRED_INCREASED.enabled(context)) {
+          return DiffResult.INCOMPATIBLE;
+        }
+      }
     }
-    return DiffResult.INCOMPATIBLE;
+    if (style) {
+      return DiffResult.INCOMPATIBLE;
+    }
+    return DiffResult.COMPATIBLE;
   }
 
   public Header getOldHeader() {
@@ -72,6 +98,14 @@ public ChangedMetadata getDescription() {
     return this.description;
   }
 
+  public ChangedExamples getExamples() {
+    return this.examples;
+  }
+
+  public ChangedExample getExample() {
+    return this.example;
+  }
+
   public ChangedSchema getSchema() {
     return this.schema;
   }
@@ -109,6 +143,16 @@ public ChangedHeader setDescription(final ChangedMetadata description) {
     return this;
   }
 
+  public ChangedHeader setExamples(ChangedExamples examples) {
+    this.examples = examples;
+    return this;
+  }
+
+  public ChangedHeader setExample(ChangedExample example) {
+    this.example = example;
+    return this;
+  }
+
   public ChangedHeader setSchema(final ChangedSchema schema) {
     this.schema = schema;
     return this;
@@ -137,6 +181,8 @@ public boolean equals(Object o) {
         && Objects.equals(newHeader, that.newHeader)
         && Objects.equals(context, that.context)
         && Objects.equals(description, that.description)
+        && Objects.equals(examples, that.examples)
+        && Objects.equals(example, that.example)
         && Objects.equals(schema, that.schema)
         && Objects.equals(content, that.content)
         && Objects.equals(extensions, that.extensions);
@@ -153,6 +199,8 @@ public int hashCode() {
         style,
         explode,
         description,
+        examples,
+        example,
         schema,
         content,
         extensions);
@@ -176,6 +224,10 @@ public java.lang.String toString() {
         + this.isExplode()
         + ", description="
         + this.getDescription()
+        + ", examples="
+        + this.getExamples()
+        + ", example="
+        + this.getExample()
         + ", schema="
         + this.getSchema()
         + ", content="
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedHeaders.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedHeaders.java
index 451e94f1e..dd228da0f 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedHeaders.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedHeaders.java
@@ -1,5 +1,7 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_HEADERS_DECREASED;
+
 import io.swagger.v3.oas.models.headers.Header;
 import java.util.ArrayList;
 import java.util.List;
@@ -31,10 +33,12 @@ public DiffResult isCoreChanged() {
     if (increased.isEmpty() && missing.isEmpty()) {
       return DiffResult.NO_CHANGES;
     }
-    if (missing.isEmpty()) {
-      return DiffResult.COMPATIBLE;
+    if (!missing.isEmpty()) {
+      if (RESPONSE_HEADERS_DECREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
     }
-    return DiffResult.INCOMPATIBLE;
+    return DiffResult.COMPATIBLE;
   }
 
   public Map<String, Header> getOldHeaders() {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedMediaType.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedMediaType.java
index 7136dea04..43f9a443d 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedMediaType.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedMediaType.java
@@ -1,7 +1,7 @@
 package org.openapitools.openapidiff.core.model;
 
 import io.swagger.v3.oas.models.media.Schema;
-import java.util.Collections;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
@@ -10,6 +10,8 @@ public class ChangedMediaType implements ComposedChanged {
   private final Schema newSchema;
   private final DiffContext context;
   private ChangedSchema schema;
+  private ChangedExamples examples;
+  private ChangedExample example;
 
   public ChangedMediaType(Schema oldSchema, Schema newSchema, DiffContext context) {
     this.oldSchema = oldSchema;
@@ -19,7 +21,7 @@ public ChangedMediaType(Schema oldSchema, Schema newSchema, DiffContext context)
 
   @Override
   public List<Changed> getChangedElements() {
-    return Collections.singletonList(schema);
+    return Arrays.asList(schema, examples, example);
   }
 
   @Override
@@ -43,11 +45,29 @@ public ChangedSchema getSchema() {
     return this.schema;
   }
 
+  public ChangedExamples getExamples() {
+    return this.examples;
+  }
+
+  public ChangedExample getExample() {
+    return this.example;
+  }
+
   public ChangedMediaType setSchema(final ChangedSchema schema) {
     this.schema = schema;
     return this;
   }
 
+  public ChangedMediaType setExamples(final ChangedExamples examples) {
+    this.examples = examples;
+    return this;
+  }
+
+  public ChangedMediaType setExample(final ChangedExample example) {
+    this.example = example;
+    return this;
+  }
+
   @Override
   public boolean equals(Object o) {
     if (this == o) return true;
@@ -56,12 +76,14 @@ public boolean equals(Object o) {
     return Objects.equals(oldSchema, that.oldSchema)
         && Objects.equals(newSchema, that.newSchema)
         && Objects.equals(context, that.context)
-        && Objects.equals(schema, that.schema);
+        && Objects.equals(schema, that.schema)
+        && Objects.equals(examples, that.examples)
+        && Objects.equals(example, that.example);
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(oldSchema, newSchema, context, schema);
+    return Objects.hash(oldSchema, newSchema, context, schema, examples, example);
   }
 
   @java.lang.Override
@@ -74,6 +96,10 @@ public java.lang.String toString() {
         + this.getContext()
         + ", schema="
         + this.getSchema()
+        + ", examples="
+        + this.getExamples()
+        + ", example="
+        + this.getExample()
         + ")";
   }
 }
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedOAuthFlow.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedOAuthFlow.java
index 5409d1d99..b6179e9be 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedOAuthFlow.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedOAuthFlow.java
@@ -1,5 +1,9 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_SCHEME_OAUTH2_AUTH_URL_CHANGED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_SCHEME_OAUTH2_REFRESH_URL_CHANGED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_SCHEME_OAUTH2_TOKEN_URL_CHANGED;
+
 import io.swagger.v3.oas.models.security.OAuthFlow;
 import java.util.Collections;
 import java.util.List;
@@ -8,14 +12,16 @@
 public class ChangedOAuthFlow implements ComposedChanged {
   private OAuthFlow oldOAuthFlow;
   private OAuthFlow newOAuthFlow;
+  private final DiffContext context;
   private boolean authorizationUrl;
   private boolean tokenUrl;
   private boolean refreshUrl;
   private ChangedExtensions extensions;
 
-  public ChangedOAuthFlow(OAuthFlow oldOAuthFlow, OAuthFlow newOAuthFlow) {
+  public ChangedOAuthFlow(OAuthFlow oldOAuthFlow, OAuthFlow newOAuthFlow, DiffContext context) {
     this.oldOAuthFlow = oldOAuthFlow;
     this.newOAuthFlow = newOAuthFlow;
+    this.context = context;
   }
 
   @Override
@@ -25,10 +31,25 @@ public List<Changed> getChangedElements() {
 
   @Override
   public DiffResult isCoreChanged() {
-    if (authorizationUrl || tokenUrl || refreshUrl) {
-      return DiffResult.INCOMPATIBLE;
+    if (!authorizationUrl && !tokenUrl && !refreshUrl) {
+      return DiffResult.NO_CHANGES;
+    }
+    if (authorizationUrl) {
+      if (SECURITY_SCHEME_OAUTH2_AUTH_URL_CHANGED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    if (refreshUrl) {
+      if (SECURITY_SCHEME_OAUTH2_REFRESH_URL_CHANGED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    if (tokenUrl) {
+      if (SECURITY_SCHEME_OAUTH2_TOKEN_URL_CHANGED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
     }
-    return DiffResult.NO_CHANGES;
+    return DiffResult.COMPATIBLE;
   }
 
   public OAuthFlow getOldOAuthFlow() {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedOpenApi.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedOpenApi.java
index e1bdd20bd..d0f23ca16 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedOpenApi.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedOpenApi.java
@@ -1,14 +1,18 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.OPENAPI_ENDPOINTS_DECREASED;
+
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import io.swagger.v3.oas.models.OpenAPI;
 import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
+import org.openapitools.openapidiff.core.compare.OpenApiDiffOptions;
 import org.openapitools.openapidiff.core.utils.EndpointUtils;
 
 public class ChangedOpenApi implements ComposedChanged {
+  private final OpenApiDiffOptions options;
   @JsonIgnore private OpenAPI oldSpecOpenApi;
   @JsonIgnore private OpenAPI newSpecOpenApi;
   private List<Endpoint> newEndpoints;
@@ -17,6 +21,10 @@ public class ChangedOpenApi implements ComposedChanged {
   private List<ChangedSchema> changedSchemas;
   private ChangedExtensions changedExtensions;
 
+  public ChangedOpenApi(OpenApiDiffOptions options) {
+    this.options = options;
+  }
+
   public List<Endpoint> getDeprecatedEndpoints() {
     return changedOperations.stream()
         .filter(ChangedOperation::isDeprecated)
@@ -40,10 +48,12 @@ public DiffResult isCoreChanged() {
     if (newEndpoints.isEmpty() && missingEndpoints.isEmpty()) {
       return DiffResult.NO_CHANGES;
     }
-    if (missingEndpoints.isEmpty()) {
-      return DiffResult.COMPATIBLE;
+    if (!missingEndpoints.isEmpty()) {
+      if (OPENAPI_ENDPOINTS_DECREASED.enabled(options.getConfig())) {
+        return DiffResult.INCOMPATIBLE;
+      }
     }
-    return DiffResult.INCOMPATIBLE;
+    return DiffResult.COMPATIBLE;
   }
 
   public OpenAPI getOldSpecOpenApi() {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedOperation.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedOperation.java
index 0da0516fc..2a6cc773a 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedOperation.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedOperation.java
@@ -64,6 +64,10 @@ public DiffResult resultRequestBody() {
     return requestBody == null ? DiffResult.NO_CHANGES : requestBody.isChanged();
   }
 
+  public DiffResult resultSecurityRequirements() {
+    return securityRequirements == null ? DiffResult.NO_CHANGES : securityRequirements.isChanged();
+  }
+
   public Operation getOldOperation() {
     return this.oldOperation;
   }
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedParameter.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedParameter.java
index 998570186..4b8208e24 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedParameter.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedParameter.java
@@ -1,5 +1,7 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.*;
+
 import io.swagger.v3.oas.models.parameters.Parameter;
 import java.util.Arrays;
 import java.util.List;
@@ -17,6 +19,8 @@ public class ChangedParameter implements ComposedChanged {
   private boolean changeExplode;
   private boolean changeAllowEmptyValue;
   private ChangedMetadata description;
+  private ChangedExamples examples;
+  private ChangedExample example;
   private ChangedSchema schema;
   private ChangedContent content;
   private ChangedExtensions extensions;
@@ -29,7 +33,7 @@ public ChangedParameter(String name, String in, DiffContext context) {
 
   @Override
   public List<Changed> getChangedElements() {
-    return Arrays.asList(description, schema, content, extensions);
+    return Arrays.asList(description, examples, example, schema, content, extensions);
   }
 
   @Override
@@ -41,13 +45,27 @@ public DiffResult isCoreChanged() {
         && !changeExplode) {
       return DiffResult.NO_CHANGES;
     }
-    if ((!changeRequired || Boolean.TRUE.equals(oldParameter.getRequired()))
-        && (!changeAllowEmptyValue || Boolean.TRUE.equals(newParameter.getAllowEmptyValue()))
-        && !changeStyle
-        && !changeExplode) {
-      return DiffResult.COMPATIBLE;
+    if (changeAllowEmptyValue && !Boolean.TRUE.equals(newParameter.getAllowEmptyValue())) {
+      if (REQUEST_PARAM_ALLOWEMPTY_DECREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    if (changeExplode) {
+      if (REQUEST_PARAM_EXPLODE_CHANGED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
     }
-    return DiffResult.INCOMPATIBLE;
+    if (changeRequired && !Boolean.TRUE.equals(oldParameter.getRequired())) {
+      if (REQUEST_PARAMS_REQUIRED_INCREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    if (changeStyle) {
+      if (REQUEST_PARAM_STYLE_CHANGED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    return DiffResult.COMPATIBLE;
   }
 
   public DiffContext getContext() {
@@ -94,6 +112,14 @@ public ChangedMetadata getDescription() {
     return this.description;
   }
 
+  public ChangedExamples getExamples() {
+    return this.examples;
+  }
+
+  public ChangedExample getExample() {
+    return this.example;
+  }
+
   public ChangedSchema getSchema() {
     return this.schema;
   }
@@ -156,6 +182,16 @@ public ChangedParameter setDescription(final ChangedMetadata description) {
     return this;
   }
 
+  public ChangedParameter setExamples(final ChangedExamples examples) {
+    this.examples = examples;
+    return this;
+  }
+
+  public ChangedParameter setExample(final ChangedExample example) {
+    this.example = example;
+    return this;
+  }
+
   public ChangedParameter setSchema(final ChangedSchema schema) {
     this.schema = schema;
     return this;
@@ -187,6 +223,8 @@ public boolean equals(Object o) {
         && Objects.equals(name, that.name)
         && Objects.equals(in, that.in)
         && Objects.equals(description, that.description)
+        && Objects.equals(examples, that.examples)
+        && Objects.equals(example, that.example)
         && Objects.equals(schema, that.schema)
         && Objects.equals(content, that.content)
         && Objects.equals(extensions, that.extensions);
@@ -206,6 +244,8 @@ public int hashCode() {
         changeExplode,
         changeAllowEmptyValue,
         description,
+        examples,
+        example,
         schema,
         content,
         extensions);
@@ -235,6 +275,10 @@ public java.lang.String toString() {
         + this.isChangeAllowEmptyValue()
         + ", description="
         + this.getDescription()
+        + ", examples="
+        + this.getExamples()
+        + ", example="
+        + this.getExample()
         + ", schema="
         + this.getSchema()
         + ", content="
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedParameters.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedParameters.java
index 2b119bf80..86dc145fd 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedParameters.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedParameters.java
@@ -1,5 +1,8 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_PARAMS_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_PARAMS_REQUIRED_INCREASED;
+
 import io.swagger.v3.oas.models.parameters.Parameter;
 import java.util.ArrayList;
 import java.util.List;
@@ -33,11 +36,17 @@ public DiffResult isCoreChanged() {
     if (increased.isEmpty() && missing.isEmpty()) {
       return DiffResult.NO_CHANGES;
     }
-    if (increased.stream().noneMatch(p -> p.getRequired() != null && p.getRequired())
-        && missing.isEmpty()) {
-      return DiffResult.COMPATIBLE;
+    if (!missing.isEmpty()) {
+      if (REQUEST_PARAMS_DECREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    if (increased.stream().anyMatch(p -> p.getRequired() != null && p.getRequired())) {
+      if (REQUEST_PARAMS_REQUIRED_INCREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
     }
-    return DiffResult.INCOMPATIBLE;
+    return DiffResult.COMPATIBLE;
   }
 
   public List<Parameter> getOldParameterList() {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedPath.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedPath.java
index e9fa4093a..2ba9830e7 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedPath.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedPath.java
@@ -1,5 +1,7 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.OPENAPI_ENDPOINTS_DECREASED;
+
 import io.swagger.v3.oas.models.Operation;
 import io.swagger.v3.oas.models.PathItem;
 import java.util.*;
@@ -36,10 +38,12 @@ public DiffResult isCoreChanged() {
     if (increased.isEmpty() && missing.isEmpty()) {
       return DiffResult.NO_CHANGES;
     }
-    if (missing.isEmpty()) {
-      return DiffResult.COMPATIBLE;
+    if (!missing.isEmpty()) {
+      if (OPENAPI_ENDPOINTS_DECREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
     }
-    return DiffResult.INCOMPATIBLE;
+    return DiffResult.COMPATIBLE;
   }
 
   public String getPathUrl() {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedPaths.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedPaths.java
index 96af52785..5e032b498 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedPaths.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedPaths.java
@@ -1,16 +1,24 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.OPENAPI_ENDPOINTS_DECREASED;
+
 import io.swagger.v3.oas.models.PathItem;
 import java.util.*;
+import org.openapitools.openapidiff.core.compare.OpenApiDiffOptions;
 
 public class ChangedPaths implements ComposedChanged {
+  private final OpenApiDiffOptions options;
   private final Map<String, PathItem> oldPathMap;
   private final Map<String, PathItem> newPathMap;
   private Map<String, PathItem> increased;
   private Map<String, PathItem> missing;
   private Map<String, ChangedPath> changed;
 
-  public ChangedPaths(Map<String, PathItem> oldPathMap, Map<String, PathItem> newPathMap) {
+  public ChangedPaths(
+      Map<String, PathItem> oldPathMap,
+      Map<String, PathItem> newPathMap,
+      OpenApiDiffOptions options) {
+    this.options = options;
     this.oldPathMap = oldPathMap;
     this.newPathMap = newPathMap;
     this.increased = new LinkedHashMap<>();
@@ -28,10 +36,12 @@ public DiffResult isCoreChanged() {
     if (increased.isEmpty() && missing.isEmpty()) {
       return DiffResult.NO_CHANGES;
     }
-    if (missing.isEmpty()) {
-      return DiffResult.COMPATIBLE;
+    if (!missing.isEmpty()) {
+      if (OPENAPI_ENDPOINTS_DECREASED.enabled(options.getConfig())) {
+        return DiffResult.INCOMPATIBLE;
+      }
     }
-    return DiffResult.INCOMPATIBLE;
+    return DiffResult.COMPATIBLE;
   }
 
   public Map<String, PathItem> getOldPathMap() {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedRequestBody.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedRequestBody.java
index 83fadd407..48cc4cf0e 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedRequestBody.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedRequestBody.java
@@ -1,5 +1,7 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.OPENAPI_ENDPOINTS_DECREASED;
+
 import io.swagger.v3.oas.models.parameters.RequestBody;
 import java.util.Arrays;
 import java.util.List;
@@ -31,7 +33,10 @@ public DiffResult isCoreChanged() {
     if (!changeRequired) {
       return DiffResult.NO_CHANGES;
     }
-    return DiffResult.INCOMPATIBLE;
+    if (OPENAPI_ENDPOINTS_DECREASED.enabled(context)) {
+      return DiffResult.INCOMPATIBLE;
+    }
+    return DiffResult.COMPATIBLE;
   }
 
   public RequestBody getOldRequestBody() {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSchema.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSchema.java
index d62cd7b69..1896783ac 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSchema.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSchema.java
@@ -1,14 +1,31 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_REQUIRED_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SCHEMA_DISCRIMINATOR_CHANGED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SCHEMA_TYPE_CHANGED;
+
 import io.swagger.v3.oas.models.media.Schema;
-import java.util.*;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import org.openapitools.openapidiff.core.model.schema.ChangedEnum;
+import org.openapitools.openapidiff.core.model.schema.ChangedMaxItems;
 import org.openapitools.openapidiff.core.model.schema.ChangedMaxLength;
+import org.openapitools.openapidiff.core.model.schema.ChangedMaxProperties;
+import org.openapitools.openapidiff.core.model.schema.ChangedMinItems;
+import org.openapitools.openapidiff.core.model.schema.ChangedMinProperties;
+import org.openapitools.openapidiff.core.model.schema.ChangedMultipleOf;
+import org.openapitools.openapidiff.core.model.schema.ChangedNullable;
 import org.openapitools.openapidiff.core.model.schema.ChangedNumericRange;
+import org.openapitools.openapidiff.core.model.schema.ChangedOneOfSchema;
+import org.openapitools.openapidiff.core.model.schema.ChangedPattern;
 import org.openapitools.openapidiff.core.model.schema.ChangedReadOnly;
 import org.openapitools.openapidiff.core.model.schema.ChangedRequired;
+import org.openapitools.openapidiff.core.model.schema.ChangedUniqueItems;
 import org.openapitools.openapidiff.core.model.schema.ChangedWriteOnly;
 
 public class ChangedSchema implements ComposedChanged {
@@ -21,6 +38,8 @@ public class ChangedSchema implements ComposedChanged {
   protected Map<String, Schema<?>> missingProperties;
   protected boolean changeDeprecated;
   protected ChangedMetadata description;
+  protected ChangedExamples examples;
+  protected ChangedExample example;
   protected boolean changeTitle;
   protected ChangedRequired required;
   protected boolean changeDefault;
@@ -31,7 +50,15 @@ public class ChangedSchema implements ComposedChanged {
   protected boolean changedType;
   protected ChangedMaxLength maxLength;
   protected ChangedNumericRange numericRange;
+  protected ChangedMultipleOf multipleOf;
+  protected ChangedMaxItems maxItems;
+  protected ChangedMinItems minItems;
+  protected ChangedMaxProperties maxProperties;
+  protected ChangedMinProperties minProperties;
+  protected ChangedNullable nullable;
+  protected ChangedUniqueItems uniqueItems;
   protected boolean discriminatorPropertyChanged;
+  protected ChangedPattern pattern;
   protected ChangedSchema items;
   protected ChangedOneOfSchema oneOfSchema;
   protected ChangedSchema addProp;
@@ -102,6 +129,8 @@ public List<Changed> getChangedElements() {
                   changedProperties.values().stream(),
                   Stream.of(
                       description,
+                      examples,
+                      example,
                       readOnly,
                       writeOnly,
                       items,
@@ -111,6 +140,14 @@ public List<Changed> getChangedElements() {
                       required,
                       maxLength,
                       numericRange,
+                      multipleOf,
+                      maxItems,
+                      minItems,
+                      maxProperties,
+                      minProperties,
+                      nullable,
+                      uniqueItems,
+                      pattern,
                       extensions))
               .collect(Collectors.toList());
     }
@@ -132,6 +169,7 @@ private DiffResult calculateCoreChanged() {
     if (!changedType
         && (oldSchema == null && newSchema == null || oldSchema != null && newSchema != null)
         && !changeFormat
+        && !changeDefault
         && increasedProperties.isEmpty()
         && missingProperties.isEmpty()
         && changedProperties.values().isEmpty()
@@ -139,24 +177,50 @@ private DiffResult calculateCoreChanged() {
         && !discriminatorPropertyChanged) {
       return DiffResult.NO_CHANGES;
     }
-    boolean missingRequiredProperties =
-        oldSchema != null
-            && oldSchema.getRequired() != null
-            && missingProperties.keySet().stream()
-                .anyMatch(missingProperty -> oldSchema.getRequired().contains(missingProperty));
-    boolean compatibleForResponse =
-        !missingRequiredProperties && (oldSchema == null || newSchema != null);
-    if ((context.isRequest() && compatibleForRequest()
-            || context.isResponse() && compatibleForResponse)
-        && !changedType
-        && !discriminatorPropertyChanged) {
-      return DiffResult.COMPATIBLE;
+    if (changedType) {
+      if (SCHEMA_TYPE_CHANGED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    if (discriminatorPropertyChanged) {
+      if (SCHEMA_DISCRIMINATOR_CHANGED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+
+    if (!compatibleForRequest() || !compatibleForResponse()) {
+      return DiffResult.INCOMPATIBLE;
     }
-    return DiffResult.INCOMPATIBLE;
+    return DiffResult.COMPATIBLE;
   }
 
   private boolean compatibleForRequest() {
-    return (oldSchema != null || newSchema == null);
+    if (context.isRequest()) {
+      if (oldSchema == null && newSchema != null) {
+        // TODO: dead code? If not, create test.
+        return false;
+      }
+    }
+    return true;
+  }
+
+  private boolean compatibleForResponse() {
+    if (context.isResponse()) {
+      if (oldSchema != null) {
+        if (newSchema == null) {
+          // TODO: dead code? If not, create test.
+          return false;
+        }
+        if (oldSchema.getRequired() != null
+            && missingProperties.keySet().stream()
+                .anyMatch(prop -> oldSchema.getRequired().contains(prop))) {
+          if (RESPONSE_REQUIRED_DECREASED.enabled(context)) {
+            return false;
+          }
+        }
+      }
+    }
+    return true;
   }
 
   public DiffContext getContext() {
@@ -191,6 +255,14 @@ public boolean isChangeDeprecated() {
     return this.changeDeprecated;
   }
 
+  public ChangedExamples getExamples() {
+    return this.examples;
+  }
+
+  public ChangedExample getExample() {
+    return this.example;
+  }
+
   public ChangedMetadata getDescription() {
     return this.description;
   }
@@ -231,6 +303,34 @@ public ChangedMaxLength getMaxLength() {
     return this.maxLength;
   }
 
+  public ChangedNumericRange getNumericRange() {
+    return this.numericRange;
+  }
+
+  public ChangedMultipleOf getMultipleOf() {
+    return this.multipleOf;
+  }
+
+  public ChangedMaxItems getMaxItems() {
+    return this.maxItems;
+  }
+
+  public ChangedMinItems getMinItems() {
+    return this.minItems;
+  }
+
+  public ChangedNullable getNullable() {
+    return this.nullable;
+  }
+
+  public ChangedUniqueItems getUniqueItems() {
+    return uniqueItems;
+  }
+
+  public ChangedPattern getPattern() {
+    return pattern;
+  }
+
   public boolean isDiscriminatorPropertyChanged() {
     return this.discriminatorPropertyChanged;
   }
@@ -251,6 +351,14 @@ public ChangedExtensions getExtensions() {
     return this.extensions;
   }
 
+  public ChangedMaxProperties getMaxProperties() {
+    return this.maxProperties;
+  }
+
+  public ChangedMinProperties getMinProperties() {
+    return this.minProperties;
+  }
+
   public ChangedSchema setContext(final DiffContext context) {
     this.context = context;
     return this;
@@ -301,6 +409,18 @@ public ChangedSchema setDescription(final ChangedMetadata description) {
     return this;
   }
 
+  public ChangedSchema setExamples(final ChangedExamples examples) {
+    clearChangedCache();
+    this.examples = examples;
+    return this;
+  }
+
+  public ChangedSchema setExample(final ChangedExample example) {
+    clearChangedCache();
+    this.example = example;
+    return this;
+  }
+
   public ChangedSchema setChangeTitle(final boolean changeTitle) {
     clearChangedCache();
     this.changeTitle = changeTitle;
@@ -361,6 +481,42 @@ public ChangedSchema setNumericRange(final ChangedNumericRange numericRange) {
     return this;
   }
 
+  public ChangedSchema setMultipleOf(final ChangedMultipleOf multipleOf) {
+    clearChangedCache();
+    this.multipleOf = multipleOf;
+    return this;
+  }
+
+  public ChangedSchema setMaxItems(final ChangedMaxItems maxItems) {
+    clearChangedCache();
+    this.maxItems = maxItems;
+    return this;
+  }
+
+  public ChangedSchema setMinItems(final ChangedMinItems minItems) {
+    clearChangedCache();
+    this.minItems = minItems;
+    return this;
+  }
+
+  public ChangedSchema setNullable(final ChangedNullable nullable) {
+    clearChangedCache();
+    this.nullable = nullable;
+    return this;
+  }
+
+  public ChangedSchema setUniqueItems(ChangedUniqueItems uniqueItems) {
+    clearChangedCache();
+    this.uniqueItems = uniqueItems;
+    return this;
+  }
+
+  public ChangedSchema setPattern(ChangedPattern pattern) {
+    clearChangedCache();
+    this.pattern = pattern;
+    return this;
+  }
+
   public ChangedSchema setDiscriminatorPropertyChanged(final boolean discriminatorPropertyChanged) {
     clearChangedCache();
     this.discriminatorPropertyChanged = discriminatorPropertyChanged;
@@ -391,6 +547,18 @@ public ChangedSchema setExtensions(final ChangedExtensions extensions) {
     return this;
   }
 
+  public ChangedSchema setMaxProperties(final ChangedMaxProperties maxProperties) {
+    clearChangedCache();
+    this.maxProperties = maxProperties;
+    return this;
+  }
+
+  public ChangedSchema setMinProperties(final ChangedMinProperties minProperties) {
+    clearChangedCache();
+    this.minProperties = minProperties;
+    return this;
+  }
+
   @Override
   public boolean equals(Object o) {
     if (this == o) return true;
@@ -410,16 +578,26 @@ public boolean equals(Object o) {
         && Objects.equals(increasedProperties, that.increasedProperties)
         && Objects.equals(missingProperties, that.missingProperties)
         && Objects.equals(description, that.description)
+        && Objects.equals(examples, that.examples)
+        && Objects.equals(example, that.example)
         && Objects.equals(required, that.required)
         && Objects.equals(enumeration, that.enumeration)
         && Objects.equals(readOnly, that.readOnly)
         && Objects.equals(writeOnly, that.writeOnly)
         && Objects.equals(maxLength, that.maxLength)
         && Objects.equals(numericRange, that.numericRange)
+        && Objects.equals(multipleOf, that.multipleOf)
+        && Objects.equals(maxItems, that.maxItems)
+        && Objects.equals(minItems, that.minItems)
+        && Objects.equals(nullable, that.nullable)
+        && Objects.equals(uniqueItems, that.uniqueItems)
         && Objects.equals(items, that.items)
         && Objects.equals(oneOfSchema, that.oneOfSchema)
         && Objects.equals(addProp, that.addProp)
-        && Objects.equals(extensions, that.extensions);
+        && Objects.equals(extensions, that.extensions)
+        && Objects.equals(maxProperties, that.maxProperties)
+        && Objects.equals(pattern, that.pattern)
+        && Objects.equals(minProperties, that.minProperties);
   }
 
   @Override
@@ -434,6 +612,8 @@ public int hashCode() {
         missingProperties,
         changeDeprecated,
         description,
+        examples,
+        example,
         changeTitle,
         required,
         changeDefault,
@@ -444,11 +624,19 @@ public int hashCode() {
         changedType,
         maxLength,
         numericRange,
+        multipleOf,
+        maxItems,
+        minItems,
+        nullable,
+        uniqueItems,
         discriminatorPropertyChanged,
         items,
         oneOfSchema,
         addProp,
-        extensions);
+        extensions,
+        maxProperties,
+        pattern,
+        minProperties);
   }
 
   @java.lang.Override
@@ -471,6 +659,10 @@ public java.lang.String toString() {
         + this.isChangeDeprecated()
         + ", description="
         + this.getDescription()
+        + ", examples="
+        + this.getExamples()
+        + ", example="
+        + this.getExample()
         + ", changeTitle="
         + this.isChangeTitle()
         + ", required="
@@ -489,6 +681,18 @@ public java.lang.String toString() {
         + this.isChangedType()
         + ", maxLength="
         + this.getMaxLength()
+        + ", numericRange="
+        + this.getNumericRange()
+        + ", multipleOf="
+        + this.getMultipleOf()
+        + ", maxItems="
+        + this.getMaxItems()
+        + ", minItems="
+        + this.getMinItems()
+        + ", nullable="
+        + this.getNullable()
+        + ", uniqueItems="
+        + this.getUniqueItems()
         + ", discriminatorPropertyChanged="
         + this.isDiscriminatorPropertyChanged()
         + ", items="
@@ -499,6 +703,12 @@ public java.lang.String toString() {
         + this.getAddProp()
         + ", extensions="
         + this.getExtensions()
+        + ", maxProperties="
+        + this.getMaxProperties()
+        + ", minProperties="
+        + this.getMinProperties()
+        + ", pattern="
+        + this.getPattern()
         + ")";
   }
 }
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSecurityRequirement.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSecurityRequirement.java
index f8e61f7dc..0c5ed1535 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSecurityRequirement.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSecurityRequirement.java
@@ -1,5 +1,7 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_REQUIREMENT_SCHEMES_INCREASED;
+
 import io.swagger.v3.oas.models.security.SecurityRequirement;
 import java.util.ArrayList;
 import java.util.List;
@@ -8,14 +10,18 @@
 public class ChangedSecurityRequirement implements ComposedChanged {
   private SecurityRequirement oldSecurityRequirement;
   private SecurityRequirement newSecurityRequirement;
+  private final DiffContext context;
   private SecurityRequirement missing;
   private SecurityRequirement increased;
   private List<ChangedSecurityScheme> changed;
 
   public ChangedSecurityRequirement(
-      SecurityRequirement oldSecurityRequirement, SecurityRequirement newSecurityRequirement) {
+      SecurityRequirement oldSecurityRequirement,
+      SecurityRequirement newSecurityRequirement,
+      DiffContext context) {
     this.oldSecurityRequirement = oldSecurityRequirement;
     this.newSecurityRequirement = newSecurityRequirement;
+    this.context = context;
     this.changed = new ArrayList<>();
   }
 
@@ -29,10 +35,12 @@ public DiffResult isCoreChanged() {
     if (increased == null && missing == null) {
       return DiffResult.NO_CHANGES;
     }
-    if (increased == null) {
-      return DiffResult.COMPATIBLE;
+    if (increased != null) {
+      if (SECURITY_REQUIREMENT_SCHEMES_INCREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
     }
-    return DiffResult.INCOMPATIBLE;
+    return DiffResult.COMPATIBLE;
   }
 
   public void addMissing(String key, List<String> scopes) {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSecurityRequirements.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSecurityRequirements.java
index d8f813801..3a8f90a34 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSecurityRequirements.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSecurityRequirements.java
@@ -1,5 +1,7 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_REQUIREMENTS_DECREASED;
+
 import io.swagger.v3.oas.models.security.SecurityRequirement;
 import java.util.ArrayList;
 import java.util.List;
@@ -9,15 +11,18 @@
 public class ChangedSecurityRequirements implements ComposedChanged {
   private List<SecurityRequirement> oldSecurityRequirements;
   private List<SecurityRequirement> newSecurityRequirements;
+  private final DiffContext context;
   private List<SecurityRequirement> missing;
   private List<SecurityRequirement> increased;
   private List<ChangedSecurityRequirement> changed;
 
   public ChangedSecurityRequirements(
       List<SecurityRequirement> oldSecurityRequirements,
-      List<SecurityRequirement> newSecurityRequirements) {
+      List<SecurityRequirement> newSecurityRequirements,
+      DiffContext context) {
     this.oldSecurityRequirements = oldSecurityRequirements;
     this.newSecurityRequirements = newSecurityRequirements;
+    this.context = context;
     this.changed = new ArrayList<>();
   }
 
@@ -31,10 +36,12 @@ public DiffResult isCoreChanged() {
     if (CollectionUtils.isEmpty(missing) && CollectionUtils.isEmpty(increased)) {
       return DiffResult.NO_CHANGES;
     }
-    if (CollectionUtils.isEmpty(missing)) {
-      return DiffResult.COMPATIBLE;
+    if (CollectionUtils.isNotEmpty(missing)) {
+      if (SECURITY_REQUIREMENTS_DECREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
     }
-    return DiffResult.INCOMPATIBLE;
+    return DiffResult.COMPATIBLE;
   }
 
   public void addMissing(SecurityRequirement securityRequirement) {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSecurityScheme.java b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSecurityScheme.java
index 2850e0f17..1adb56b6f 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSecurityScheme.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedSecurityScheme.java
@@ -1,5 +1,7 @@
 package org.openapitools.openapidiff.core.model;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.*;
+
 import io.swagger.v3.oas.models.security.SecurityScheme;
 import java.util.Arrays;
 import java.util.List;
@@ -8,6 +10,7 @@
 public class ChangedSecurityScheme implements ComposedChanged {
   private SecurityScheme oldSecurityScheme;
   private SecurityScheme newSecurityScheme;
+  private final DiffContext context;
   private boolean changedType;
   private boolean changedIn;
   private boolean changedScheme;
@@ -18,9 +21,11 @@ public class ChangedSecurityScheme implements ComposedChanged {
   private ChangedOAuthFlows oAuthFlows;
   private ChangedExtensions extensions;
 
-  public ChangedSecurityScheme(SecurityScheme oldSecurityScheme, SecurityScheme newSecurityScheme) {
+  public ChangedSecurityScheme(
+      SecurityScheme oldSecurityScheme, SecurityScheme newSecurityScheme, DiffContext context) {
     this.oldSecurityScheme = oldSecurityScheme;
     this.newSecurityScheme = newSecurityScheme;
+    this.context = context;
   }
 
   @Override
@@ -38,22 +43,36 @@ public DiffResult isCoreChanged() {
         && (changedScopes == null || changedScopes.isUnchanged())) {
       return DiffResult.NO_CHANGES;
     }
-    if (!changedType
-        && !changedIn
-        && !changedScheme
-        && !changedBearerFormat
-        && !changedOpenIdConnectUrl
-        && (changedScopes == null || changedScopes.getIncreased().isEmpty())) {
 
+    if (changedBearerFormat) {
+      if (SECURITY_SCHEME_BEARER_FORMAT_CHANGED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    if (changedOpenIdConnectUrl) {
+      if (SECURITY_SCHEME_OPENIDCONNECT_URL_CHANGED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    if (changedScheme) {
+      if (SECURITY_SCHEME_SCHEME_CHANGED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    if (changedScopes != null && !changedScopes.getIncreased().isEmpty()) {
+      if (SECURITY_SCHEME_SCOPES_INCREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    if (changedIn || changedType) {
       // TODO: Dead code removal opportunity for changedType and changedIn. It appears that
       // SecuritySchemaDiff will never be given the chance to detect differences TYPE and
       // IN differences because that case has already been detected and filtered out by
       // SecurityRequirementsDiff and recorded as a dropped requirement in
       // ChangedSecurityRequirements.
-
-      return DiffResult.COMPATIBLE;
+      return DiffResult.INCOMPATIBLE;
     }
-    return DiffResult.INCOMPATIBLE;
+    return DiffResult.COMPATIBLE;
   }
 
   public SecurityScheme getOldSecurityScheme() {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/DiffContext.java b/core/src/main/java/org/openapitools/openapidiff/core/model/DiffContext.java
index 485c3518b..f2003d375 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/DiffContext.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/DiffContext.java
@@ -1,13 +1,17 @@
 package org.openapitools.openapidiff.core.model;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import io.swagger.v3.oas.models.PathItem;
 import java.util.HashMap;
 import java.util.Map;
+import org.apache.commons.configuration2.Configuration;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.openapitools.openapidiff.core.compare.OpenApiDiffOptions;
 
 public class DiffContext {
 
+  @JsonIgnore private final OpenApiDiffOptions options;
   private String url;
   private Map<String, String> parameters;
   private PathItem.HttpMethod method;
@@ -17,7 +21,8 @@ public class DiffContext {
   private String leftUrl;
   private String rightUrl;
 
-  public DiffContext() {
+  public DiffContext(OpenApiDiffOptions options) {
+    this.options = options;
     parameters = new HashMap<>();
     response = false;
     request = true;
@@ -43,6 +48,16 @@ public DiffContext copyWithLeftRightUrls(String leftUrl, String rightUrl) {
     return copy().setLeftAndRightUrls(leftUrl, rightUrl);
   }
 
+  @JsonIgnore
+  public OpenApiDiffOptions getOptions() {
+    return options;
+  }
+
+  @JsonIgnore
+  public Configuration getConfig() {
+    return options.getConfig();
+  }
+
   private DiffContext setRequest() {
     this.request = true;
     this.response = false;
@@ -82,7 +97,7 @@ private DiffContext setMethod(PathItem.HttpMethod method) {
   }
 
   private DiffContext copy() {
-    DiffContext context = new DiffContext();
+    DiffContext context = new DiffContext(options);
     context.url = this.url;
     context.parameters = this.parameters;
     context.method = this.method;
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/deferred/RecursiveSchemaSet.java b/core/src/main/java/org/openapitools/openapidiff/core/model/deferred/RecursiveSchemaSet.java
index 079139db2..890d2e6c0 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/deferred/RecursiveSchemaSet.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/deferred/RecursiveSchemaSet.java
@@ -7,12 +7,20 @@ public class RecursiveSchemaSet {
   HashSet<String> leftKeys = new HashSet<>();
   HashSet<String> rightKeys = new HashSet<>();
 
+  public HashSet<String> getLeftKeys() {
+    return leftKeys;
+  }
+
+  public HashSet<String> getRightKeys() {
+    return rightKeys;
+  }
+
   public boolean contains(CacheKey key) {
     return leftKeys.contains(key.getLeft()) || rightKeys.contains(key.getRight());
   }
 
   public void put(CacheKey key) {
     leftKeys.add(key.getLeft());
-    leftKeys.add(key.getRight());
+    rightKeys.add(key.getRight());
   }
 }
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedEnum.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedEnum.java
index 0dcd5e6e9..ef4486628 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedEnum.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedEnum.java
@@ -1,5 +1,8 @@
 package org.openapitools.openapidiff.core.model.schema;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_ENUM_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_ENUM_INCREASED;
+
 import java.util.List;
 import org.openapitools.openapidiff.core.model.ChangedList;
 import org.openapitools.openapidiff.core.model.DiffContext;
@@ -13,10 +16,16 @@ public ChangedEnum(List<T> oldValue, List<T> newValue, DiffContext context) {
 
   @Override
   public DiffResult isItemsChanged() {
-    if (context.isRequest() && getMissing().isEmpty()
-        || context.isResponse() && getIncreased().isEmpty()) {
-      return DiffResult.COMPATIBLE;
+    if (context.isRequest() && !getMissing().isEmpty()) {
+      if (REQUEST_ENUM_DECREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    if (context.isResponse() && !getIncreased().isEmpty()) {
+      if (RESPONSE_ENUM_INCREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
     }
-    return DiffResult.INCOMPATIBLE;
+    return DiffResult.COMPATIBLE;
   }
 }
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxItems.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxItems.java
new file mode 100644
index 000000000..a452adac2
--- /dev/null
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxItems.java
@@ -0,0 +1,44 @@
+package org.openapitools.openapidiff.core.model.schema;
+
+import java.util.Objects;
+import org.openapitools.openapidiff.core.model.Changed;
+import org.openapitools.openapidiff.core.model.DiffContext;
+import org.openapitools.openapidiff.core.model.DiffResult;
+
+public class ChangedMaxItems implements Changed {
+  private final Integer oldValue;
+  private final Integer newValue;
+  private final DiffContext context;
+
+  public ChangedMaxItems(Integer oldValue, Integer newValue, DiffContext context) {
+    this.oldValue = oldValue;
+    this.newValue = newValue;
+    this.context = context;
+  }
+
+  @Override
+  public DiffResult isChanged() {
+    if (Objects.equals(oldValue, newValue)) {
+      return DiffResult.NO_CHANGES;
+    }
+    if (oldValue == null || newValue == null) {
+      return DiffResult.COMPATIBLE;
+    }
+    if (newValue < oldValue) {
+      return DiffResult.INCOMPATIBLE;
+    }
+    return DiffResult.COMPATIBLE;
+  }
+
+  public Integer getOldValue() {
+    return oldValue;
+  }
+
+  public Integer getNewValue() {
+    return newValue;
+  }
+
+  public DiffContext getContext() {
+    return context;
+  }
+}
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxLength.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxLength.java
index 8bb5933da..efb068bcf 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxLength.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxLength.java
@@ -1,5 +1,8 @@
 package org.openapitools.openapidiff.core.model.schema;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_MAX_LENGTH_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_MAX_LENGTH_INCREASED;
+
 import java.util.Objects;
 import org.openapitools.openapidiff.core.model.Changed;
 import org.openapitools.openapidiff.core.model.DiffContext;
@@ -15,11 +18,17 @@ public DiffResult isChanged() {
     if (Objects.equals(oldValue, newValue)) {
       return DiffResult.NO_CHANGES;
     }
-    if (context.isRequest() && (newValue == null || oldValue != null && oldValue <= newValue)
-        || context.isResponse() && (oldValue == null || newValue != null && newValue <= oldValue)) {
-      return DiffResult.COMPATIBLE;
+    if (context.isRequest() && (oldValue == null || newValue != null && newValue < oldValue)) {
+      if (REQUEST_MAX_LENGTH_DECREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    if (context.isResponse() && (newValue == null || oldValue != null && newValue > oldValue)) {
+      if (RESPONSE_MAX_LENGTH_INCREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
     }
-    return DiffResult.INCOMPATIBLE;
+    return DiffResult.COMPATIBLE;
   }
 
   public ChangedMaxLength(
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxProperties.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxProperties.java
new file mode 100644
index 000000000..c4c56af3f
--- /dev/null
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMaxProperties.java
@@ -0,0 +1,46 @@
+package org.openapitools.openapidiff.core.model.schema;
+
+import org.openapitools.openapidiff.core.model.Changed;
+import org.openapitools.openapidiff.core.model.DiffContext;
+import org.openapitools.openapidiff.core.model.DiffResult;
+
+public class ChangedMaxProperties implements Changed {
+  private Integer oldValue;
+  private Integer newValue;
+  private DiffContext context;
+
+  public ChangedMaxProperties(Integer oldValue, Integer newValue, DiffContext context) {
+    this.oldValue = oldValue;
+    this.newValue = newValue;
+    this.context = context;
+  }
+
+  public Integer getOldValue() {
+    return oldValue;
+  }
+
+  public Integer getNewValue() {
+    return newValue;
+  }
+
+  @Override
+  public DiffResult isChanged() {
+    if (oldValue == null && newValue == null) {
+      return DiffResult.NO_CHANGES;
+    }
+
+    if (oldValue == null) {
+      return DiffResult.INCOMPATIBLE;
+    }
+
+    if (newValue == null) {
+      return DiffResult.COMPATIBLE;
+    }
+
+    if (!oldValue.equals(newValue)) {
+      return oldValue > newValue ? DiffResult.INCOMPATIBLE : DiffResult.COMPATIBLE;
+    }
+
+    return DiffResult.NO_CHANGES;
+  }
+}
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMinItems.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMinItems.java
new file mode 100644
index 000000000..cb5604e73
--- /dev/null
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMinItems.java
@@ -0,0 +1,44 @@
+package org.openapitools.openapidiff.core.model.schema;
+
+import java.util.Objects;
+import org.openapitools.openapidiff.core.model.Changed;
+import org.openapitools.openapidiff.core.model.DiffContext;
+import org.openapitools.openapidiff.core.model.DiffResult;
+
+public class ChangedMinItems implements Changed {
+  private final Integer oldValue;
+  private final Integer newValue;
+  private final DiffContext context;
+
+  public ChangedMinItems(Integer oldValue, Integer newValue, DiffContext context) {
+    this.oldValue = oldValue;
+    this.newValue = newValue;
+    this.context = context;
+  }
+
+  @Override
+  public DiffResult isChanged() {
+    if (Objects.equals(oldValue, newValue)) {
+      return DiffResult.NO_CHANGES;
+    }
+    if (oldValue == null || newValue == null) {
+      return DiffResult.COMPATIBLE;
+    }
+    if (newValue > oldValue) {
+      return DiffResult.INCOMPATIBLE;
+    }
+    return DiffResult.COMPATIBLE;
+  }
+
+  public Integer getOldValue() {
+    return oldValue;
+  }
+
+  public Integer getNewValue() {
+    return newValue;
+  }
+
+  public DiffContext getContext() {
+    return context;
+  }
+}
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMinProperties.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMinProperties.java
new file mode 100644
index 000000000..f574b5c80
--- /dev/null
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMinProperties.java
@@ -0,0 +1,46 @@
+package org.openapitools.openapidiff.core.model.schema;
+
+import org.openapitools.openapidiff.core.model.Changed;
+import org.openapitools.openapidiff.core.model.DiffContext;
+import org.openapitools.openapidiff.core.model.DiffResult;
+
+public class ChangedMinProperties implements Changed {
+  private Integer oldValue;
+  private Integer newValue;
+  private DiffContext context;
+
+  public ChangedMinProperties(Integer oldValue, Integer newValue, DiffContext context) {
+    this.oldValue = oldValue;
+    this.newValue = newValue;
+    this.context = context;
+  }
+
+  public Integer getOldValue() {
+    return oldValue;
+  }
+
+  public Integer getNewValue() {
+    return newValue;
+  }
+
+  @Override
+  public DiffResult isChanged() {
+    if (oldValue == null && newValue == null) {
+      return DiffResult.NO_CHANGES;
+    }
+
+    if (oldValue == null) {
+      return DiffResult.INCOMPATIBLE;
+    }
+
+    if (newValue == null) {
+      return DiffResult.COMPATIBLE;
+    }
+
+    if (!oldValue.equals(newValue)) {
+      return newValue > oldValue ? DiffResult.INCOMPATIBLE : DiffResult.COMPATIBLE;
+    }
+
+    return DiffResult.NO_CHANGES;
+  }
+}
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMultipleOf.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMultipleOf.java
new file mode 100644
index 000000000..adaf15710
--- /dev/null
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedMultipleOf.java
@@ -0,0 +1,57 @@
+package org.openapitools.openapidiff.core.model.schema;
+
+import java.math.BigDecimal;
+import java.util.Objects;
+import org.openapitools.openapidiff.core.model.Changed;
+import org.openapitools.openapidiff.core.model.DiffResult;
+
+public class ChangedMultipleOf implements Changed {
+
+  private final BigDecimal left;
+  private final BigDecimal right;
+
+  public ChangedMultipleOf(BigDecimal leftMultipleOf, BigDecimal rightMultipleOf) {
+    this.left = leftMultipleOf;
+    this.right = rightMultipleOf;
+  }
+
+  @Override
+  public DiffResult isChanged() {
+    if (Objects.equals(left, right)) {
+      return DiffResult.NO_CHANGES;
+    }
+
+    // multipleof removed -> compatible
+    if (right == null) {
+      return DiffResult.COMPATIBLE;
+    }
+
+    return DiffResult.INCOMPATIBLE;
+  }
+
+  public BigDecimal getLeft() {
+    return left;
+  }
+
+  public BigDecimal getRight() {
+    return right;
+  }
+
+  @Override
+  public String toString() {
+    return "ChangedMultipleOf [left=" + left + ", right=" + right + "]";
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    ChangedMultipleOf that = (ChangedMultipleOf) o;
+    return Objects.equals(left, that.getLeft()) && Objects.equals(right, that.getRight());
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(left, right);
+  }
+}
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedNullable.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedNullable.java
new file mode 100644
index 000000000..befc1d16d
--- /dev/null
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedNullable.java
@@ -0,0 +1,54 @@
+package org.openapitools.openapidiff.core.model.schema;
+
+import java.util.Objects;
+import org.openapitools.openapidiff.core.model.Changed;
+import org.openapitools.openapidiff.core.model.DiffResult;
+
+public class ChangedNullable implements Changed {
+
+  private final Boolean left;
+  private final Boolean right;
+
+  public ChangedNullable(Boolean leftNullable, Boolean rightNullable) {
+    this.left = leftNullable;
+    this.right = rightNullable;
+  }
+
+  @Override
+  public DiffResult isChanged() {
+    boolean leftValue = left != null && left;
+    boolean rightValue = right != null && right;
+
+    if (leftValue != rightValue) {
+      return DiffResult.COMPATIBLE;
+    }
+
+    return DiffResult.NO_CHANGES;
+  }
+
+  public Boolean getLeft() {
+    return left;
+  }
+
+  public Boolean getRight() {
+    return right;
+  }
+
+  @Override
+  public String toString() {
+    return "ChangedNullable [left=" + left + ", right=" + right + "]";
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    ChangedNullable that = (ChangedNullable) o;
+    return Objects.equals(left, that.getLeft()) && Objects.equals(right, that.getRight());
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(left, right);
+  }
+}
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedNumericRange.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedNumericRange.java
index 537496cd9..151c12fb6 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedNumericRange.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedNumericRange.java
@@ -1,5 +1,9 @@
 package org.openapitools.openapidiff.core.model.schema;
 
+import static org.apache.commons.lang3.BooleanUtils.isTrue;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_NUMERIC_RANGE_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_NUMERIC_RANGE_INCREASED;
+
 import java.math.BigDecimal;
 import java.util.Objects;
 import org.openapitools.openapidiff.core.model.Changed;
@@ -25,35 +29,48 @@ public DiffResult isChanged() {
         && Objects.equals(oldMaximumExclusiveValue, newMaximumExclusiveValue)) {
       return DiffResult.NO_CHANGES;
     }
-    if (context.isRequest()
-            && (newMinimumValue == null
-                || oldMinimumValue != null
-                    && oldMinimumValue.unscaledValue().compareTo(newMinimumValue.unscaledValue())
-                        >= 0)
-            && (newMaximumValue == null
-                || oldMaximumValue != null
-                    && oldMaximumValue.unscaledValue().compareTo(newMaximumValue.unscaledValue())
-                        <= 0)
-            && (newMinimumExclusiveValue == null
-                || oldMinimumExclusiveValue != null && newMinimumExclusiveValue == true)
-            && (newMaximumExclusiveValue == null
-                || oldMaximumExclusiveValue != null && newMaximumExclusiveValue == true)
-        || context.isResponse()
-            && (newMinimumValue == null
-                || oldMinimumValue != null
-                    && oldMinimumValue.unscaledValue().compareTo(newMinimumValue.unscaledValue())
-                        >= 0)
-            && (newMaximumValue == null
-                || oldMaximumValue != null
-                    && oldMaximumValue.unscaledValue().compareTo(newMaximumValue.unscaledValue())
-                        <= 0)
-            && (newMinimumExclusiveValue == null
-                || oldMinimumExclusiveValue != null && newMinimumExclusiveValue == true)
-            && (newMaximumExclusiveValue == null
-                || oldMaximumExclusiveValue != null && newMaximumExclusiveValue == true)) {
+
+    if ((context.isRequest() && !REQUEST_NUMERIC_RANGE_DECREASED.enabled(context))
+        || (context.isResponse() && !RESPONSE_NUMERIC_RANGE_INCREASED.enabled(context))) {
       return DiffResult.COMPATIBLE;
     }
-    return DiffResult.INCOMPATIBLE;
+
+    boolean exclusiveMaxOld = isTrue(oldMaximumExclusiveValue);
+    boolean exclusiveMinOld = isTrue(oldMinimumExclusiveValue);
+    boolean exclusiveMaxNew = isTrue(newMaximumExclusiveValue);
+    boolean exclusiveMinNew = isTrue(newMinimumExclusiveValue);
+    int diffMax = compare(oldMaximumValue, newMaximumValue, false);
+    int diffMin = compare(oldMinimumValue, newMinimumValue, true);
+
+    if (context.isRequest()) {
+      if (diffMax > 0 || (diffMax == 0 && !exclusiveMaxOld && exclusiveMaxNew)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+      if (diffMin < 0 || (diffMin == 0 && !exclusiveMinOld && exclusiveMinNew)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    } else if (context.isResponse()) {
+      if (diffMax < 0 || (diffMax == 0 && exclusiveMaxOld && !exclusiveMaxNew)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+      if (diffMin > 0 || (diffMin == 0 && exclusiveMinOld && !exclusiveMinNew)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    return DiffResult.COMPATIBLE;
+  }
+
+  private int compare(BigDecimal left, BigDecimal right, boolean nullMeansLessThan) {
+    if (left == null && right == null) {
+      return 0;
+    }
+    if (left == null) {
+      return nullMeansLessThan ? -1 : 1;
+    }
+    if (right == null) {
+      return nullMeansLessThan ? 1 : -1;
+    }
+    return left.unscaledValue().compareTo(right.unscaledValue());
   }
 
   public ChangedNumericRange(
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedOneOfSchema.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedOneOfSchema.java
similarity index 75%
rename from core/src/main/java/org/openapitools/openapidiff/core/model/ChangedOneOfSchema.java
rename to core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedOneOfSchema.java
index ebf07d2b7..60159f569 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/ChangedOneOfSchema.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedOneOfSchema.java
@@ -1,10 +1,18 @@
-package org.openapitools.openapidiff.core.model;
+package org.openapitools.openapidiff.core.model.schema;
+
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_ONEOF_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_ONEOF_INCREASED;
 
 import io.swagger.v3.oas.models.media.Schema;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import org.openapitools.openapidiff.core.model.Changed;
+import org.openapitools.openapidiff.core.model.ChangedSchema;
+import org.openapitools.openapidiff.core.model.ComposedChanged;
+import org.openapitools.openapidiff.core.model.DiffContext;
+import org.openapitools.openapidiff.core.model.DiffResult;
 
 public class ChangedOneOfSchema implements ComposedChanged {
   private final Map<String, String> oldMapping;
@@ -31,10 +39,17 @@ public DiffResult isCoreChanged() {
     if (increased.isEmpty() && missing.isEmpty()) {
       return DiffResult.NO_CHANGES;
     }
-    if (context.isRequest() && missing.isEmpty() || context.isResponse() && increased.isEmpty()) {
-      return DiffResult.COMPATIBLE;
+    if (context.isRequest() && !missing.isEmpty()) {
+      if (REQUEST_ONEOF_DECREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    if (context.isResponse() && !increased.isEmpty()) {
+      if (RESPONSE_ONEOF_INCREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
     }
-    return DiffResult.INCOMPATIBLE;
+    return DiffResult.COMPATIBLE;
   }
 
   public Map<String, String> getOldMapping() {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedPattern.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedPattern.java
new file mode 100644
index 000000000..06907cd2e
--- /dev/null
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedPattern.java
@@ -0,0 +1,47 @@
+package org.openapitools.openapidiff.core.model.schema;
+
+import java.util.Objects;
+import org.openapitools.openapidiff.core.model.Changed;
+import org.openapitools.openapidiff.core.model.DiffContext;
+import org.openapitools.openapidiff.core.model.DiffResult;
+
+public class ChangedPattern implements Changed {
+  private final String oldPattern;
+  private final String newPattern;
+  private final DiffContext context;
+
+  public ChangedPattern(String oldPattern, String newPattern, DiffContext context) {
+    this.oldPattern = oldPattern;
+    this.newPattern = newPattern;
+    this.context = context;
+  }
+
+  @Override
+  public DiffResult isChanged() {
+    return Objects.equals(oldPattern, newPattern) ? DiffResult.NO_CHANGES : DiffResult.INCOMPATIBLE;
+  }
+
+  @Override
+  public boolean isCompatible() {
+    return Objects.equals(oldPattern, newPattern);
+  }
+
+  public DiffResult isDiffBackwardCompatible() {
+    if (!Objects.equals(oldPattern, newPattern)) {
+      return DiffResult.INCOMPATIBLE;
+    }
+    return DiffResult.COMPATIBLE;
+  }
+
+  public String getOldPattern() {
+    return oldPattern;
+  }
+
+  public String getNewPattern() {
+    return newPattern;
+  }
+
+  public DiffContext getContext() {
+    return context;
+  }
+}
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedReadOnly.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedReadOnly.java
index 25d86af8f..9bde49acd 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedReadOnly.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedReadOnly.java
@@ -1,5 +1,8 @@
 package org.openapitools.openapidiff.core.model.schema;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_READONLY_INCREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_READONLY_REQUIRED_DECREASED;
+
 import java.util.Objects;
 import java.util.Optional;
 import org.openapitools.openapidiff.core.model.Changed;
@@ -29,10 +32,16 @@ public DiffResult isChanged() {
     }
     if (context.isRequest()) {
       if (Boolean.TRUE.equals(newValue)) {
-        return DiffResult.INCOMPATIBLE;
-      } else {
-        return context.isRequired() ? DiffResult.INCOMPATIBLE : DiffResult.COMPATIBLE;
+        if (REQUEST_READONLY_INCREASED.enabled(context)) {
+          return DiffResult.INCOMPATIBLE;
+        }
+      } else if (context.isRequired()) {
+        // Incompatible because a prev RO prop (invalid) is now not RO and required
+        if (REQUEST_READONLY_REQUIRED_DECREASED.enabled(context)) {
+          return DiffResult.INCOMPATIBLE;
+        }
       }
+      return DiffResult.COMPATIBLE;
     }
     return DiffResult.UNKNOWN;
   }
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedRequired.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedRequired.java
index d6b41f3cd..58a9ae49a 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedRequired.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedRequired.java
@@ -1,5 +1,8 @@
 package org.openapitools.openapidiff.core.model.schema;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_REQUIRED_INCREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_REQUIRED_DECREASED;
+
 import java.util.List;
 import org.openapitools.openapidiff.core.model.ChangedList;
 import org.openapitools.openapidiff.core.model.DiffContext;
@@ -13,10 +16,16 @@ public ChangedRequired(List<String> oldValue, List<String> newValue, DiffContext
 
   @Override
   public DiffResult isItemsChanged() {
-    if (context.isRequest() && getIncreased().isEmpty()
-        || context.isResponse() && getMissing().isEmpty()) {
-      return DiffResult.COMPATIBLE;
+    if (context.isRequest() && !getIncreased().isEmpty()) {
+      if (REQUEST_REQUIRED_INCREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
+    }
+    if (context.isResponse() && !getMissing().isEmpty()) {
+      if (RESPONSE_REQUIRED_DECREASED.enabled(context)) {
+        return DiffResult.INCOMPATIBLE;
+      }
     }
-    return DiffResult.INCOMPATIBLE;
+    return DiffResult.COMPATIBLE;
   }
 }
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedUniqueItems.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedUniqueItems.java
new file mode 100644
index 000000000..ecccdf674
--- /dev/null
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedUniqueItems.java
@@ -0,0 +1,58 @@
+package org.openapitools.openapidiff.core.model.schema;
+
+import java.util.Objects;
+import org.openapitools.openapidiff.core.model.Changed;
+import org.openapitools.openapidiff.core.model.DiffResult;
+
+public class ChangedUniqueItems implements Changed {
+
+  private final Boolean left;
+  private final Boolean right;
+
+  public ChangedUniqueItems(Boolean leftNullable, Boolean rightNullable) {
+    this.left = leftNullable;
+    this.right = rightNullable;
+  }
+
+  @Override
+  public DiffResult isChanged() {
+    boolean leftValue = left != null && left;
+    boolean rightValue = right != null && right;
+
+    if (leftValue == false && rightValue == true) {
+      return DiffResult.INCOMPATIBLE;
+    }
+
+    if (leftValue == true && rightValue == false) {
+      return DiffResult.COMPATIBLE;
+    }
+
+    return DiffResult.NO_CHANGES;
+  }
+
+  public Boolean getLeft() {
+    return left;
+  }
+
+  public Boolean getRight() {
+    return right;
+  }
+
+  @Override
+  public String toString() {
+    return "ChangedUniqueItems [left=" + left + ", right=" + right + "]";
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    ChangedNullable that = (ChangedNullable) o;
+    return Objects.equals(left, that.getLeft()) && Objects.equals(right, that.getRight());
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(left, right);
+  }
+}
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedWriteOnly.java b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedWriteOnly.java
index 91d19a644..110b6ede2 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedWriteOnly.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/model/schema/ChangedWriteOnly.java
@@ -1,5 +1,8 @@
 package org.openapitools.openapidiff.core.model.schema;
 
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_WRITEONLY_INCREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_WRITEONLY_REQUIRED_DECREASED;
+
 import java.util.Objects;
 import java.util.Optional;
 import org.openapitools.openapidiff.core.model.Changed;
@@ -29,10 +32,15 @@ public DiffResult isChanged() {
     }
     if (context.isResponse()) {
       if (Boolean.TRUE.equals(newValue)) {
-        return DiffResult.INCOMPATIBLE;
-      } else {
-        return context.isRequired() ? DiffResult.INCOMPATIBLE : DiffResult.COMPATIBLE;
+        if (RESPONSE_WRITEONLY_INCREASED.enabled(context)) {
+          return DiffResult.INCOMPATIBLE;
+        }
+      } else if (context.isRequired()) {
+        if (RESPONSE_WRITEONLY_REQUIRED_DECREASED.enabled(context)) {
+          return DiffResult.INCOMPATIBLE;
+        }
       }
+      return DiffResult.COMPATIBLE;
     }
     return DiffResult.UNKNOWN;
   }
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/output/AsciidocRender.java b/core/src/main/java/org/openapitools/openapidiff/core/output/AsciidocRender.java
new file mode 100644
index 000000000..997241dc2
--- /dev/null
+++ b/core/src/main/java/org/openapitools/openapidiff/core/output/AsciidocRender.java
@@ -0,0 +1,311 @@
+package org.openapitools.openapidiff.core.output;
+
+import static org.openapitools.openapidiff.core.model.Changed.result;
+
+import io.swagger.v3.oas.models.media.ArraySchema;
+import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.oas.models.parameters.Parameter;
+import io.swagger.v3.oas.models.responses.ApiResponse;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import org.apache.commons.lang3.StringUtils;
+import org.openapitools.openapidiff.core.exception.RendererException;
+import org.openapitools.openapidiff.core.model.*;
+import org.openapitools.openapidiff.core.utils.RefPointer;
+import org.openapitools.openapidiff.core.utils.RefType;
+
+public class AsciidocRender implements Render {
+  private static final int LINE_LENGTH = 74;
+  protected static RefPointer<Schema<?>> refPointer = new RefPointer<>(RefType.SCHEMAS);
+  protected ChangedOpenApi diff;
+
+  @Override
+  public void render(ChangedOpenApi diff, OutputStreamWriter outputStreamWriter) {
+    this.diff = diff;
+    if (diff.isUnchanged()) {
+      safelyAppend(
+          outputStreamWriter,
+          bigTitle(
+              diff.getNewSpecOpenApi().getInfo().getTitle(),
+              diff.getNewSpecOpenApi().getInfo().getVersion()));
+      safelyAppend(outputStreamWriter, System.lineSeparator());
+      safelyAppend(outputStreamWriter, System.lineSeparator());
+      safelyAppend(outputStreamWriter, "NOTE: No differences. Specifications are equivalents");
+    } else {
+      safelyAppend(
+          outputStreamWriter,
+          bigTitle(
+              diff.getNewSpecOpenApi().getInfo().getTitle(),
+              diff.getNewSpecOpenApi().getInfo().getVersion()));
+      safelyAppend(outputStreamWriter, System.lineSeparator());
+      safelyAppend(outputStreamWriter, ":reproducible:\n:sectlinks:\n:toc:\n");
+      safelyAppend(outputStreamWriter, System.lineSeparator());
+
+      List<Endpoint> newEndpoints = diff.getNewEndpoints();
+      listEndpoints(newEndpoints, "What's New", outputStreamWriter);
+
+      List<Endpoint> missingEndpoints = diff.getMissingEndpoints();
+      listEndpoints(missingEndpoints, "What's Deleted", outputStreamWriter);
+
+      List<Endpoint> deprecatedEndpoints = diff.getDeprecatedEndpoints();
+      listEndpoints(deprecatedEndpoints, "What's Deprecated", outputStreamWriter);
+
+      List<ChangedOperation> changedOperations = diff.getChangedOperations();
+      ol_changed(changedOperations, outputStreamWriter);
+
+      safelyAppend(outputStreamWriter, System.lineSeparator());
+      safelyAppend(
+          outputStreamWriter,
+          diff.isCompatible()
+              ? "NOTE: API changes are backward compatible"
+              : "WARNING: API changes broke backward compatibility");
+      safelyAppend(outputStreamWriter, System.lineSeparator());
+    }
+    try {
+      outputStreamWriter.close();
+    } catch (IOException e) {
+      throw new RendererException(e);
+    }
+  }
+
+  private void ol_changed(
+      List<ChangedOperation> operations, OutputStreamWriter outputStreamWriter) {
+    if (null == operations || operations.isEmpty()) {
+      return;
+    }
+    safelyAppend(outputStreamWriter, title("What's Changed", 2));
+    safelyAppend(outputStreamWriter, System.lineSeparator());
+    for (ChangedOperation operation : operations) {
+      String pathUrl = operation.getPathUrl();
+      String method = operation.getHttpMethod().toString();
+      String desc =
+          Optional.ofNullable(operation.getSummary()).map(ChangedMetadata::getRight).orElse("");
+
+      safelyAppend(outputStreamWriter, itemEndpoint(method, pathUrl, desc));
+      if (result(operation.getParameters()).isDifferent()) {
+        safelyAppend(outputStreamWriter, "* Parameter:\n");
+        safelyAppend(outputStreamWriter, ul_param(operation.getParameters()));
+        safelyAppend(outputStreamWriter, System.lineSeparator());
+      }
+      if (operation.resultRequestBody().isDifferent()) {
+        safelyAppend(outputStreamWriter, "* Request:\n");
+        safelyAppend(
+            outputStreamWriter, ul_content(operation.getRequestBody().getContent(), true, 2));
+        safelyAppend(outputStreamWriter, System.lineSeparator());
+      }
+      if (operation.resultApiResponses().isDifferent()) {
+        safelyAppend(outputStreamWriter, "* Return Type:\n");
+        safelyAppend(outputStreamWriter, ul_response(operation.getApiResponses()));
+        safelyAppend(outputStreamWriter, System.lineSeparator());
+      }
+    }
+  }
+
+  private String ul_response(ChangedApiResponse changedApiResponse) {
+    Map<String, ApiResponse> addResponses = changedApiResponse.getIncreased();
+    Map<String, ApiResponse> delResponses = changedApiResponse.getMissing();
+    Map<String, ChangedResponse> changedResponses = changedApiResponse.getChanged();
+    StringBuilder sb = new StringBuilder();
+    for (String propName : addResponses.keySet()) {
+      sb.append(itemResponse("** Add ", propName));
+    }
+    for (String propName : delResponses.keySet()) {
+      sb.append(itemResponse("** Deleted ", propName));
+    }
+    for (Entry<String, ChangedResponse> entry : changedResponses.entrySet()) {
+      sb.append(itemChangedResponse("** Changed ", entry.getKey(), entry.getValue()));
+    }
+    return sb.toString();
+  }
+
+  private String itemResponse(String title, String code) {
+    StringBuilder sb = new StringBuilder();
+    String status = "";
+    if (!code.equals("default") && !code.matches("[1-5]XX")) {
+      status = HttpStatus.getReasonPhrase(Integer.parseInt(code));
+    }
+    sb.append(title).append(code).append(' ').append(status).append("\n");
+    return sb.toString();
+  }
+
+  private String itemChangedResponse(String title, String contentType, ChangedResponse response) {
+    return itemResponse(title, contentType)
+        + "** Media types:\n"
+        + ul_content(response.getContent(), false, 3);
+  }
+
+  private String ul_content(ChangedContent changedContent, boolean isRequest, int indent) {
+    StringBuilder sb = new StringBuilder();
+    if (changedContent == null) {
+      return sb.toString();
+    }
+    for (String propName : changedContent.getIncreased().keySet()) {
+      sb.append(itemContent("Added ", propName, indent));
+    }
+    for (String propName : changedContent.getMissing().keySet()) {
+      sb.append(itemContent("Deleted ", propName, indent));
+    }
+    for (String propName : changedContent.getChanged().keySet()) {
+      sb.append(
+          itemContent(
+              "Changed ", propName, indent, changedContent.getChanged().get(propName), isRequest));
+    }
+    return sb.toString();
+  }
+
+  private String itemContent(String title, String contentType, int indent) {
+    return StringUtils.repeat('*', indent) + " " + title + contentType + "\n";
+  }
+
+  private String itemContent(
+      String title,
+      String contentType,
+      int indent,
+      ChangedMediaType changedMediaType,
+      boolean isRequest) {
+    StringBuilder sb = new StringBuilder();
+    sb.append(itemContent(title, contentType, indent))
+        .append(itemContent("Schema:", "", indent))
+        .append(changedMediaType.isCompatible() ? "Backward compatible" : "Broken compatibility")
+        .append("\n");
+    if (!changedMediaType.isCompatible()) {
+      sb.append(incompatibilities(changedMediaType.getSchema()));
+    }
+    return sb.toString();
+  }
+
+  private String incompatibilities(final ChangedSchema schema) {
+    return incompatibilities("", schema);
+  }
+
+  private String incompatibilities(String propName, final ChangedSchema schema) {
+    StringBuilder sb = new StringBuilder();
+    if (schema.getItems() != null) {
+      sb.append(items(propName, schema.getItems()));
+    }
+    if (schema.isCoreChanged() == DiffResult.INCOMPATIBLE && schema.isChangedType()) {
+      String type = type(schema.getOldSchema()) + " -> " + type(schema.getNewSchema());
+      sb.append(property(propName, "Changed property type", type));
+    }
+    String prefix = propName.isEmpty() ? "" : propName + ".";
+    sb.append(
+        properties(prefix, "Missing property", schema.getMissingProperties(), schema.getContext()));
+    schema
+        .getChangedProperties()
+        .forEach((name, property) -> sb.append(incompatibilities(prefix + name, property)));
+    return sb.toString();
+  }
+
+  private String items(String propName, ChangedSchema schema) {
+    return incompatibilities(propName + "[n]", schema);
+  }
+
+  private String properties(
+      String propPrefix, String title, Map<String, Schema<?>> properties, DiffContext context) {
+    StringBuilder sb = new StringBuilder();
+    if (properties != null) {
+      properties.forEach((key, value) -> sb.append(resolveProperty(propPrefix, value, key, title)));
+    }
+    return sb.toString();
+  }
+
+  private String resolveProperty(String propPrefix, Schema<?> value, String key, String title) {
+    try {
+      return property(propPrefix + key, title, resolve(value));
+    } catch (Exception e) {
+      return property(propPrefix + key, title, type(value));
+    }
+  }
+
+  protected String property(String name, String title, Schema<?> schema) {
+    return property(name, title, type(schema));
+  }
+
+  protected String property(String name, String title, String type) {
+    return String.format("*** %s: %s (%s)%n\n", title, name, type);
+  }
+
+  protected Schema<?> resolve(Schema<?> schema) {
+    return refPointer.resolveRef(
+        diff.getNewSpecOpenApi().getComponents(), schema, schema.get$ref());
+  }
+
+  protected String type(Schema<?> schema) {
+    String result = "object";
+    if (schema == null) {
+      result = "no schema";
+    } else if (schema instanceof ArraySchema) {
+      result = "array";
+    } else if (schema.getType() != null) {
+      result = schema.getType();
+    }
+    return result;
+  }
+
+  private String ul_param(ChangedParameters changedParameters) {
+    List<Parameter> addParameters = changedParameters.getIncreased();
+    List<Parameter> delParameters = changedParameters.getMissing();
+    List<ChangedParameter> changed = changedParameters.getChanged();
+    StringBuilder sb = new StringBuilder();
+    for (Parameter param : addParameters) {
+      sb.append(itemParam("** Add ", param));
+    }
+    for (ChangedParameter param : changed) {
+      sb.append(li_changedParam(param));
+    }
+    for (Parameter param : delParameters) {
+      sb.append(itemParam("** Delete ", param));
+    }
+    return sb.toString();
+  }
+
+  private String itemParam(String title, Parameter param) {
+    return title + param.getName() + " in " + param.getIn() + System.lineSeparator();
+  }
+
+  private String li_changedParam(ChangedParameter changeParam) {
+    if (changeParam.isDeprecated()) {
+      return itemParam("** Deprecated ", changeParam.getNewParameter());
+    } else {
+      return itemParam("** Changed ", changeParam.getNewParameter());
+    }
+  }
+
+  private String listEndpoints(
+      List<Endpoint> endpoints, String title, OutputStreamWriter outputStreamWriter) {
+    if (null == endpoints || endpoints.isEmpty()) {
+      return "";
+    }
+    StringBuilder sb = new StringBuilder();
+    sb.append(title(title));
+    for (Endpoint endpoint : endpoints) {
+      sb.append(
+          itemEndpoint(
+              endpoint.getMethod().toString(), endpoint.getPathUrl(), endpoint.getSummary()));
+    }
+    return sb.append(System.lineSeparator()).toString();
+  }
+
+  private String itemEndpoint(String method, String path, String desc) {
+    return String.format("=== %s%s%n", StringUtils.rightPad(method, 6), path);
+  }
+
+  public String bigTitle(String title, String version) {
+    char ch = '=';
+
+    return String.format("= %s (v %s)", title.toUpperCase(), version);
+  }
+
+  public String title(String title) {
+    return this.title(title, '-');
+  }
+
+  public String title(String title, int level) {
+    String little = StringUtils.repeat("=", level);
+    return String.format("%s %s", little, title);
+  }
+}
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/output/ConsoleRender.java b/core/src/main/java/org/openapitools/openapidiff/core/output/ConsoleRender.java
index a3e3a31ee..4f8e10fc9 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/output/ConsoleRender.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/output/ConsoleRender.java
@@ -47,6 +47,7 @@ public void render(ChangedOpenApi diff, OutputStreamWriter outputStreamWriter) {
       List<ChangedOperation> changedOperations = diff.getChangedOperations();
       ol_changed(changedOperations, outputStreamWriter);
 
+      safelyAppend(outputStreamWriter, title("Result"));
       safelyAppend(
           outputStreamWriter,
           StringUtils.center(
@@ -76,6 +77,8 @@ private void ol_changed(
       String desc =
           Optional.ofNullable(operation.getSummary()).map(ChangedMetadata::getRight).orElse("");
 
+      safelyAppend(outputStreamWriter, itemEndpoint(method, pathUrl, desc));
+
       if (result(operation.getParameters()).isDifferent()) {
         safelyAppend(outputStreamWriter, StringUtils.repeat(' ', 2));
         safelyAppend(outputStreamWriter, "Parameter:");
@@ -94,7 +97,6 @@ private void ol_changed(
         safelyAppend(outputStreamWriter, System.lineSeparator());
         safelyAppend(outputStreamWriter, ul_response(operation.getApiResponses()));
       }
-      safelyAppend(outputStreamWriter, itemEndpoint(method, pathUrl, desc));
     }
   }
 
@@ -279,10 +281,10 @@ private String li_changedParam(ChangedParameter changeParam) {
     }
   }
 
-  private String listEndpoints(
+  private void listEndpoints(
       List<Endpoint> endpoints, String title, OutputStreamWriter outputStreamWriter) {
     if (null == endpoints || endpoints.isEmpty()) {
-      return "";
+      return;
     }
     StringBuilder sb = new StringBuilder();
     sb.append(title(title));
@@ -291,7 +293,8 @@ private String listEndpoints(
           itemEndpoint(
               endpoint.getMethod().toString(), endpoint.getPathUrl(), endpoint.getSummary()));
     }
-    return sb.append(System.lineSeparator()).toString();
+
+    safelyAppend(outputStreamWriter, sb.append(System.lineSeparator()).toString());
   }
 
   private String itemEndpoint(String method, String path, String desc) {
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/output/HtmlRender.java b/core/src/main/java/org/openapitools/openapidiff/core/output/HtmlRender.java
index 4de76c646..eb4c5b884 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/output/HtmlRender.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/output/HtmlRender.java
@@ -26,6 +26,7 @@
 import io.swagger.v3.oas.models.media.Schema;
 import io.swagger.v3.oas.models.parameters.Parameter;
 import io.swagger.v3.oas.models.responses.ApiResponse;
+import io.swagger.v3.oas.models.security.SecurityRequirement;
 import j2html.rendering.FlatHtml;
 import j2html.tags.ContainerTag;
 import j2html.tags.specialized.DivTag;
@@ -50,6 +51,8 @@
 import org.openapitools.openapidiff.core.model.ChangedParameters;
 import org.openapitools.openapidiff.core.model.ChangedResponse;
 import org.openapitools.openapidiff.core.model.ChangedSchema;
+import org.openapitools.openapidiff.core.model.ChangedSecurityRequirement;
+import org.openapitools.openapidiff.core.model.ChangedSecurityRequirements;
 import org.openapitools.openapidiff.core.model.DiffContext;
 import org.openapitools.openapidiff.core.model.DiffResult;
 import org.openapitools.openapidiff.core.model.Endpoint;
@@ -64,15 +67,27 @@ public class HtmlRender implements Render {
 
   private final String title;
   private final String linkCss;
+  private final boolean showAllChanges;
   protected ChangedOpenApi diff;
 
   public HtmlRender() {
     this("Api Change Log", "http://deepoove.com/swagger-diff/stylesheets/demo.css");
   }
 
+  public HtmlRender(boolean showAllChanges) {
+    this("Api Change Log", "http://deepoove.com/swagger-diff/stylesheets/demo.css", showAllChanges);
+  }
+
   public HtmlRender(String title, String linkCss) {
     this.title = title;
     this.linkCss = linkCss;
+    this.showAllChanges = false;
+  }
+
+  public HtmlRender(String title, String linkCss, boolean showAllChanges) {
+    this.title = title;
+    this.linkCss = linkCss;
+    this.showAllChanges = showAllChanges;
   }
 
   public void render(ChangedOpenApi diff, OutputStreamWriter outputStreamWriter) {
@@ -200,6 +215,11 @@ private OlTag ol_changed(List<ChangedOperation> changedOperations) {
         ul_detail.with(
             li().with(h3("Response")).with(ul_response(changedOperation.getApiResponses())));
       }
+      if (showAllChanges && changedOperation.resultSecurityRequirements().isDifferent()) {
+        ul_detail.with(
+            li().with(h3("Security Requirements"))
+                .with(ul_securityRequirements(changedOperation.getSecurityRequirements())));
+      }
       ol.with(
           li().with(span(method).withClass(method))
               .withText(pathUrl + " ")
@@ -209,6 +229,52 @@ private OlTag ol_changed(List<ChangedOperation> changedOperations) {
     return ol;
   }
 
+  private UlTag ul_securityRequirements(ChangedSecurityRequirements changedSecurityRequirements) {
+    List<SecurityRequirement> addRequirements = changedSecurityRequirements.getIncreased();
+    List<SecurityRequirement> delRequirements = changedSecurityRequirements.getMissing();
+    List<ChangedSecurityRequirement> changedRequirements = changedSecurityRequirements.getChanged();
+    UlTag ul = ul().withClass("change security requirements");
+    if (addRequirements != null) {
+      for (SecurityRequirement addRequirement : addRequirements) {
+        ul.with(li_addSecurityRequirement(addRequirement));
+      }
+    }
+    if (delRequirements != null) {
+      for (SecurityRequirement delRequirement : delRequirements) {
+        ul.with(li_missingSecurityRequirement(delRequirement));
+      }
+    }
+    if (changedRequirements != null) {
+      for (ChangedSecurityRequirement changedRequirement : changedRequirements) {
+        ul.with(li_changedSecurityRequirement(changedRequirement));
+      }
+    }
+
+    return ul;
+  }
+
+  private LiTag li_addSecurityRequirement(SecurityRequirement securityRequirement) {
+    return li().withText("New security requirement : ")
+        .with(span(null == securityRequirement.toString() ? "" : (securityRequirement.toString())));
+  }
+
+  private LiTag li_missingSecurityRequirement(SecurityRequirement securityRequirement) {
+    return li().withText("Deleted security requirement : ")
+        .with(span(null == securityRequirement.toString() ? "" : (securityRequirement.toString())));
+  }
+
+  private LiTag li_changedSecurityRequirement(
+      ChangedSecurityRequirement changedSecurityRequirement) {
+    return li().withText(String.format("Changed security requirement : "))
+        .with(
+            span(
+                (null == changedSecurityRequirement.getNewSecurityRequirement()
+                        || null
+                            == changedSecurityRequirement.getNewSecurityRequirement().toString())
+                    ? ""
+                    : (changedSecurityRequirement.getNewSecurityRequirement().toString())));
+  }
+
   private UlTag ul_response(ChangedApiResponse changedApiResponse) {
     Map<String, ApiResponse> addResponses = changedApiResponse.getIncreased();
     Map<String, ApiResponse> delResponses = changedApiResponse.getMissing();
@@ -279,8 +345,10 @@ private LiTag li_changedRequest(String name, ChangedMediaType request) {
     LiTag li =
         li().with(div_changedSchema(request.getSchema()))
             .withText(String.format("Changed body: '%s'", name));
-    if (request.isIncompatible()) {
+    if (request.isIncompatible() && !showAllChanges) {
       incompatibilities(li, request.getSchema());
+    } else if (showAllChanges) {
+      allChanges(li, request.getSchema());
     }
     return li;
   }
@@ -291,6 +359,28 @@ private DivTag div_changedSchema(ChangedSchema schema) {
     return div;
   }
 
+  private void allChanges(final LiTag output, final ChangedSchema schema) {
+    allChanges(output, "", schema);
+  }
+
+  private void allChanges(
+      final ContainerTag<?> output, String propName, final ChangedSchema schema) {
+    String prefix = propName.isEmpty() ? "" : propName + ".";
+    properties(
+        output, prefix, "Missing property", schema.getMissingProperties(), schema.getContext());
+    properties(
+        output, prefix, "Added property", schema.getIncreasedProperties(), schema.getContext());
+
+    propertiesChanged(
+        output, prefix, "Changed property", schema.getChangedProperties(), schema.getContext());
+    if (schema.getItems() != null) {
+      itemsAllChanges(output, propName, schema.getItems());
+    }
+    schema
+        .getChangedProperties()
+        .forEach((name, property) -> allChanges(output, prefix + name, property));
+  }
+
   private void incompatibilities(final LiTag output, final ChangedSchema schema) {
     incompatibilities(output, "", schema);
   }
@@ -316,6 +406,10 @@ private void items(ContainerTag<?> output, String propName, ChangedSchema schema
     incompatibilities(output, propName + "[n]", schema);
   }
 
+  private void itemsAllChanges(ContainerTag<?> output, String propName, ChangedSchema schema) {
+    allChanges(output, propName + "[n]", schema);
+  }
+
   private void properties(
       ContainerTag<?> output,
       String propPrefix,
@@ -327,6 +421,17 @@ private void properties(
     }
   }
 
+  private void propertiesChanged(
+      ContainerTag<?> output,
+      String propPrefix,
+      String title,
+      Map<String, ChangedSchema> properties,
+      DiffContext context) {
+    if (properties != null) {
+      properties.forEach((key, value) -> resolveProperty(output, propPrefix, key, value, title));
+    }
+  }
+
   private void resolveProperty(
       ContainerTag<?> output, String propPrefix, String key, Schema<?> value, String title) {
     try {
@@ -336,6 +441,15 @@ private void resolveProperty(
     }
   }
 
+  private void resolveProperty(
+      ContainerTag<?> output, String propPrefix, String key, ChangedSchema value, String title) {
+    try {
+      property(output, propPrefix + key, title, resolve(value));
+    } catch (Exception e) {
+      property(output, propPrefix + key, title, type(value));
+    }
+  }
+
   protected void property(ContainerTag<?> output, String name, String title, Schema<?> schema) {
     property(output, name, title, type(schema));
   }
@@ -349,6 +463,13 @@ protected Schema<?> resolve(Schema<?> schema) {
         diff.getNewSpecOpenApi().getComponents(), schema, schema.get$ref());
   }
 
+  protected Schema<?> resolve(ChangedSchema schema) {
+    return refPointer.resolveRef(
+        diff.getNewSpecOpenApi().getComponents(),
+        schema.getNewSchema(),
+        schema.getNewSchema().get$ref());
+  }
+
   protected String type(Schema<?> schema) {
     String result = "object";
     if (schema == null) {
@@ -361,6 +482,10 @@ protected String type(Schema<?> schema) {
     return result;
   }
 
+  protected String type(ChangedSchema schema) {
+    return type(schema.getNewSchema());
+  }
+
   private UlTag ul_param(ChangedParameters changedParameters) {
     List<Parameter> addParameters = changedParameters.getIncreased();
     List<Parameter> delParameters = changedParameters.getMissing();
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/output/MarkdownRender.java b/core/src/main/java/org/openapitools/openapidiff/core/output/MarkdownRender.java
index 5e0d0dd76..e55179b15 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/output/MarkdownRender.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/output/MarkdownRender.java
@@ -20,6 +20,7 @@
 import org.apache.commons.lang3.StringUtils;
 import org.openapitools.openapidiff.core.exception.RendererException;
 import org.openapitools.openapidiff.core.model.*;
+import org.openapitools.openapidiff.core.model.schema.ChangedOneOfSchema;
 import org.openapitools.openapidiff.core.utils.RefPointer;
 import org.openapitools.openapidiff.core.utils.RefType;
 import org.slf4j.Logger;
diff --git a/core/src/main/java/org/openapitools/openapidiff/core/output/Render.java b/core/src/main/java/org/openapitools/openapidiff/core/output/Render.java
index 8169f31cd..529a290b9 100644
--- a/core/src/main/java/org/openapitools/openapidiff/core/output/Render.java
+++ b/core/src/main/java/org/openapitools/openapidiff/core/output/Render.java
@@ -1,5 +1,6 @@
 package org.openapitools.openapidiff.core.output;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 import org.openapitools.openapidiff.core.exception.RendererException;
@@ -7,7 +8,38 @@
 
 public interface Render {
 
-  void render(ChangedOpenApi diff, OutputStreamWriter outputStreamWriter);
+  /**
+   * render provided diff object
+   *
+   * @param diff diff object to render
+   * @param outputStreamWriter writer for rendered results
+   */
+  void render(ChangedOpenApi diff, OutputStreamWriter outputStreamWriter) throws RendererException;
+
+  /**
+   * render provided diff object
+   *
+   * @deprecated since 2.1.0, use {@link Render#render(ChangedOpenApi, OutputStreamWriter)} to avoid
+   *     massive String output issues. details <a
+   *     href="https://github.com/OpenAPITools/openapi-diff/issues/543">#543</a>
+   * @param diff diff object to render
+   * @return rendered output
+   */
+  @Deprecated
+  default String render(ChangedOpenApi diff) throws RendererException {
+    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(byteArrayOutputStream);
+    render(diff, outputStreamWriter);
+    String result = byteArrayOutputStream.toString();
+
+    try {
+      outputStreamWriter.close();
+    } catch (IOException e) {
+      throw new RendererException(e);
+    }
+
+    return result;
+  }
 
   default void safelyAppend(OutputStreamWriter outputStreamWriter, String csq) {
     try {
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/AddPropDiffTest.java b/core/src/test/java/org/openapitools/openapidiff/core/AddPropDiffTest.java
deleted file mode 100644
index 6d668c115..000000000
--- a/core/src/test/java/org/openapitools/openapidiff/core/AddPropDiffTest.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.openapitools.openapidiff.core;
-
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiAreEquals;
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardCompatible;
-
-import org.junit.jupiter.api.Test;
-
-public class AddPropDiffTest {
-  private final String OPENAPI_DOC1 = "add-prop-1.yaml";
-  private final String OPENAPI_DOC2 = "add-prop-2.yaml";
-
-  @Test
-  public void testDiffSame() {
-    assertOpenApiAreEquals(OPENAPI_DOC1, OPENAPI_DOC1);
-  }
-
-  @Test
-  public void testDiffDifferent() {
-    assertOpenApiBackwardCompatible(OPENAPI_DOC1, OPENAPI_DOC2, true);
-  }
-}
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/AddPropPutDiffTest.java b/core/src/test/java/org/openapitools/openapidiff/core/AddPropPutDiffTest.java
deleted file mode 100644
index 6ecc1bc22..000000000
--- a/core/src/test/java/org/openapitools/openapidiff/core/AddPropPutDiffTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.openapitools.openapidiff.core;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiAreEquals;
-
-import org.junit.jupiter.api.Test;
-import org.openapitools.openapidiff.core.model.ChangedOpenApi;
-
-public class AddPropPutDiffTest {
-  private final String OPENAPI_DOC1 = "add-prop-put-1.yaml";
-  private final String OPENAPI_DOC2 = "add-prop-put-2.yaml";
-
-  @Test
-  public void testDiffSame() {
-    assertOpenApiAreEquals(OPENAPI_DOC1, OPENAPI_DOC1);
-  }
-
-  @Test
-  public void testFieldAdditionalInPutApiIsCompatible() {
-    // See https://github.com/OpenAPITools/openapi-diff/pull/537
-    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
-    assertThat(changedOpenApi.isDifferent()).isTrue();
-    assertThat(changedOpenApi.isCompatible()).isTrue();
-  }
-}
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/AdditionalPropertiesTest.java b/core/src/test/java/org/openapitools/openapidiff/core/AdditionalPropertiesTest.java
deleted file mode 100644
index 7fabd712c..000000000
--- a/core/src/test/java/org/openapitools/openapidiff/core/AdditionalPropertiesTest.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.openapitools.openapidiff.core;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStreamWriter;
-import org.junit.jupiter.api.Test;
-import org.openapitools.openapidiff.core.model.ChangedOpenApi;
-import org.openapitools.openapidiff.core.output.ConsoleRender;
-
-class AdditionalPropertiesTest {
-  @Test
-  void booleanAdditionalPropertiesAreSupported() {
-    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
-    ChangedOpenApi diff = OpenApiCompare.fromLocations("issue-256_1.json", "issue-256_2.json");
-    ConsoleRender render = new ConsoleRender();
-    render.render(diff, outputStreamWriter);
-    assertThat(outputStream.toString()).isNotBlank();
-  }
-}
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/AllOfOneOfDiffTest.java b/core/src/test/java/org/openapitools/openapidiff/core/AllOfOneOfDiffTest.java
index ec1bcfc53..cd43c5961 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/AllOfOneOfDiffTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/AllOfOneOfDiffTest.java
@@ -9,6 +9,6 @@ public class AllOfOneOfDiffTest {
   @Test
   void allOfReferringToOneOfSchemasAreSupported() {
     ChangedOpenApi diff = OpenApiCompare.fromLocations("issue-317_1.json", "issue-317_2.json");
-    assertThat(diff.isCoreChanged().isUnchanged());
+    assertThat(diff.isCoreChanged().isUnchanged()).isTrue();
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/ChangesResolver.java b/core/src/test/java/org/openapitools/openapidiff/core/ChangesResolver.java
new file mode 100644
index 000000000..94dac20d2
--- /dev/null
+++ b/core/src/test/java/org/openapitools/openapidiff/core/ChangesResolver.java
@@ -0,0 +1,141 @@
+package org.openapitools.openapidiff.core;
+
+import io.swagger.v3.oas.models.PathItem.HttpMethod;
+import java.util.Optional;
+import javax.annotation.Nullable;
+import org.openapitools.openapidiff.core.model.ChangedApiResponse;
+import org.openapitools.openapidiff.core.model.ChangedContent;
+import org.openapitools.openapidiff.core.model.ChangedHeaders;
+import org.openapitools.openapidiff.core.model.ChangedMediaType;
+import org.openapitools.openapidiff.core.model.ChangedOpenApi;
+import org.openapitools.openapidiff.core.model.ChangedOperation;
+import org.openapitools.openapidiff.core.model.ChangedParameter;
+import org.openapitools.openapidiff.core.model.ChangedParameters;
+import org.openapitools.openapidiff.core.model.ChangedRequestBody;
+import org.openapitools.openapidiff.core.model.ChangedResponse;
+import org.openapitools.openapidiff.core.model.ChangedSchema;
+
+public class ChangesResolver {
+
+  /**
+   * Get the ChangedOperation for the given method and path.
+   *
+   * @param changedOpenApi the ChangedOpenApi object
+   * @param method the HTTP method
+   * @param path the path
+   * @return the ChangedOperation object
+   */
+  @Nullable
+  public static ChangedOperation getChangedOperation(
+      ChangedOpenApi changedOpenApi, HttpMethod method, String path) {
+    return changedOpenApi.getChangedOperations().stream()
+        .filter(
+            operation ->
+                operation.getHttpMethod().equals(method) && operation.getPathUrl().equals(path))
+        .findFirst()
+        .orElse(null);
+  }
+
+  /**
+   * Get the ChangedParameter for the given method, path, and parameter name.
+   *
+   * @param changedOpenApi the ChangedOpenApi object
+   * @param method the HTTP method
+   * @param path the path
+   * @param parameterName the parameter name
+   * @return the ChangedParameter object
+   */
+  @Nullable
+  public static ChangedParameter getChangedParameter(
+      ChangedOpenApi changedOpenApi, HttpMethod method, String path, String parameterName) {
+    ChangedOperation changedOperation = getChangedOperation(changedOpenApi, method, path);
+
+    if (changedOperation == null) {
+      return null;
+    }
+
+    return Optional.ofNullable(changedOperation.getParameters())
+        .map(ChangedParameters::getChanged)
+        .flatMap(
+            changedParameters ->
+                changedParameters.stream()
+                    .filter(changedParameter -> changedParameter.getName().equals(parameterName))
+                    .findFirst())
+        .orElse(null);
+  }
+
+  /**
+   * Get the ChangedHeaders for the given method, path, and response code.
+   *
+   * @param changedOpenApi the ChangedOpenApi object
+   * @param method the HTTP method
+   * @param path the path
+   * @param responseCode the response code
+   * @return the ChangedHeaders object
+   */
+  @Nullable
+  public static ChangedHeaders getChangedResponseHeaders(
+      ChangedOpenApi changedOpenApi, HttpMethod method, String path, String responseCode) {
+    return Optional.ofNullable(getChangedOperation(changedOpenApi, method, path))
+        .map(ChangedOperation::getApiResponses)
+        .map(ChangedApiResponse::getChanged)
+        .map(responses -> responses.get(responseCode))
+        .map(ChangedResponse::getHeaders)
+        .orElse(null);
+  }
+
+  /**
+   * Get the ChangedSchema for the given method, path, and media type.
+   *
+   * @param changedOpenApi the ChangedOpenApi object
+   * @param method the HTTP method
+   * @param path the path
+   * @param mediaType the media type
+   * @return the ChangedSchema object
+   */
+  @Nullable
+  public static ChangedSchema getRequestBodyChangedSchema(
+      ChangedOpenApi changedOpenApi, HttpMethod method, String path, String mediaType) {
+    ChangedOperation changedOperation = getChangedOperation(changedOpenApi, method, path);
+
+    if (changedOperation == null) {
+      return null;
+    }
+
+    return Optional.ofNullable(changedOperation)
+        .map(ChangedOperation::getRequestBody)
+        .map(ChangedRequestBody::getContent)
+        .map(ChangedContent::getChanged)
+        .map(changedMediaTypes -> changedMediaTypes.get(mediaType))
+        .map(ChangedMediaType::getSchema)
+        .orElse(null);
+  }
+
+  /**
+   * Get the response ChangedSchema for the given method, path, response code, and media type.
+   *
+   * @param changedOpenApi the ChangedOpenApi object
+   * @param method the HTTP method
+   * @param path the path
+   * @param responseCode the response code
+   * @param mediaType the media type
+   * @return the ChangedSchema object
+   */
+  @Nullable
+  public static ChangedSchema getResponseBodyChangedSchema(
+      ChangedOpenApi changedOpenApi,
+      HttpMethod method,
+      String path,
+      String responseCode,
+      String mediaType) {
+    return Optional.ofNullable(getChangedOperation(changedOpenApi, method, path))
+        .map(ChangedOperation::getApiResponses)
+        .map(ChangedApiResponse::getChanged)
+        .map(responses -> responses.get(responseCode))
+        .map(ChangedResponse::getContent)
+        .map(ChangedContent::getChanged)
+        .map(changedMediaTypes -> changedMediaTypes.get(mediaType))
+        .map(ChangedMediaType::getSchema)
+        .orElse(null);
+  }
+}
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/ConsoleRenderTest.java b/core/src/test/java/org/openapitools/openapidiff/core/ConsoleRenderTest.java
deleted file mode 100644
index f56b4cb95..000000000
--- a/core/src/test/java/org/openapitools/openapidiff/core/ConsoleRenderTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.openapitools.openapidiff.core;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStreamWriter;
-import org.junit.jupiter.api.Test;
-import org.openapitools.openapidiff.core.model.ChangedOpenApi;
-import org.openapitools.openapidiff.core.output.ConsoleRender;
-
-public class ConsoleRenderTest {
-  @Test
-  public void renderDoesNotFailWhenPropertyHasBeenRemoved() {
-    ConsoleRender render = new ConsoleRender();
-    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
-    ChangedOpenApi diff =
-        OpenApiCompare.fromLocations("missing_property_1.yaml", "missing_property_2.yaml");
-    render.render(diff, outputStreamWriter);
-    assertThat(outputStream.toString()).isNotBlank();
-  }
-
-  @Test
-  public void renderDoesNotFailWhenHTTPStatusCodeIsRange() {
-    ConsoleRender render = new ConsoleRender();
-    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
-    ChangedOpenApi diff =
-        OpenApiCompare.fromLocations("range_statuscode_1.yaml", "range_statuscode_2.yaml");
-    render.render(diff, outputStreamWriter);
-    assertThat(outputStream.toString()).isNotBlank();
-  }
-}
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/ExamplesDiffTest.java b/core/src/test/java/org/openapitools/openapidiff/core/ExamplesDiffTest.java
new file mode 100644
index 000000000..1743de4d1
--- /dev/null
+++ b/core/src/test/java/org/openapitools/openapidiff/core/ExamplesDiffTest.java
@@ -0,0 +1,167 @@
+package org.openapitools.openapidiff.core;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.openapitools.openapidiff.core.TestUtils.getOpenApiChangedOperations;
+
+import java.util.List;
+import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.ChangedOperation;
+
+public class ExamplesDiffTest {
+
+  @Test
+  public void issue666OAS30ExampleInMediaType() {
+    List<ChangedOperation> changedOperations =
+        getOpenApiChangedOperations(
+            "issue-666-oas-3-0-examples-handling-1.yaml",
+            "issue-666-oas-3-0-examples-handling-2.yaml");
+
+    ChangedOperation requestMediaTypeExampleChanged =
+        changedOperations.stream()
+            .filter(o -> "/example/request/media-type".equals(o.getPathUrl()))
+            .findFirst()
+            .orElse(null);
+    ChangedOperation responseMediaTypeExampleChanged =
+        changedOperations.stream()
+            .filter(o -> "/example/response/media-type".equals(o.getPathUrl()))
+            .findFirst()
+            .orElse(null);
+
+    assertThat(requestMediaTypeExampleChanged).isNotNull();
+    assertThat(responseMediaTypeExampleChanged).isNotNull();
+  }
+
+  @Test
+  public void issue666OAS31ExamplesInMediaType() {
+    List<ChangedOperation> changedOperations =
+        getOpenApiChangedOperations(
+            "issue-666-oas-3-1-examples-handling-1.yaml",
+            "issue-666-oas-3-1-examples-handling-2.yaml");
+
+    ChangedOperation requestMediaTypeExamplesChanged =
+        changedOperations.stream()
+            .filter(o -> "/examples/request/media-type".equals(o.getPathUrl()))
+            .findFirst()
+            .orElse(null);
+    ChangedOperation responseMediaTypeExamplesChanged =
+        changedOperations.stream()
+            .filter(o -> "/examples/response/media-type".equals(o.getPathUrl()))
+            .findFirst()
+            .orElse(null);
+
+    assertThat(requestMediaTypeExamplesChanged).isNotNull();
+    assertThat(responseMediaTypeExamplesChanged).isNotNull();
+  }
+
+  @Test
+  public void issue666OAS30ExampleInParameter() {
+    List<ChangedOperation> changedOperations =
+        getOpenApiChangedOperations(
+            "issue-666-oas-3-0-examples-handling-1.yaml",
+            "issue-666-oas-3-0-examples-handling-2.yaml");
+
+    ChangedOperation paramExampleChanged =
+        changedOperations.stream()
+            .filter(o -> "/example/parameter/{id}".equals(o.getPathUrl()))
+            .findFirst()
+            .orElse(null);
+
+    assertThat(paramExampleChanged).isNotNull();
+  }
+
+  @Test
+  public void issue666OAS31ExamplesInParameter() {
+    List<ChangedOperation> changedOperations =
+        getOpenApiChangedOperations(
+            "issue-666-oas-3-1-examples-handling-1.yaml",
+            "issue-666-oas-3-1-examples-handling-2.yaml");
+
+    ChangedOperation paramExamplesChanged =
+        changedOperations.stream()
+            .filter(o -> "/examples/parameter/{id}".equals(o.getPathUrl()))
+            .findFirst()
+            .orElse(null);
+
+    assertThat(paramExamplesChanged).isNotNull();
+  }
+
+  @Test
+  public void issue666OAS30ExampleInResponseHeader() {
+    List<ChangedOperation> changedOperations =
+        getOpenApiChangedOperations(
+            "issue-666-oas-3-0-examples-handling-1.yaml",
+            "issue-666-oas-3-0-examples-handling-2.yaml");
+
+    ChangedOperation operation =
+        changedOperations.stream()
+            .filter(o -> "/example/response/header".equals(o.getPathUrl()))
+            .findFirst()
+            .orElse(null);
+
+    assertThat(operation).isNotNull();
+  }
+
+  @Test
+  public void issue666OAS31ExamplesInResponseHeader() {
+    List<ChangedOperation> changedOperations =
+        getOpenApiChangedOperations(
+            "issue-666-oas-3-1-examples-handling-1.yaml",
+            "issue-666-oas-3-1-examples-handling-2.yaml");
+
+    ChangedOperation operation =
+        changedOperations.stream()
+            .filter(o -> "/examples/response/header".equals(o.getPathUrl()))
+            .findFirst()
+            .orElse(null);
+
+    assertThat(operation).isNotNull();
+  }
+
+  @Test
+  public void issue666OAS30ExampleInSchema() {
+    List<ChangedOperation> changedOperations =
+        getOpenApiChangedOperations(
+            "issue-666-oas-3-0-examples-handling-1.yaml",
+            "issue-666-oas-3-0-examples-handling-2.yaml");
+
+    ChangedOperation operation =
+        changedOperations.stream()
+            .filter(o -> "/example/model/property".equals(o.getPathUrl()))
+            .findFirst()
+            .orElse(null);
+
+    assertThat(operation).isNotNull();
+  }
+
+  @Test
+  public void issue666OAS31ExamplesInSchema() {
+    List<ChangedOperation> changedOperations =
+        getOpenApiChangedOperations(
+            "issue-666-oas-3-1-examples-handling-1.yaml",
+            "issue-666-oas-3-1-examples-handling-2.yaml");
+
+    ChangedOperation operation =
+        changedOperations.stream()
+            .filter(o -> "/examples/model/property".equals(o.getPathUrl()))
+            .findFirst()
+            .orElse(null);
+
+    assertThat(operation).isNotNull();
+  }
+
+  @Test
+  public void issue666OAS30ExampleInComposedSchema() {
+    List<ChangedOperation> changedOperations =
+        getOpenApiChangedOperations(
+            "issue-666-oas-3-0-examples-handling-1.yaml",
+            "issue-666-oas-3-0-examples-handling-2.yaml");
+
+    ChangedOperation operation =
+        changedOperations.stream()
+            .filter(o -> "/example/model/property/composed".equals(o.getPathUrl()))
+            .findFirst()
+            .orElse(null);
+
+    assertThat(operation).isNotNull();
+  }
+}
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/OperationDiffTest.java b/core/src/test/java/org/openapitools/openapidiff/core/OperationDiffTest.java
index 79f929f82..4a1794204 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/OperationDiffTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/OperationDiffTest.java
@@ -1,23 +1,69 @@
 package org.openapitools.openapidiff.core;
 
+import static io.swagger.v3.oas.models.PathItem.HttpMethod.*;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.openapitools.openapidiff.core.ChangesResolver.getChangedOperation;
 
 import org.junit.jupiter.api.Test;
 import org.openapitools.openapidiff.core.model.ChangedOpenApi;
+import org.openapitools.openapidiff.core.model.ChangedOperation;
 import org.openapitools.openapidiff.core.model.DiffResult;
 
 public class OperationDiffTest {
 
-  private final String OPENAPI_DOC1 = "operation_diff_1.yaml";
-  private final String OPENAPI_DOC2 = "operation_diff_2.yaml";
+  private final String OPENAPI_DOC1 = "operationDiff/operation_diff_1.yaml";
+  private final String OPENAPI_DOC2 = "operationDiff/operation_diff_2.yaml";
 
   @Test
-  public void testContentDiffWithOneEmptyMediaType() {
+  public void testOperationIdChanged() {
     ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
-    assertThat(changedOpenApi.isChanged()).isEqualTo(DiffResult.METADATA);
-    assertThat(changedOpenApi.isDifferent()).isTrue();
-    assertThat(changedOpenApi.getChangedOperations().size()).isEqualTo(1);
-    assertThat(changedOpenApi.getChangedOperations().get(0).getOperationId().isDifferent())
-        .isTrue();
+    ChangedOperation changedOperation =
+        getChangedOperation(changedOpenApi, GET, "/operation/operation-id");
+
+    assertThat(changedOperation).isNotNull();
+    assertThat(changedOperation.isChanged()).isEqualTo(DiffResult.METADATA);
+    assertThat(changedOperation.getOperationId().getRight()).isEqualTo("changed");
+  }
+
+  @Test
+  public void testOperationSummaryChanged() {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedOperation changedOperation =
+        getChangedOperation(changedOpenApi, GET, "/operation/summary");
+
+    assertThat(changedOperation).isNotNull();
+    assertThat(changedOperation.isChanged()).isEqualTo(DiffResult.METADATA);
+    assertThat(changedOperation.getSummary().getRight()).isEqualTo("changed");
+  }
+
+  @Test
+  public void testOperationDescriptionChanged() {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedOperation changedOperation =
+        getChangedOperation(changedOpenApi, GET, "/operation/description");
+
+    assertThat(changedOperation).isNotNull();
+    assertThat(changedOperation.isChanged()).isEqualTo(DiffResult.METADATA);
+    assertThat(changedOperation.getDescription().getRight()).isEqualTo("changed");
+  }
+
+  @Test
+  public void testOperationBecomesDeprecated() {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedOperation changedOperation =
+        getChangedOperation(changedOpenApi, GET, "/operation/becomes-deprecated");
+
+    assertThat(changedOperation).isNotNull();
+    assertThat(changedOperation.isDeprecated()).isTrue();
+  }
+
+  @Test
+  public void testOperationBecomesNotDeprecated() {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedOperation changedOperation =
+        getChangedOperation(changedOpenApi, GET, "/operation/becomes-not-deprecated");
+
+    assertThat(changedOperation).isNotNull();
+    assertThat(changedOperation.isDeprecated()).isTrue();
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/ParameterDiffTest.java b/core/src/test/java/org/openapitools/openapidiff/core/ParameterDiffTest.java
index 6e4cd9303..40f0cba74 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/ParameterDiffTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/ParameterDiffTest.java
@@ -1,91 +1,277 @@
 package org.openapitools.openapidiff.core;
 
+import static io.swagger.v3.oas.models.PathItem.HttpMethod.GET;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.openapitools.openapidiff.core.ChangesResolver.getChangedOperation;
+import static org.openapitools.openapidiff.core.ChangesResolver.getChangedParameter;
+import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiAreEquals;
 import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiChangedEndpoints;
 
+import io.swagger.v3.oas.models.parameters.Parameter;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.ChangedOpenApi;
+import org.openapitools.openapidiff.core.model.ChangedOperation;
+import org.openapitools.openapidiff.core.model.ChangedParameter;
+import org.openapitools.openapidiff.core.model.ChangedParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class ParameterDiffTest {
 
+  private final String OPENAPI_DOC1 = "parameterDiff/parameter_diff_1.yaml";
+  private final String OPENAPI_DOC2 = "parameterDiff/parameter_diff_2.yaml";
+  private final String OVERLOADED_PARAMETERS = "parameterDiff/parameters_overloading.yaml";
+  private final String DUPLICATED_PARAMETER_TYPES = "parameterDiff/parameters_overloading_2.yaml";
+
+  @Test
+  public void testAddParameter() {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedOperation changedOperation =
+        getChangedOperation(changedOpenApi, GET, "/parameter/added");
+
+    assertThat(changedOperation).isNotNull();
+    List<Parameter> increasedParams =
+        Optional.ofNullable(changedOperation.getParameters())
+            .map(ChangedParameters::getIncreased)
+            .orElse(Collections.emptyList());
+    assertThat(increasedParams.size()).isEqualTo(1);
+    assertThat(increasedParams.get(0).getName()).isEqualTo("param");
+  }
+
+  @Test
+  public void testRemoveParameter() {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedOperation changedOperation =
+        getChangedOperation(changedOpenApi, GET, "/parameter/removed");
+
+    assertThat(changedOperation).isNotNull();
+    List<Parameter> missingParams =
+        Optional.ofNullable(changedOperation.getParameters())
+            .map(ChangedParameters::getMissing)
+            .orElse(Collections.emptyList());
+    assertThat(missingParams.size()).isEqualTo(1);
+    assertThat(missingParams.get(0).getName()).isEqualTo("param");
+  }
+
+  @Test
+  public void testParameterBecomesDeprecated() {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedParameter changedParameter =
+        getChangedParameter(changedOpenApi, GET, "/parameter/becomes-deprecated", "X-Header");
+
+    assertThat(changedParameter).isNotNull();
+    assertThat(changedParameter.isDeprecated()).isTrue();
+  }
+
+  @Test
+  public void testParameterBecomesNotDeprecated() {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedParameter changedParameter =
+        getChangedParameter(changedOpenApi, GET, "/parameter/becomes-not-deprecated", "X-Header");
+
+    assertThat(changedParameter).isNotNull();
+    assertThat(changedParameter.isDeprecated()).isTrue();
+  }
+
+  @Test
+  public void testParameterRequiredChanged() {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedParameter changedParameter =
+        getChangedParameter(changedOpenApi, GET, "/parameter/required", "param");
+
+    assertThat(changedParameter).isNotNull();
+    assertThat(changedParameter.isChangeRequired()).isTrue();
+  }
+
+  @Test
+  public void testParameterDescriptionChanged() {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedParameter changedParameter =
+        getChangedParameter(changedOpenApi, GET, "/parameter/description", "param");
+
+    assertThat(changedParameter).isNotNull();
+    assertThat(changedParameter.getDescription().getRight()).isEqualTo("changed");
+  }
+
+  @Test
+  public void testParameterExplodeChanged() {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedParameter changedParameter =
+        getChangedParameter(changedOpenApi, GET, "/parameter/explode", "param");
+
+    assertThat(changedParameter).isNotNull();
+    assertThat(changedParameter.isChangeExplode()).isTrue();
+  }
+
+  @Test
+  public void testParameterStyleChanged() {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedParameter changedParameter =
+        getChangedParameter(changedOpenApi, GET, "/parameter/style", "param");
+
+    assertThat(changedParameter).isNotNull();
+    assertThat(changedParameter.isChangeStyle()).isTrue();
+  }
+
+  @Test
+  void testDiffWithOverloadedParameterTypes() {
+    assertDoesNotThrow(
+        () -> OpenApiCompare.fromLocations(OVERLOADED_PARAMETERS, OVERLOADED_PARAMETERS));
+    assertOpenApiAreEquals(OVERLOADED_PARAMETERS, OVERLOADED_PARAMETERS);
+  }
+
   @Test
-  public void testDiffDifferent() {
-    assertOpenApiChangedEndpoints("parameters_diff_1.yaml", "parameters_diff_2.yaml");
+  void testDiffWithDuplicatedParameterTypes() {
+    assertThrows(
+        IllegalArgumentException.class,
+        () -> OpenApiCompare.fromLocations(DUPLICATED_PARAMETER_TYPES, DUPLICATED_PARAMETER_TYPES),
+        "Two path items have the same signature: /projects/{}");
   }
 
   @Test
   public void issue458MaximumDecreased() {
     assertOpenApiChangedEndpoints(
-        "issue-458-integer-limits_1.yaml", "issue-458-integer-limits_2.yaml");
+        "parameterDiff/issue-458-integer-limits_1.yaml",
+        "parameterDiff/issue-458-integer-limits_2.yaml");
   }
 
   @Test
   public void issue458MaximumIncreased() {
     assertOpenApiChangedEndpoints(
-        "issue-458-integer-limits_1.yaml", "issue-458-integer-limits_3.yaml");
+        "parameterDiff/issue-458-integer-limits_1.yaml",
+        "parameterDiff/issue-458-integer-limits_3.yaml");
   }
 
   @Test
   public void issue458MinimumDecreased() {
     assertOpenApiChangedEndpoints(
-        "issue-458-integer-limits_1.yaml", "issue-458-integer-limits_4.yaml");
+        "parameterDiff/issue-458-integer-limits_1.yaml",
+        "parameterDiff/issue-458-integer-limits_4.yaml");
   }
 
   @Test
   public void issue458MinimumIncreased() {
     assertOpenApiChangedEndpoints(
-        "issue-458-integer-limits_1.yaml", "issue-458-integer-limits_5.yaml");
+        "parameterDiff/issue-458-integer-limits_1.yaml",
+        "parameterDiff/issue-458-integer-limits_5.yaml");
   }
 
   @Test
   public void issue458IntegerFormatChanged() {
     assertOpenApiChangedEndpoints(
-        "issue-458-integer-limits_1.yaml", "issue-458-integer-limits_6.yaml");
+        "parameterDiff/issue-458-integer-limits_1.yaml",
+        "parameterDiff/issue-458-integer-limits_6.yaml");
   }
 
   @Test
   public void issue458ExclusiveMinimumChanged() {
     assertOpenApiChangedEndpoints(
-        "issue-458-integer-limits_1.yaml", "issue-458-integer-limits_7.yaml");
+        "parameterDiff/issue-458-integer-limits_1.yaml",
+        "parameterDiff/issue-458-integer-limits_7.yaml");
   }
 
   @Test
   public void issue458ExclusiveMaximumChanged() {
     assertOpenApiChangedEndpoints(
-        "issue-458-integer-limits_1.yaml", "issue-458-integer-limits_8.yaml");
+        "parameterDiff/issue-458-integer-limits_1.yaml",
+        "parameterDiff/issue-458-integer-limits_8.yaml");
   }
 
   @Test
   public void issue458ExclusiveMinimumRemoved() {
     assertOpenApiChangedEndpoints(
-        "issue-458-integer-limits_1.yaml", "issue-458-integer-limits_9.yaml");
+        "parameterDiff/issue-458-integer-limits_1.yaml",
+        "parameterDiff/issue-458-integer-limits_9.yaml");
   }
 
   @Test
   public void issue458ExclusiveMaximumRemoved() {
     assertOpenApiChangedEndpoints(
-        "issue-458-integer-limits_1.yaml", "issue-458-integer-limits_10.yaml");
+        "parameterDiff/issue-458-integer-limits_1.yaml",
+        "parameterDiff/issue-458-integer-limits_10.yaml");
   }
 
   @Test
   public void issue458ExclusiveMaximumTrueToFalse() {
     assertOpenApiChangedEndpoints(
-        "issue-458-integer-limits_11.yaml", "issue-458-integer-limits_12.yaml");
+        "parameterDiff/issue-458-integer-limits_11.yaml",
+        "parameterDiff/issue-458-integer-limits_12.yaml");
   }
 
   @Test
   public void issue458ExclusiveMinimumTrueToFalse() {
     assertOpenApiChangedEndpoints(
-        "issue-458-integer-limits_11.yaml", "issue-458-integer-limits_13.yaml");
+        "parameterDiff/issue-458-integer-limits_11.yaml",
+        "parameterDiff/issue-458-integer-limits_13.yaml");
   }
 
   @Test
   public void issue458ExclusiveMaximumTrueRemoved() {
     assertOpenApiChangedEndpoints(
-        "issue-458-integer-limits_11.yaml", "issue-458-integer-limits_12.yaml");
+        "parameterDiff/issue-458-integer-limits_11.yaml",
+        "parameterDiff/issue-458-integer-limits_12.yaml");
   }
 
   @Test
   public void issue458ExclusiveMinimumTrueRemoved() {
     assertOpenApiChangedEndpoints(
-        "issue-458-integer-limits_11.yaml", "issue-458-integer-limits_13.yaml");
+        "parameterDiff/issue-458-integer-limits_11.yaml",
+        "parameterDiff/issue-458-integer-limits_13.yaml");
+  }
+
+  @Test
+  public void issue488RenameParameterAddAndRemoveParameterReturnFalse() {
+    assertOpenApiChangedEndpoints(
+        "parameterDiff/issue-488-1.json", "parameterDiff/issue-488-2.json");
+  }
+
+  final String TEST_MSG_1 =
+      "Testing: \n"
+          + "1. Same path but different pathParameters\n"
+          + "2. different parameters in the parameters: section\n"
+          + "3. Parameters have different schema\n"
+          + "eg:\n"
+          + "old path   -- students/{id}\n"
+          + "old schema -- id: integer\n"
+          + "new path   -- students/{username}\n"
+          + "new schema -- username: string";
+
+  @Test
+  @DisplayName(
+      "Same Path, different PathParams, Params in the `Parameters`: match pathParam, Different Schema")
+  public void pathSamePathParamsDiffParamSameAsInPathButSchemaDiff() {
+    final Logger logger = LoggerFactory.getLogger(ParameterDiffTest.class);
+    logger.info(TEST_MSG_1);
+    String OPENAPI_DOC1 = "parameterDiff/path_parameter_diff_param_schema_diff_old.yaml";
+    String OPENAPI_DOC2 = "parameterDiff/path_parameter_diff_param_schema_diff_new.yaml";
+    ChangedOpenApi diff = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    Assertions.assertTrue(diff.isDifferent());
+    Assertions.assertFalse(diff.isCompatible());
+  }
+
+  final String TEST_MSG_2 =
+      "Testing: \n"
+          + "1. Same path but different pathParameters\n"
+          + "2. different parameters in the parameters: section\n"
+          + "3. Parameters have same schema\n";
+
+  @Test
+  @DisplayName(
+      "Same Path, different PathParams, Params in the `Parameters`: match pathParam, same Schema")
+  public void pathSamePathParamsDiffParamNameDiffSchemaSame() {
+    final Logger logger = LoggerFactory.getLogger(ParameterDiffTest.class);
+    logger.info(TEST_MSG_2);
+    String OPENAPI_DOC1 = "parameterDiff/path_parameter_diff_param_name_diff_old.yaml";
+    String OPENAPI_DOC2 = "parameterDiff/path_parameter_diff_param_name_diff_new.yaml";
+    ChangedOpenApi diff = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    Assertions.assertFalse(diff.isDifferent());
+    Assertions.assertTrue(diff.isCompatible());
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/ParametersOverloadingTest.java b/core/src/test/java/org/openapitools/openapidiff/core/ParametersOverloadingTest.java
deleted file mode 100644
index bc779be56..000000000
--- a/core/src/test/java/org/openapitools/openapidiff/core/ParametersOverloadingTest.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.openapitools.openapidiff.core;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiAreEquals;
-
-import org.junit.jupiter.api.Test;
-
-class ParametersOverloadingTest {
-
-  private final String OVERLOADED_PARAMETERS = "parameters_overloading.yaml";
-  private final String DUPLICATED_PARAMETER_TYPES = "parameters_overloading_2.yaml";
-
-  @Test
-  void testDiffWithOverloadedParameterTypes() {
-    assertDoesNotThrow(
-        () -> OpenApiCompare.fromLocations(OVERLOADED_PARAMETERS, OVERLOADED_PARAMETERS));
-    assertOpenApiAreEquals(OVERLOADED_PARAMETERS, OVERLOADED_PARAMETERS);
-  }
-
-  @Test
-  void testDiffWithDuplicatedParameterTypes() {
-    assertThrows(
-        IllegalArgumentException.class,
-        () -> OpenApiCompare.fromLocations(DUPLICATED_PARAMETER_TYPES, DUPLICATED_PARAMETER_TYPES),
-        "Two path items have the same signature: /projects/{}");
-  }
-}
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/PathParameterSchemaDiffTest.java b/core/src/test/java/org/openapitools/openapidiff/core/PathParameterSchemaDiffTest.java
deleted file mode 100644
index 1c4065ed9..000000000
--- a/core/src/test/java/org/openapitools/openapidiff/core/PathParameterSchemaDiffTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.openapitools.openapidiff.core;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.openapitools.openapidiff.core.model.ChangedOpenApi;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class PathParameterSchemaDiffTest {
-  final String TEST_MSG_1 =
-      "Testing: \n"
-          + "1. Same path but different pathParameters\n"
-          + "2. different parameters in the parameters: section\n"
-          + "3. Parameters have different schema\n"
-          + "eg:\n"
-          + "old path   -- students/{id}\n"
-          + "old schema -- id: integer\n"
-          + "new path   -- students/{username}\n"
-          + "new schema -- username: string";
-
-  final String TEST_MSG_2 =
-      "Testing: \n"
-          + "1. Same path but different pathParameters\n"
-          + "2. different parameters in the parameters: section\n"
-          + "3. Parameters have same schema\n";
-
-  @Test
-  @DisplayName(
-      "Same Path, different PathParams, Params in the `Parameters`: match pathParam, Different Schema")
-  public void pathSamePathParamsDiffParamSameAsInPathButSchemaDiff() {
-    final Logger logger = LoggerFactory.getLogger(PathParameterSchemaDiffTest.class);
-    logger.info(TEST_MSG_1);
-    String OPENAPI_DOC1 = "path_parameter_diff_param_schema_diff_old.yaml";
-    String OPENAPI_DOC2 = "path_parameter_diff_param_schema_diff_new.yaml";
-    ChangedOpenApi diff = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
-    Assertions.assertTrue(diff.isDifferent());
-    Assertions.assertFalse(diff.isCompatible());
-  }
-
-  @Test
-  @DisplayName(
-      "Same Path, different PathParams, Params in the `Parameters`: match pathParam, same Schema")
-  public void pathSamePathParamsDiffParamNameDiffSchemaSame() {
-    final Logger logger = LoggerFactory.getLogger(PathParameterSchemaDiffTest.class);
-    logger.info(TEST_MSG_2);
-    String OPENAPI_DOC1 = "path_parameter_diff_param_name_diff_old.yaml";
-    String OPENAPI_DOC2 = "path_parameter_diff_param_name_diff_new.yaml";
-    ChangedOpenApi diff = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
-    Assertions.assertFalse(diff.isDifferent());
-    Assertions.assertTrue(diff.isCompatible());
-  }
-}
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/ResponseHeaderDiffTest.java b/core/src/test/java/org/openapitools/openapidiff/core/ResponseHeaderDiffTest.java
index 05e4ecfe3..c388e9692 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/ResponseHeaderDiffTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/ResponseHeaderDiffTest.java
@@ -1,34 +1,86 @@
 package org.openapitools.openapidiff.core;
 
+import static io.swagger.v3.oas.models.PathItem.HttpMethod.GET;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.openapitools.openapidiff.core.ChangesResolver.getChangedResponseHeaders;
 
 import java.util.Map;
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.ChangedHeader;
 import org.openapitools.openapidiff.core.model.ChangedHeaders;
 import org.openapitools.openapidiff.core.model.ChangedOpenApi;
-import org.openapitools.openapidiff.core.model.ChangedResponse;
 
 public class ResponseHeaderDiffTest {
 
-  private final String OPENAPI_DOC1 = "header_1.yaml";
-  private final String OPENAPI_DOC2 = "header_2.yaml";
+  private final String OPENAPI_DOC1 = "responseHeaderDiff/response_header_1.yaml";
+  private final String OPENAPI_DOC2 = "responseHeaderDiff/response_header_2.yaml";
 
   @Test
-  public void testDiffDifferent() {
+  public void testResponseHeadersDescriptionChanges() {
     ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedHeaders changedResponseHeaders =
+        getChangedResponseHeaders(changedOpenApi, GET, "/response/headers/description", "200");
 
-    assertThat(changedOpenApi.getNewEndpoints()).isEmpty();
-    assertThat(changedOpenApi.getMissingEndpoints()).isEmpty();
-    assertThat(changedOpenApi.getChangedOperations()).isNotEmpty();
-
-    Map<String, ChangedResponse> changedResponses =
-        changedOpenApi.getChangedOperations().get(0).getApiResponses().getChanged();
-    assertThat(changedResponses).isNotEmpty();
-    assertThat(changedResponses).containsKey("200");
-    ChangedHeaders changedHeaders = changedResponses.get("200").getHeaders();
-    assertThat(changedHeaders.isDifferent()).isTrue();
-    assertThat(changedHeaders.getChanged()).hasSize(1);
-    assertThat(changedHeaders.getIncreased()).hasSize(1);
-    assertThat(changedHeaders.getMissing()).hasSize(1);
+    assertThat(changedResponseHeaders).isNotNull();
+    Map<String, ChangedHeader> changedHeaders = changedResponseHeaders.getChanged();
+
+    assertThat(changedHeaders).containsKey("x-header-description-changed");
+    assertThat(changedHeaders.get("x-header-description-changed").getDescription()).isNotNull();
+    assertThat(changedHeaders.get("x-header-description-changed").getDescription().getLeft())
+        .isEqualTo("old description");
+    assertThat(changedHeaders.get("x-header-description-changed").getDescription().getRight())
+        .isEqualTo("new description");
+
+    assertThat(changedHeaders).containsKey("x-header-description-added");
+    assertThat(changedHeaders.get("x-header-description-added").getDescription()).isNotNull();
+    assertThat(changedHeaders.get("x-header-description-added").getDescription().getLeft())
+        .isNull();
+    assertThat(changedHeaders.get("x-header-description-added").getDescription().getRight())
+        .isEqualTo("added description");
+
+    assertThat(changedHeaders).containsKey("x-header-description-removed");
+    assertThat(changedHeaders.get("x-header-description-removed").getDescription()).isNotNull();
+    assertThat(changedHeaders.get("x-header-description-removed").getDescription().getLeft())
+        .isEqualTo("old description");
+    assertThat(changedHeaders.get("x-header-description-removed").getDescription().getRight())
+        .isNull();
+  }
+
+  @Test
+  public void testResponseHeadersRequiredChanges() {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedHeaders changedResponseHeaders =
+        getChangedResponseHeaders(changedOpenApi, GET, "/response/headers/required", "200");
+
+    assertThat(changedResponseHeaders).isNotNull();
+    Map<String, ChangedHeader> changedHeaders = changedResponseHeaders.getChanged();
+
+    assertThat(changedHeaders).containsKey("x-header-required-changed");
+  }
+
+  @Test
+  public void testResponseHeadersExplodeChanges() {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedHeaders changedResponseHeaders =
+        getChangedResponseHeaders(changedOpenApi, GET, "/response/headers/explode", "200");
+
+    assertThat(changedResponseHeaders).isNotNull();
+    Map<String, ChangedHeader> changedHeaders = changedResponseHeaders.getChanged();
+
+    assertThat(changedHeaders).containsKey("x-header-explode-changed");
+  }
+
+  @Test // issue #485
+  public void testResponseHeadersDeprecatedChanges() {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(OPENAPI_DOC1, OPENAPI_DOC2);
+    ChangedHeaders changedResponseHeaders =
+        getChangedResponseHeaders(changedOpenApi, GET, "/response/headers/deprecated", "200");
+
+    assertThat(changedResponseHeaders).isNotNull();
+    Map<String, ChangedHeader> changedHeaders = changedResponseHeaders.getChanged();
+    assertThat(changedHeaders).containsKey("x-header-becomes-deprecated");
+    assertThat(changedHeaders.get("x-header-becomes-deprecated").isDeprecated()).isTrue();
+    assertThat(changedHeaders).containsKey("x-header-becomes-not-deprecated");
+    assertThat(changedHeaders.get("x-header-becomes-not-deprecated").isDeprecated()).isTrue();
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/SchemaDiffTest.java b/core/src/test/java/org/openapitools/openapidiff/core/SchemaDiffTest.java
new file mode 100644
index 000000000..1f41406a1
--- /dev/null
+++ b/core/src/test/java/org/openapitools/openapidiff/core/SchemaDiffTest.java
@@ -0,0 +1,441 @@
+package org.openapitools.openapidiff.core;
+
+import static io.swagger.v3.oas.models.PathItem.HttpMethod.POST;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.openapitools.openapidiff.core.ChangesResolver.getRequestBodyChangedSchema;
+import static org.openapitools.openapidiff.core.ChangesResolver.getResponseBodyChangedSchema;
+import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardCompatible;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStreamWriter;
+import java.math.BigDecimal;
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.ChangedOpenApi;
+import org.openapitools.openapidiff.core.model.ChangedSchema;
+import org.openapitools.openapidiff.core.model.DiffResult;
+import org.openapitools.openapidiff.core.model.schema.ChangedRequired;
+import org.openapitools.openapidiff.core.output.ConsoleRender;
+
+public class SchemaDiffTest {
+
+  @Test // issue #717
+  public void schemaPropertyDefaultChanged() {
+    ChangedOpenApi changedOpenApi =
+        OpenApiCompare.fromLocations(
+            "schemaDiff/schema-props-defaults-handling-1.yaml",
+            "schemaDiff/schema-props-defaults-handling-2.yaml");
+
+    assertEquals(1, changedOpenApi.getChangedOperations().size());
+    assertEquals(1, changedOpenApi.getChangedSchemas().size());
+    ChangedSchema changedSchema = changedOpenApi.getChangedSchemas().get(0);
+    assertEquals(1, changedSchema.getChangedProperties().size());
+    assertTrue(changedSchema.getChangedProperties().containsKey("field1"));
+    assertTrue(changedSchema.getChangedProperties().get("field1").isChangeDefault());
+  }
+
+  @Test
+  public void schemaPropertyTypeChanged() {
+    ChangedOpenApi changedOpenApi =
+        OpenApiCompare.fromLocations(
+            "schemaDiff/schema-props-type-handling-1.yaml",
+            "schemaDiff/schema-props-type-handling-2.yaml");
+
+    assertEquals(1, changedOpenApi.getChangedOperations().size());
+    assertEquals(1, changedOpenApi.getChangedSchemas().size());
+    ChangedSchema changedSchema = changedOpenApi.getChangedSchemas().get(0);
+    assertEquals(1, changedSchema.getChangedProperties().size());
+    assertTrue(changedSchema.getChangedProperties().containsKey("field1"));
+    assertTrue(changedSchema.getChangedProperties().get("field1").isChangedType());
+  }
+
+  @Test // issue #485
+  public void schemaBecomesDeprecatedTest() {
+    ChangedOpenApi changedOpenApi =
+        OpenApiCompare.fromLocations(
+            "schemaDiff/schema-deprecated-handling-1.yaml",
+            "schemaDiff/schema-deprecated-handling-2.yaml");
+
+    ChangedSchema requestBodySchema =
+        getRequestBodyChangedSchema(
+            changedOpenApi, POST, "/schema-diff/deprecated/added", "application/json");
+    assertNotNull(requestBodySchema);
+    assertTrue(requestBodySchema.isChangeDeprecated());
+  }
+
+  @Test // issue #485
+  public void schemaBecomesNotDeprecatedTest() {
+    ChangedOpenApi changedOpenApi =
+        OpenApiCompare.fromLocations(
+            "schemaDiff/schema-deprecated-handling-1.yaml",
+            "schemaDiff/schema-deprecated-handling-2.yaml");
+
+    ChangedSchema requestBodySchema =
+        getRequestBodyChangedSchema(
+            changedOpenApi, POST, "/schema-diff/deprecated/removed", "application/json");
+    assertNotNull(requestBodySchema);
+    assertTrue(requestBodySchema.isChangeDeprecated());
+  }
+
+  @Test // issue #256
+  void booleanAdditionalPropertiesAreSupported() {
+    ChangedOpenApi diff =
+        OpenApiCompare.fromLocations(
+            "schemaDiff/schema-additional-properties-1.json",
+            "schemaDiff/schema-additional-properties-2.json");
+
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+    ConsoleRender render = new ConsoleRender();
+    render.render(diff, outputStreamWriter);
+    assertThat(outputStream.toString()).isNotBlank();
+  }
+
+  @Test
+  public void addPropertyHandlingTest() {
+    assertOpenApiBackwardCompatible(
+        "schemaDiff/schema-add-property-1.yaml", "schemaDiff/schema-add-property-2.yaml", true);
+  }
+
+  @Test // issue #537
+  public void addPropertyInPutApiIsCompatible() {
+    ChangedOpenApi changedOpenApi =
+        OpenApiCompare.fromLocations(
+            "schemaDiff/schema-add-property-put-1.yaml",
+            "schemaDiff/schema-add-property-put-2.yaml");
+
+    assertThat(changedOpenApi.isDifferent()).isTrue();
+    assertThat(changedOpenApi.isCompatible()).isTrue();
+  }
+
+  @Test // issues #483 #463
+  public void changeMultipleOfHandling() {
+    ChangedOpenApi changedOpenApi =
+        OpenApiCompare.fromLocations(
+            "schemaDiff/schema-multiple-of-diff-1.yaml",
+            "schemaDiff/schema-multiple-of-diff-2.yaml");
+    ChangedSchema changedSchema =
+        getRequestBodyChangedSchema(
+            changedOpenApi, POST, "/schema/numeric/multiple-of", "application/json");
+
+    assertThat(changedSchema).isNotNull();
+    Map<String, ChangedSchema> props = changedSchema.getChangedProperties();
+    assertThat(props).isNotEmpty();
+
+    // Check changes in multipleOf
+    assertThat(props.get("field1").getMultipleOf().isIncompatible()).isTrue();
+    assertThat(props.get("field1").getMultipleOf().getLeft()).isEqualTo(BigDecimal.valueOf(10));
+    assertThat(props.get("field1").getMultipleOf().getRight()).isEqualTo(BigDecimal.valueOf(20));
+
+    assertThat(props.get("field2").getMultipleOf().isIncompatible()).isTrue();
+    assertThat(props.get("field2").getMultipleOf().getLeft()).isEqualTo(BigDecimal.valueOf(0.01));
+    assertThat(props.get("field2").getMultipleOf().getRight()).isEqualTo(BigDecimal.valueOf(0.1));
+
+    // Check addition of multipleOf
+    assertThat(props.get("field3").getMultipleOf().isIncompatible()).isTrue();
+    assertThat(props.get("field3").getMultipleOf().getLeft()).isNull();
+    assertThat(props.get("field3").getMultipleOf().getRight()).isEqualTo(BigDecimal.valueOf(10));
+
+    // Check deletion of multipleOf
+    assertThat(props.get("field4").getMultipleOf().getLeft()).isEqualTo(BigDecimal.valueOf(10));
+    assertThat(props.get("field4").getMultipleOf().getRight()).isNull();
+  }
+
+  @Test // issues #480 and #779
+  public void changeMinMaxItemsHandling() {
+    ChangedOpenApi changedOpenApi =
+        OpenApiCompare.fromLocations(
+            "schemaDiff/schema-min-max-items-diff-1.yaml",
+            "schemaDiff/schema-min-max-items-diff-2.yaml");
+    ChangedSchema changedSchema =
+        getRequestBodyChangedSchema(
+            changedOpenApi, POST, "/schema/array/items", "application/json");
+
+    assertThat(changedSchema).isNotNull();
+    Map<String, ChangedSchema> props = changedSchema.getChangedProperties();
+    assertThat(props).isNotEmpty();
+
+    // Check no changes in minItems and maxItems
+    assertThat(props.get("field0")).isNull();
+
+    // Check increasing of minItems
+    assertThat(props.get("field1").getMinItems().isIncompatible()).isTrue();
+    assertThat(props.get("field1").getMinItems().getOldValue()).isEqualTo(1);
+    assertThat(props.get("field1").getMinItems().getNewValue()).isEqualTo(2);
+
+    // Check decreasing of minItems
+    assertThat(props.get("field2").getMinItems().isCompatible()).isTrue();
+    assertThat(props.get("field2").getMinItems().getOldValue()).isEqualTo(20);
+    assertThat(props.get("field2").getMinItems().getNewValue()).isEqualTo(10);
+
+    // Check increasing of maxItems
+    assertThat(props.get("field3").getMaxItems().isCompatible()).isTrue();
+    assertThat(props.get("field3").getMaxItems().getOldValue()).isEqualTo(90);
+    assertThat(props.get("field3").getMaxItems().getNewValue()).isEqualTo(100);
+
+    // Check decreasing of maxItems
+    assertThat(props.get("field4").getMaxItems().isIncompatible()).isTrue();
+    assertThat(props.get("field4").getMaxItems().getOldValue()).isEqualTo(100);
+    assertThat(props.get("field4").getMaxItems().getNewValue()).isEqualTo(90);
+
+    // Check removal of minItems
+    assertThat(props.get("field5").getMinItems().isCompatible()).isTrue();
+    assertThat(props.get("field5").getMinItems().getOldValue()).isEqualTo(1);
+    assertThat(props.get("field5").getMinItems().getNewValue()).isNull();
+
+    // Check removal of maxItems
+    assertThat(props.get("field5").getMaxItems().isCompatible()).isTrue();
+    assertThat(props.get("field5").getMaxItems().getOldValue()).isEqualTo(100);
+    assertThat(props.get("field5").getMaxItems().getNewValue()).isNull();
+
+    // Check addition of minItems
+    assertThat(props.get("field6").getMinItems().isCompatible()).isTrue();
+    assertThat(props.get("field6").getMinItems().getOldValue()).isNull();
+    assertThat(props.get("field6").getMinItems().getNewValue()).isEqualTo(1);
+
+    // Check addition of maxItems
+    assertThat(props.get("field6").getMaxItems().isCompatible()).isTrue();
+    assertThat(props.get("field6").getMaxItems().getOldValue()).isNull();
+    assertThat(props.get("field6").getMaxItems().getNewValue()).isEqualTo(100);
+  }
+
+  @Test // issue #482
+  public void changeNullableHandling() {
+    ChangedOpenApi changedOpenApi =
+        OpenApiCompare.fromLocations(
+            "schemaDiff/schema-nullable-diff-1.yaml", "schemaDiff/schema-nullable-diff-2.yaml");
+    ChangedSchema changedSchema =
+        getRequestBodyChangedSchema(changedOpenApi, POST, "/schema/nullable", "application/json");
+
+    assertThat(changedSchema).isNotNull();
+    Map<String, ChangedSchema> props = changedSchema.getChangedProperties();
+    assertThat(props).isNotEmpty();
+
+    // Check no changes in nullable
+    assertThat(props.get("field0")).isNull();
+
+    // Check changes in nullable
+    assertThat(props.get("field1").getNullable().isCompatible()).isTrue();
+    assertThat(props.get("field1").getNullable().getLeft()).isTrue();
+    assertThat(props.get("field1").getNullable().getRight()).isFalse();
+
+    // Check deletion of nullable
+    assertThat(props.get("field2").getNullable().isCompatible()).isTrue();
+    assertThat(props.get("field2").getNullable().getLeft()).isTrue();
+    assertThat(props.get("field2").getNullable().getRight()).isNull();
+
+    // Check addition of nullable
+    assertThat(props.get("field3").getNullable().isCompatible()).isTrue();
+    assertThat(props.get("field3").getNullable().getLeft()).isNull();
+    assertThat(props.get("field3").getNullable().getRight()).isTrue();
+  }
+
+  @Test // issue #478
+  public void changeUniqueItemsHandling() {
+    ChangedOpenApi changedOpenApi =
+        OpenApiCompare.fromLocations(
+            "schemaDiff/schema-uniqueItems-diff-1.yaml",
+            "schemaDiff/schema-uniqueItems-diff-2.yaml");
+    ChangedSchema changedSchema =
+        getRequestBodyChangedSchema(
+            changedOpenApi, POST, "/schema/uniqueItems", "application/json");
+
+    assertThat(changedSchema).isNotNull();
+    Map<String, ChangedSchema> props = changedSchema.getChangedProperties();
+    assertThat(props).isNotEmpty();
+
+    // Check no changes in uniqueItems
+    assertThat(props.get("field0")).isNull();
+
+    // Check changes true -> false
+    assertThat(props.get("field1").getUniqueItems().isCompatible()).isTrue();
+    assertThat(props.get("field1").getUniqueItems().getLeft()).isTrue();
+    assertThat(props.get("field1").getUniqueItems().getRight()).isFalse();
+
+    // Check changes false -> true
+    assertThat(props.get("field2").getUniqueItems().isIncompatible()).isTrue();
+    assertThat(props.get("field2").getUniqueItems().getLeft()).isFalse();
+    assertThat(props.get("field2").getUniqueItems().getRight()).isTrue();
+
+    // Check deletion of uniqueItems
+    assertThat(props.get("field3").getUniqueItems().isCompatible()).isTrue();
+    assertThat(props.get("field3").getUniqueItems().getLeft()).isTrue();
+    assertThat(props.get("field3").getUniqueItems().getRight()).isNull();
+
+    // Check addition of uniqueItems
+    assertThat(props.get("field4").getUniqueItems().isIncompatible()).isTrue();
+    assertThat(props.get("field4").getUniqueItems().getLeft()).isNull();
+    assertThat(props.get("field4").getUniqueItems().getRight()).isTrue();
+  }
+
+  @Test // issue #479
+  public void changeMinMaxPropertiesHandling() {
+    ChangedOpenApi changedOpenApi =
+        OpenApiCompare.fromLocations(
+            "schemaDiff/schema-min-max-properties-diff-1.yaml",
+            "schemaDiff/schema-min-max-properties-diff-2.yaml");
+    ChangedSchema changedSchema =
+        getRequestBodyChangedSchema(
+            changedOpenApi, POST, "/schema/object/min-max-properties", "application/json");
+
+    assertThat(changedSchema).isNotNull();
+    Map<String, ChangedSchema> props = changedSchema.getChangedProperties();
+    assertThat(props).isNotEmpty();
+
+    // Check increasing of minProperties
+    assertThat(props.get("field1").getMinProperties().isIncompatible()).isTrue();
+    assertThat(props.get("field1").getMinProperties().getOldValue()).isEqualTo(1);
+    assertThat(props.get("field1").getMinProperties().getNewValue()).isEqualTo(10);
+
+    // Check decreasing of minProperties
+    assertThat(props.get("field2").getMinProperties().isCompatible()).isTrue();
+    assertThat(props.get("field2").getMinProperties().getOldValue()).isEqualTo(10);
+    assertThat(props.get("field2").getMinProperties().getNewValue()).isEqualTo(1);
+
+    // Check increasing of maxProperties
+    assertThat(props.get("field3").getMaxProperties().isCompatible()).isTrue();
+    assertThat(props.get("field3").getMaxProperties().getOldValue()).isEqualTo(10);
+    assertThat(props.get("field3").getMaxProperties().getNewValue()).isEqualTo(100);
+
+    // Check decreasing of maxProperties
+    assertThat(props.get("field4").getMaxProperties().isIncompatible()).isTrue();
+    assertThat(props.get("field4").getMaxProperties().getOldValue()).isEqualTo(100);
+    assertThat(props.get("field4").getMaxProperties().getNewValue()).isEqualTo(10);
+  }
+
+  @Test // issue #346
+  public void requiredPropertyChangedTest() {
+    ChangedOpenApi changedOpenApi =
+        OpenApiCompare.fromLocations(
+            "schemaDiff/required-property-1.yaml", "schemaDiff/required-property-2.yaml");
+
+    // Test request body schema changes
+    ChangedSchema requestSchema =
+        getRequestBodyChangedSchema(changedOpenApi, POST, "/schema/required", "application/json");
+
+    assertNotNull(requestSchema, "Request schema should not be null");
+    ChangedRequired requestRequired = requestSchema.getRequired();
+    assertNotNull(requestRequired, "Request required changes should not be null");
+
+    // Test request property changes
+    assertThat(requestRequired.getIncreased()).contains("becomesRequired");
+    assertThat(requestRequired.getMissing()).contains("becomesOptional");
+    assertThat(requestRequired.getIncreased()).doesNotContain("unchanged");
+    assertThat(requestRequired.getMissing()).doesNotContain("unchanged");
+
+    // Verify breaking changes in request - new required properties are breaking
+    assertThat(requestRequired.isItemsChanged()).isEqualTo(DiffResult.INCOMPATIBLE);
+
+    // Test response schema changes
+    ChangedSchema responseSchema =
+        getResponseBodyChangedSchema(
+            changedOpenApi, POST, "/schema/required", "200", "application/json");
+
+    assertNotNull(responseSchema, "Response schema should not be null");
+    ChangedRequired responseRequired = responseSchema.getRequired();
+    assertNotNull(responseRequired, "Response required changes should not be null");
+
+    // Test response property changes
+    assertThat(responseRequired.getIncreased()).contains("becomesRequired");
+    assertThat(responseRequired.getMissing()).contains("becomesOptional");
+    assertThat(responseRequired.getIncreased()).doesNotContain("unchanged");
+    assertThat(responseRequired.getMissing()).doesNotContain("unchanged");
+
+    // Verify breaking changes in response - removing required properties is breaking
+    assertThat(responseRequired.isItemsChanged()).isEqualTo(DiffResult.INCOMPATIBLE);
+  }
+
+  @Test // issue #104
+  public void changePatternHandling() {
+    ChangedOpenApi changedOpenApi =
+        OpenApiCompare.fromLocations(
+            "schemaDiff/schema-pattern-diff-1.yaml", "schemaDiff/schema-pattern-diff-2.yaml");
+    ChangedSchema changedSchema =
+        getRequestBodyChangedSchema(changedOpenApi, POST, "/schema/pattern", "application/json");
+
+    assertThat(changedSchema).isNotNull();
+    Map<String, ChangedSchema> props = changedSchema.getChangedProperties();
+    assertThat(props).isNotEmpty();
+
+    // Check no changes in pattern
+    assertThat(props.get("patternUnchanged")).isNull();
+
+    // Check changes in pattern (modification)
+    assertThat(props.get("patternModified").getPattern().isChanged())
+        .isEqualTo(DiffResult.INCOMPATIBLE);
+    assertThat(props.get("patternModified").getPattern().getOldPattern()).isEqualTo("^[a-z]+$");
+    assertThat(props.get("patternModified").getPattern().getNewPattern()).isEqualTo("^[a-zA-Z]+$");
+
+    // Check deletion of pattern
+    assertThat(props.get("patternRemoved").getPattern().isChanged())
+        .isEqualTo(DiffResult.INCOMPATIBLE);
+    assertThat(props.get("patternRemoved").getPattern().getOldPattern()).isEqualTo("^[0-9]+$");
+    assertThat(props.get("patternRemoved").getPattern().getNewPattern()).isNull();
+
+    // Check addition of pattern
+    assertThat(props.get("patternAdded").getPattern().isChanged())
+        .isEqualTo(DiffResult.INCOMPATIBLE);
+    assertThat(props.get("patternAdded").getPattern().getOldPattern()).isNull();
+    assertThat(props.get("patternAdded").getPattern().getNewPattern())
+        .isEqualTo("^\\d{3}-\\d{2}-\\d{4}$?");
+  }
+
+  @Test // issue #212
+  public void testAnyOfDiff() {
+    ChangedOpenApi changedOpenApi =
+        OpenApiCompare.fromLocations(
+            "schemaDiff/anyOf-diff-1.yaml", "schemaDiff/anyOf-diff-2.yaml");
+    ChangedSchema changedSchema =
+        getRequestBodyChangedSchema(changedOpenApi, POST, "/anyof/test", "application/json");
+
+    assertThat(changedSchema).isNotNull();
+    // The diff compares the *merged* schema resulting from anyOf, not the anyOf structure itself.
+    // See details in #772
+    assertThat(changedSchema.isChanged()).isEqualTo(DiffResult.COMPATIBLE);
+
+    // fieldA only changed required status, not its schema
+    assertThat(changedSchema.getChangedProperties()).isEmpty();
+
+    // fieldB: Removed from the merged schema properties
+    assertThat(changedSchema.getMissingProperties()).containsKey("fieldB");
+
+    // fieldC: Added to the merged schema properties
+    assertThat(changedSchema.getIncreasedProperties()).containsKey("fieldC");
+
+    // Check the overall required list changes for the merged schema
+    assertThat(changedSchema.getRequired().isChanged()).isEqualTo(DiffResult.COMPATIBLE);
+    assertThat(changedSchema.getRequired().getMissing()).containsExactly("fieldA");
+    assertThat(changedSchema.getRequired().getIncreased()).isEmpty();
+  }
+
+  @Test // issue #212 - adapted for allOf
+  public void testAllOfDiff() {
+    ChangedOpenApi changedOpenApi =
+        OpenApiCompare.fromLocations(
+            "schemaDiff/allOf-diff-1.yaml", "schemaDiff/allOf-diff-2.yaml");
+    ChangedSchema changedSchema =
+        getRequestBodyChangedSchema(changedOpenApi, POST, "/allof/test", "application/json");
+
+    assertThat(changedSchema).isNotNull();
+    // The diff compares the *merged* schema resulting from allOf, not the allOf structure itself.
+    // See details in #772
+    assertThat(changedSchema.isChanged()).isEqualTo(DiffResult.COMPATIBLE);
+
+    // fieldA only changed required status, commonField is unchanged
+    assertThat(changedSchema.getChangedProperties()).isEmpty();
+
+    // fieldB: Removed from the merged schema properties
+    assertThat(changedSchema.getMissingProperties()).containsKey("fieldB");
+
+    // fieldC: Added to the merged schema properties
+    assertThat(changedSchema.getIncreasedProperties()).containsKey("fieldC");
+
+    // Check the overall required list changes for the merged schema
+    assertThat(changedSchema.getRequired().isChanged()).isEqualTo(DiffResult.COMPATIBLE);
+    assertThat(changedSchema.getRequired().getMissing()).containsExactly("fieldA");
+    assertThat(changedSchema.getRequired().getIncreased()).isEmpty();
+  }
+}
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/TestUtils.java b/core/src/test/java/org/openapitools/openapidiff/core/TestUtils.java
index 5e07d0bcd..597bf830f 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/TestUtils.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/TestUtils.java
@@ -3,7 +3,11 @@
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.slf4j.LoggerFactory.getLogger;
 
+import java.util.List;
+import org.openapitools.openapidiff.core.compare.OpenApiDiffOptions;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 import org.openapitools.openapidiff.core.model.ChangedOpenApi;
+import org.openapitools.openapidiff.core.model.ChangedOperation;
 import org.openapitools.openapidiff.core.model.DiffResult;
 import org.slf4j.Logger;
 
@@ -40,6 +44,24 @@ public static void assertSpecChangedButCompatible(String oldSpec, String newSpec
     assertThat(diffResult.isCompatible()).isTrue();
   }
 
+  public static void assertSpecIncompatible(
+      String oldSpec, String newSpec, BackwardIncompatibleProp prop) {
+    OpenApiDiffOptions.Builder builder = OpenApiDiffOptions.builder();
+    // Expect incompatible when BackwardIncompatibleProp enabled
+    builder.configProperty(prop.getPropertyName(), "true");
+    OpenApiDiffOptions optsIncompat = builder.build();
+    ChangedOpenApi apiIncompat = OpenApiCompare.fromLocations(oldSpec, newSpec, null, optsIncompat);
+    LOG.info("Result: {}", apiIncompat.isChanged().getValue());
+    assertThat(apiIncompat.isIncompatible()).isTrue();
+    // Expect changed but compatible when BackwardIncompatibleProp disabled
+    builder.configProperty(prop.getPropertyName(), "false");
+    OpenApiDiffOptions optsCompat = builder.build();
+    ChangedOpenApi apiCompat = OpenApiCompare.fromLocations(oldSpec, newSpec, null, optsCompat);
+    LOG.info("Result: {}", apiCompat.isChanged().getValue());
+    assertThat(apiCompat.isDifferent()).isTrue();
+    assertThat(apiCompat.isCompatible()).isTrue();
+  }
+
   public static void assertOpenApiBackwardCompatible(
       String oldSpec, String newSpec, boolean isDiff) {
     ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(oldSpec, newSpec);
@@ -52,4 +74,9 @@ public static void assertOpenApiBackwardIncompatible(String oldSpec, String newS
     LOG.info("Result: {}", changedOpenApi.isChanged().getValue());
     assertThat(changedOpenApi.isIncompatible()).isTrue();
   }
+
+  public static List<ChangedOperation> getOpenApiChangedOperations(String oldSpec, String newSpec) {
+    ChangedOpenApi changedOpenApi = OpenApiCompare.fromLocations(oldSpec, newSpec);
+    return changedOpenApi.getChangedOperations();
+  }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ApiResponseBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ApiResponseBCTest.java
index c93bc5d4a..045a16e48 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ApiResponseBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ApiResponseBCTest.java
@@ -1,10 +1,12 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_RESPONSES_DECREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class ApiResponseBCTest {
   private final String BASE = "bc_response_apiresponse_base.yaml";
@@ -21,6 +23,7 @@ public void changedButCompatible() {
 
   @Test
   public void decreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_response_apiresponse_decreased.yaml");
+    BackwardIncompatibleProp prop = RESPONSE_RESPONSES_DECREASED;
+    assertSpecIncompatible(BASE, "bc_response_apiresponse_decreased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ContentBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ContentBCTest.java
index 130255b80..8bd95764e 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ContentBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ContentBCTest.java
@@ -1,10 +1,13 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_CONTENT_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_CONTENT_DECREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class ContentBCTest {
   private final String BASE = "bc_content_base.yaml";
@@ -21,11 +24,13 @@ public void changedButCompatible() {
 
   @Test
   public void requestDecreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_content_decreased.yaml");
+    BackwardIncompatibleProp prop = REQUEST_CONTENT_DECREASED;
+    assertSpecIncompatible(BASE, "bc_request_content_decreased.yaml", prop);
   }
 
   @Test
   public void responseDecreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_response_content_decreased.yaml");
+    BackwardIncompatibleProp prop = RESPONSE_CONTENT_DECREASED;
+    assertSpecIncompatible(BASE, "bc_response_content_decreased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/EnumBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/EnumBCTest.java
index 3eecfda39..d5a7921a4 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/EnumBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/EnumBCTest.java
@@ -1,10 +1,13 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_ENUM_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_ENUM_INCREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class EnumBCTest {
   private final String BASE = "bc_enum_base.yaml";
@@ -21,11 +24,13 @@ public void changedButCompatible() {
 
   @Test
   public void requestDecreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_enum_decreased.yaml");
+    BackwardIncompatibleProp prop = REQUEST_ENUM_DECREASED;
+    assertSpecIncompatible(BASE, "bc_request_enum_decreased.yaml", prop);
   }
 
   @Test
   public void responseIncreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_response_enum_increased.yaml");
+    BackwardIncompatibleProp prop = RESPONSE_ENUM_INCREASED;
+    assertSpecIncompatible(BASE, "bc_response_enum_increased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/HeaderBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/HeaderBCTest.java
index d97209d19..bf36d7772 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/HeaderBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/HeaderBCTest.java
@@ -1,37 +1,44 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_HEADER_EXPLODE_CHANGED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_HEADER_REQUIRED_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_HEADER_REQUIRED_INCREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class HeaderBCTest {
   private final String BASE = "bc_response_header_base.yaml";
 
   @Test
-  public void responseHeaderUnchanged() {
+  public void unchanged() {
     assertSpecUnchanged(BASE, BASE);
   }
 
   @Test
-  public void responseHeaderDeprecated() {
-    assertSpecChangedButCompatible(BASE, "bc_response_header_deprecated.yaml");
+  public void changedButCompatible() {
+    assertSpecChangedButCompatible(BASE, "bc_response_header_changed_but_compatible.yaml");
   }
 
   @Test
-  public void responseHeaderRequiredAdded() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_response_header_required_added.yaml");
+  public void responseExplodeChanged() {
+    BackwardIncompatibleProp prop = RESPONSE_HEADER_EXPLODE_CHANGED;
+    assertSpecIncompatible(BASE, "bc_response_header_explode_changed.yaml", prop);
   }
 
   @Test
-  public void responseHeaderRequiredDeleted() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_response_header_required_deleted.yaml");
+  public void responseRequiredDecreased() {
+    BackwardIncompatibleProp prop = RESPONSE_HEADER_REQUIRED_DECREASED;
+    assertSpecIncompatible(BASE, "bc_response_header_required_decreased.yaml", prop);
   }
 
   @Test
-  public void responseHeaderExplode() {
-    String RESPONSE_HEADER_EXPLODE = "bc_response_header_explode.yaml";
-    assertOpenApiBackwardIncompatible(BASE, RESPONSE_HEADER_EXPLODE);
+  public void responseRequiredIncreased() {
+    // TODO: Document why desired or remove support (test added to avoid unintentional regression)
+    BackwardIncompatibleProp prop = RESPONSE_HEADER_REQUIRED_INCREASED;
+    assertSpecIncompatible(BASE, "bc_response_header_required_increased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/HeadersBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/HeadersBCTest.java
index b796a35e6..e08b4b8c8 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/HeadersBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/HeadersBCTest.java
@@ -1,26 +1,29 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_HEADERS_DECREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class HeadersBCTest {
   private final String BASE = "bc_response_headers_base.yaml";
 
   @Test
-  public void responseHeadersUnchanged() {
+  public void unchanged() {
     assertSpecUnchanged(BASE, BASE);
   }
 
   @Test
-  public void responseHeadersIncreased() {
-    assertSpecChangedButCompatible(BASE, "bc_response_headers_increased.yaml");
+  public void changedButCompatible() {
+    assertSpecChangedButCompatible(BASE, "bc_response_headers_changed_but_compatible.yaml");
   }
 
   @Test
-  public void responseHeadersMissing() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_response_headers_missing.yaml");
+  public void responseDecreased() {
+    BackwardIncompatibleProp prop = RESPONSE_HEADERS_DECREASED;
+    assertSpecIncompatible(BASE, "bc_response_headers_decreased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/MaxLengthBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/MaxLengthBCTest.java
index 96c019b40..243ff892a 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/MaxLengthBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/MaxLengthBCTest.java
@@ -1,9 +1,12 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_MAX_LENGTH_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_MAX_LENGTH_INCREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class MaxLengthBCTest {
   private final String BASE = "bc_maxlength_base.yaml";
@@ -15,11 +18,13 @@ public void maxLengthUnchanged() {
 
   @Test
   public void requestMaxLengthDecreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_maxlength_decreased.yaml");
+    BackwardIncompatibleProp prop = REQUEST_MAX_LENGTH_DECREASED;
+    assertSpecIncompatible(BASE, "bc_request_maxlength_decreased.yaml", prop);
   }
 
   @Test
   public void responseMaxLengthIncreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_response_maxlength_increased.yaml");
+    BackwardIncompatibleProp prop = RESPONSE_MAX_LENGTH_INCREASED;
+    assertSpecIncompatible(BASE, "bc_response_maxlength_increased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/NumericRangeBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/NumericRangeBCTest.java
index 1f713f98a..a589c7ea0 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/NumericRangeBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/NumericRangeBCTest.java
@@ -1,8 +1,10 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_NUMERIC_RANGE_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_NUMERIC_RANGE_INCREASED;
 
 import org.junit.jupiter.api.Test;
 
@@ -16,99 +18,94 @@ public void unchanged() {
 
   @Test
   public void changedButCompatible() {
-    // TODO: Fix bug where response range-narrowing is deemed incompatible, then test here
     assertSpecChangedButCompatible(BASE, "bc_numericrange_changed_but_compatible.yaml");
   }
 
   @Test
   public void requestExclusiveMaxCreated() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_numericrange_exclusive_max_created.yaml");
+    assertIncompatibleRequest("bc_request_numericrange_exclusive_max_created.yaml");
   }
 
   @Test
   public void requestExclusiveMaxSet() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_numericrange_exclusive_max_set.yaml");
+    assertIncompatibleRequest("bc_request_numericrange_exclusive_max_set.yaml");
   }
 
   @Test
   public void requestExclusiveMinCreated() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_numericrange_exclusive_min_created.yaml");
+    assertIncompatibleRequest("bc_request_numericrange_exclusive_min_created.yaml");
   }
 
   @Test
   public void requestExclusiveMinSet() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_numericrange_exclusive_min_set.yaml");
+    assertIncompatibleRequest("bc_request_numericrange_exclusive_min_set.yaml");
   }
 
   @Test
   public void requestMaxAdded() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_numericrange_max_added.yaml");
+    assertIncompatibleRequest("bc_request_numericrange_max_added.yaml");
   }
 
   @Test
   public void requestMaxDecreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_numericrange_max_decreased.yaml");
+    assertIncompatibleRequest("bc_request_numericrange_max_decreased.yaml");
   }
 
   @Test
   public void requestMinAdded() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_numericrange_min_added.yaml");
+    assertIncompatibleRequest("bc_request_numericrange_min_added.yaml");
   }
 
   @Test
   public void requestMinIncreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_numericrange_min_increased.yaml");
+    assertIncompatibleRequest("bc_request_numericrange_min_increased.yaml");
   }
 
   @Test
   public void responseExclusiveMaxDeleted() {
-    // TODO: Should be incompatible because clients may be unprepared for wider range
-    //  (test added to avoid unintentional regression)
-    assertSpecChangedButCompatible(BASE, "bc_response_numericrange_exclusive_max_deleted.yaml");
+    assertIncompatibleResponse("bc_response_numericrange_exclusive_max_deleted.yaml");
   }
 
   @Test
   public void responseExclusiveMaxUnset() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_response_numericrange_exclusive_max_unset.yaml");
+    assertIncompatibleResponse("bc_response_numericrange_exclusive_max_unset.yaml");
   }
 
   @Test
   public void responseExclusiveMinDeleted() {
-    // TODO: Should be incompatible because clients may be unprepared for wider range
-    //  (test added to avoid unintentional regression)
-    assertSpecChangedButCompatible(BASE, "bc_response_numericrange_exclusive_min_deleted.yaml");
+    assertIncompatibleResponse("bc_response_numericrange_exclusive_min_deleted.yaml");
   }
 
   @Test
   public void responseExclusiveMinUnset() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_response_numericrange_exclusive_min_unset.yaml");
+    assertIncompatibleResponse("bc_response_numericrange_exclusive_min_unset.yaml");
   }
 
   @Test
   public void responseMaxDeleted() {
-    // TODO: Should be incompatible because clients may be unprepared for wider range
-    //  (test added to avoid unintentional regression)
-    assertSpecChangedButCompatible(BASE, "bc_response_numericrange_max_deleted.yaml");
+    assertIncompatibleResponse("bc_response_numericrange_max_deleted.yaml");
   }
 
   @Test
   public void responseMaxIncreased() {
-    // TODO: Should be incompatible because clients may be unprepared
-    //  (test added to avoid unintentional regression)
-    assertSpecChangedButCompatible(BASE, "bc_response_numericrange_max_increased.yaml");
+    assertIncompatibleResponse("bc_response_numericrange_max_increased.yaml");
   }
 
   @Test
   public void responseMinDecreased() {
-    // TODO: Should be incompatible because clients may be unprepared for wider range
-    //  (test added to avoid unintentional regression)
-    assertSpecChangedButCompatible(BASE, "bc_response_numericrange_min_decreased.yaml");
+    assertIncompatibleResponse("bc_response_numericrange_min_decreased.yaml");
   }
 
   @Test
   public void responseMinDeleted() {
-    // TODO: Should be incompatible because clients may be unprepared for wider range
-    //  (test added to avoid unintentional regression)
-    assertSpecChangedButCompatible(BASE, "bc_response_numericrange_min_deleted.yaml");
+    assertIncompatibleResponse("bc_response_numericrange_min_deleted.yaml");
+  }
+
+  private void assertIncompatibleRequest(String newSpec) {
+    assertSpecIncompatible(BASE, newSpec, REQUEST_NUMERIC_RANGE_DECREASED);
+  }
+
+  private void assertIncompatibleResponse(String newSpec) {
+    assertSpecIncompatible(BASE, newSpec, RESPONSE_NUMERIC_RANGE_INCREASED);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/OAuthFlowBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/OAuthFlowBCTest.java
index 62cf3b9a0..476546504 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/OAuthFlowBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/OAuthFlowBCTest.java
@@ -1,9 +1,13 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_SCHEME_OAUTH2_AUTH_URL_CHANGED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_SCHEME_OAUTH2_REFRESH_URL_CHANGED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_SCHEME_OAUTH2_TOKEN_URL_CHANGED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class OAuthFlowBCTest {
   private final String BASE = "bc_oauthflow_base.yaml";
@@ -15,16 +19,19 @@ public void unchanged() {
 
   @Test
   public void authorizationUrlChanged() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_oauthflow_authorization_url_changed.yaml");
+    BackwardIncompatibleProp prop = SECURITY_SCHEME_OAUTH2_AUTH_URL_CHANGED;
+    assertSpecIncompatible(BASE, "bc_oauthflow_authorization_url_changed.yaml", prop);
   }
 
   @Test
   public void refreshUrlChanged() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_oauthflow_refresh_url_changed.yaml");
+    BackwardIncompatibleProp prop = SECURITY_SCHEME_OAUTH2_REFRESH_URL_CHANGED;
+    assertSpecIncompatible(BASE, "bc_oauthflow_refresh_url_changed.yaml", prop);
   }
 
   @Test
   public void tokenUrlChanged() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_oauthflow_token_url_changed.yaml");
+    BackwardIncompatibleProp prop = SECURITY_SCHEME_OAUTH2_TOKEN_URL_CHANGED;
+    assertSpecIncompatible(BASE, "bc_oauthflow_token_url_changed.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/OneOfBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/OneOfBCTest.java
index e42829cca..fb2c06291 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/OneOfBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/OneOfBCTest.java
@@ -1,10 +1,13 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_ONEOF_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_ONEOF_INCREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class OneOfBCTest {
   private final String BASE = "bc_oneof_base.yaml";
@@ -20,12 +23,14 @@ public void changedButCompatible() {
   }
 
   @Test
-  public void requestOneOfDecreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_oneof_decreased.yaml");
+  public void requestDecreased() {
+    BackwardIncompatibleProp prop = REQUEST_ONEOF_DECREASED;
+    assertSpecIncompatible(BASE, "bc_request_oneof_decreased.yaml", prop);
   }
 
   @Test
-  public void responseOneOfIncreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_response_oneof_increased.yaml");
+  public void responseIncreased() {
+    BackwardIncompatibleProp prop = RESPONSE_ONEOF_INCREASED;
+    assertSpecIncompatible(BASE, "bc_response_oneof_increased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/OpenApiBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/OpenApiBCTest.java
index 0cb493aa2..2d3e53065 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/OpenApiBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/OpenApiBCTest.java
@@ -1,10 +1,12 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.OPENAPI_ENDPOINTS_DECREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class OpenApiBCTest {
   private final String BASE = "bc_openapi_base.yaml";
@@ -21,6 +23,7 @@ public void changedButCompatible() {
 
   @Test
   public void endpointsDecreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_openapi_endpoints_decreased.yaml");
+    BackwardIncompatibleProp prop = OPENAPI_ENDPOINTS_DECREASED;
+    assertSpecIncompatible(BASE, "bc_openapi_endpoints_decreased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ParameterBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ParameterBCTest.java
index 4f1d30852..edcd40073 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ParameterBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ParameterBCTest.java
@@ -1,10 +1,15 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_PARAMS_REQUIRED_INCREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_PARAM_ALLOWEMPTY_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_PARAM_EXPLODE_CHANGED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_PARAM_STYLE_CHANGED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class ParameterBCTest {
   private final String BASE = "bc_request_param_base.yaml";
@@ -21,21 +26,25 @@ public void changedButCompatible() {
 
   @Test
   public void allowEmptyValueDecreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_param_allowemptyvalue_decreased.yaml");
+    BackwardIncompatibleProp prop = REQUEST_PARAM_ALLOWEMPTY_DECREASED;
+    assertSpecIncompatible(BASE, "bc_request_param_allowemptyvalue_decreased.yaml", prop);
   }
 
   @Test
   public void explodeChanged() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_param_explode_changed.yaml");
+    BackwardIncompatibleProp prop = REQUEST_PARAM_EXPLODE_CHANGED;
+    assertSpecIncompatible(BASE, "bc_request_param_explode_changed.yaml", prop);
   }
 
   @Test
   public void requiredIncreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_param_required_increased.yaml");
+    BackwardIncompatibleProp prop = REQUEST_PARAMS_REQUIRED_INCREASED;
+    assertSpecIncompatible(BASE, "bc_request_param_required_increased.yaml", prop);
   }
 
   @Test
   public void styleChanged() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_param_style_changed.yaml");
+    BackwardIncompatibleProp prop = REQUEST_PARAM_STYLE_CHANGED;
+    assertSpecIncompatible(BASE, "bc_request_param_style_changed.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ParametersBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ParametersBCTest.java
index 1b913115d..5f2755bbc 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ParametersBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ParametersBCTest.java
@@ -1,10 +1,13 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_PARAMS_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_PARAMS_REQUIRED_INCREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class ParametersBCTest {
   private final String BASE = "bc_request_params_base.yaml";
@@ -21,11 +24,13 @@ public void changedButCompatible() {
 
   @Test
   public void decreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_params_decreased.yaml");
+    BackwardIncompatibleProp prop = REQUEST_PARAMS_DECREASED;
+    assertSpecIncompatible(BASE, "bc_request_params_decreased.yaml", prop);
   }
 
   @Test
   public void requiredIncreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_params_required_increased.yaml");
+    BackwardIncompatibleProp prop = REQUEST_PARAMS_REQUIRED_INCREASED;
+    assertSpecIncompatible(BASE, "bc_request_params_required_increased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/PathBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/PathBCTest.java
index b0b9ab39c..c1b2a60f1 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/PathBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/PathBCTest.java
@@ -1,10 +1,12 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.OPENAPI_ENDPOINTS_DECREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class PathBCTest {
   private final String BASE = "bc_path_base.yaml";
@@ -21,6 +23,7 @@ public void changedButCompatible() {
 
   @Test
   public void opsDecreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_path_ops_decreased.yaml");
+    BackwardIncompatibleProp prop = OPENAPI_ENDPOINTS_DECREASED;
+    assertSpecIncompatible(BASE, "bc_path_ops_decreased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/PathsBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/PathsBCTest.java
index 495739d18..d865ee44a 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/PathsBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/PathsBCTest.java
@@ -1,10 +1,12 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.OPENAPI_ENDPOINTS_DECREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class PathsBCTest {
   private final String BASE = "bc_paths_base.yaml";
@@ -21,6 +23,7 @@ public void changedButCompatible() {
 
   @Test
   public void decreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_paths_decreased.yaml");
+    BackwardIncompatibleProp prop = OPENAPI_ENDPOINTS_DECREASED;
+    assertSpecIncompatible(BASE, "bc_paths_decreased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ReadOnlyBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ReadOnlyBCTest.java
index 579a7e178..02d2fa9a0 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ReadOnlyBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/ReadOnlyBCTest.java
@@ -1,10 +1,13 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_READONLY_INCREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_READONLY_REQUIRED_DECREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class ReadOnlyBCTest {
   private final String BASE = "bc_readonly_base.yaml";
@@ -21,12 +24,14 @@ public void changedButCompatible() {
 
   @Test
   public void requestReadOnlyIncreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_readonly_increased.yaml");
+    BackwardIncompatibleProp prop = REQUEST_READONLY_INCREASED;
+    assertSpecIncompatible(BASE, "bc_request_readonly_increased.yaml", prop);
   }
 
   @Test
   public void requestReadOnlyRequiredDecreased() {
-    // TODO: Document why desired or remove support (test added to avoid unintentional regression)
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_readonly_required_decreased.yaml");
+    // Incompatible because a prev RO prop (invalid) is now not RO and required
+    BackwardIncompatibleProp prop = REQUEST_READONLY_REQUIRED_DECREASED;
+    assertSpecIncompatible(BASE, "bc_request_readonly_required_decreased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/RequestBodyBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/RequestBodyBCTest.java
index b02c0a3e0..5b1000702 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/RequestBodyBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/RequestBodyBCTest.java
@@ -1,9 +1,11 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.OPENAPI_ENDPOINTS_DECREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class RequestBodyBCTest {
   private final String BASE = "bc_request_body_base.yaml";
@@ -15,6 +17,7 @@ public void unchanged() {
 
   @Test
   public void requiredChanged() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_body_required_changed.yaml");
+    BackwardIncompatibleProp prop = OPENAPI_ENDPOINTS_DECREASED;
+    assertSpecIncompatible(BASE, "bc_request_body_required_changed.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/RequiredBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/RequiredBCTest.java
index bda8b2d8e..c7cfadb0a 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/RequiredBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/RequiredBCTest.java
@@ -1,10 +1,13 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.REQUEST_REQUIRED_INCREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_REQUIRED_DECREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class RequiredBCTest {
 
@@ -22,11 +25,13 @@ public void changedButCompatible() {
 
   @Test
   public void requestRequiredIncreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_request_required_increased.yaml");
+    BackwardIncompatibleProp prop = REQUEST_REQUIRED_INCREASED;
+    assertSpecIncompatible(BASE, "bc_request_required_increased.yaml", prop);
   }
 
   @Test
   public void responseRequiredDecreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_response_required_decreased.yaml");
+    BackwardIncompatibleProp prop = RESPONSE_REQUIRED_DECREASED;
+    assertSpecIncompatible(BASE, "bc_response_required_decreased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SchemaBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SchemaBCTest.java
index f0e683b79..781b48f2a 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SchemaBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SchemaBCTest.java
@@ -2,9 +2,14 @@
 
 import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_REQUIRED_DECREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SCHEMA_DISCRIMINATOR_CHANGED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SCHEMA_TYPE_CHANGED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class SchemaBCTest {
   private final String BASE = "bc_schema_base.yaml";
@@ -21,7 +26,8 @@ public void changedButCompatible() {
 
   @Test
   public void discriminatorChanged() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_schema_discriminator_changed.yaml");
+    BackwardIncompatibleProp prop = SCHEMA_DISCRIMINATOR_CHANGED;
+    assertSpecIncompatible(BASE, "bc_schema_discriminator_changed.yaml", prop);
   }
 
   @Test
@@ -37,6 +43,7 @@ public void requestFormatIncreased() {
 
   @Test
   public void requestPropsPutIncreased() {
+    // See https://github.com/OpenAPITools/openapi-diff/issues/537
     assertSpecChangedButCompatible(BASE, "bc_request_schema_props_put_increased.yaml");
   }
 
@@ -53,11 +60,13 @@ public void responseFormatIncreased() {
 
   @Test
   public void responsePropsRequiredDecreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_response_schema_props_required_decreased.yaml");
+    BackwardIncompatibleProp prop = RESPONSE_REQUIRED_DECREASED;
+    assertSpecIncompatible(BASE, "bc_response_schema_props_required_decreased.yaml", prop);
   }
 
   @Test
   public void typeChanged() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_schema_type_changed.yaml");
+    BackwardIncompatibleProp prop = SCHEMA_TYPE_CHANGED;
+    assertSpecIncompatible(BASE, "bc_schema_type_changed.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SecurityRequirementBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SecurityRequirementBCTest.java
index 80c79cec9..73a3ca227 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SecurityRequirementBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SecurityRequirementBCTest.java
@@ -1,8 +1,10 @@
 package org.openapitools.openapidiff.core.backcompat;
 
 import static org.openapitools.openapidiff.core.TestUtils.*;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_REQUIREMENT_SCHEMES_INCREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class SecurityRequirementBCTest {
   private final String BASE = "bc_security_requirement_base.yaml";
@@ -19,6 +21,7 @@ public void changedButCompatible() {
 
   @Test
   public void schemesIncreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_security_requirement_schemes_increased.yaml");
+    BackwardIncompatibleProp prop = SECURITY_REQUIREMENT_SCHEMES_INCREASED;
+    assertSpecIncompatible(BASE, "bc_security_requirement_schemes_increased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SecurityRequirementsBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SecurityRequirementsBCTest.java
index a9df11df0..931b35bce 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SecurityRequirementsBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SecurityRequirementsBCTest.java
@@ -1,10 +1,10 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
-import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
-import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.TestUtils.*;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.SECURITY_REQUIREMENTS_DECREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class SecurityRequirementsBCTest {
   private final String BASE = "bc_security_requirements_base.yaml";
@@ -26,7 +26,8 @@ public void changedButCompatible() {
   // requirements should be compatible.
   @Test
   public void decreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_security_requirements_decreased.yaml");
+    BackwardIncompatibleProp prop = SECURITY_REQUIREMENTS_DECREASED;
+    assertSpecIncompatible(BASE, "bc_security_requirements_decreased.yaml", prop);
   }
 
   // TODO: A missing incompatible check seems to be if requirements increase from zero to 1 or more
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SecuritySchemeBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SecuritySchemeBCTest.java
index b275523dd..d89d824d5 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SecuritySchemeBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/SecuritySchemeBCTest.java
@@ -1,10 +1,10 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
-import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
-import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.TestUtils.*;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.*;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class SecuritySchemeBCTest {
   private final String BASE = "bc_security_scheme_base.yaml";
@@ -21,7 +21,8 @@ public void changedButCompatible() {
 
   @Test
   public void bearerFormatChanged() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_security_scheme_bearer_format_changed.yaml");
+    BackwardIncompatibleProp prop = SECURITY_SCHEME_BEARER_FORMAT_CHANGED;
+    assertSpecIncompatible(BASE, "bc_security_scheme_bearer_format_changed.yaml", prop);
   }
 
   @Test
@@ -31,12 +32,14 @@ public void inChanged() {
 
   @Test
   public void openIdConnectUrlChanged() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_security_scheme_open_id_connect_url_changed.yaml");
+    BackwardIncompatibleProp prop = SECURITY_SCHEME_OPENIDCONNECT_URL_CHANGED;
+    assertSpecIncompatible(BASE, "bc_security_scheme_open_id_connect_url_changed.yaml", prop);
   }
 
   @Test
   public void schemeChanged() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_security_scheme_scheme_changed.yaml");
+    BackwardIncompatibleProp prop = SECURITY_SCHEME_SCHEME_CHANGED;
+    assertSpecIncompatible(BASE, "bc_security_scheme_scheme_changed.yaml", prop);
   }
 
   @Test
@@ -46,6 +49,7 @@ public void typeChanged() {
 
   @Test
   public void scopesIncreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_security_scheme_scopes_increased.yaml");
+    BackwardIncompatibleProp prop = SECURITY_SCHEME_SCOPES_INCREASED;
+    assertSpecIncompatible(BASE, "bc_security_scheme_scopes_increased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/WriteOnlyBCTest.java b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/WriteOnlyBCTest.java
index f3ea427f0..a12853c82 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/backcompat/WriteOnlyBCTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/backcompat/WriteOnlyBCTest.java
@@ -1,10 +1,13 @@
 package org.openapitools.openapidiff.core.backcompat;
 
-import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiBackwardIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecChangedButCompatible;
+import static org.openapitools.openapidiff.core.TestUtils.assertSpecIncompatible;
 import static org.openapitools.openapidiff.core.TestUtils.assertSpecUnchanged;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_WRITEONLY_INCREASED;
+import static org.openapitools.openapidiff.core.model.BackwardIncompatibleProp.RESPONSE_WRITEONLY_REQUIRED_DECREASED;
 
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.model.BackwardIncompatibleProp;
 
 public class WriteOnlyBCTest {
   private final String BASE = "bc_writeonly_base.yaml";
@@ -21,12 +24,14 @@ public void changedButCompatible() {
 
   @Test
   public void responseWriteOnlyIncreased() {
-    assertOpenApiBackwardIncompatible(BASE, "bc_response_writeonly_increased.yaml");
+    BackwardIncompatibleProp prop = RESPONSE_WRITEONLY_INCREASED;
+    assertSpecIncompatible(BASE, "bc_response_writeonly_increased.yaml", prop);
   }
 
   @Test
   public void responseWriteOnlyRequiredDecreased() {
+    BackwardIncompatibleProp prop = RESPONSE_WRITEONLY_REQUIRED_DECREASED;
     // TODO: Document why desired or remove support (test added to avoid unintentional regression)
-    assertOpenApiBackwardIncompatible(BASE, "bc_response_writeonly_required_decreased.yaml");
+    assertSpecIncompatible(BASE, "bc_response_writeonly_required_decreased.yaml", prop);
   }
 }
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/output/AsciidocRenderTest.java b/core/src/test/java/org/openapitools/openapidiff/core/output/AsciidocRenderTest.java
new file mode 100644
index 000000000..228623a2c
--- /dev/null
+++ b/core/src/test/java/org/openapitools/openapidiff/core/output/AsciidocRenderTest.java
@@ -0,0 +1,96 @@
+package org.openapitools.openapidiff.core.output;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStreamWriter;
+import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.OpenApiCompare;
+import org.openapitools.openapidiff.core.model.ChangedOpenApi;
+
+public class AsciidocRenderTest {
+  @Test
+  public void renderDoesNotFailWhenPropertyHasBeenRemoved() {
+    AsciidocRender render = new AsciidocRender();
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+    ChangedOpenApi diff =
+        OpenApiCompare.fromLocations("missing_property_1.yaml", "missing_property_2.yaml");
+    render.render(diff, outputStreamWriter);
+    assertThat(outputStream.toString()).isNotBlank();
+  }
+
+  @Test
+  public void renderDoesNotCauseStackOverflowWithRecursiveDefinitions() {
+    AsciidocRender render = new AsciidocRender();
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+    ChangedOpenApi diff = OpenApiCompare.fromLocations("recursive_old.yaml", "recursive_new.yaml");
+    render.render(diff, outputStreamWriter);
+    assertThat(outputStream.toString()).isNotBlank();
+  }
+
+  @Test
+  public void renderDoesNotFailWhenHTTPStatusCodeIsRange() {
+    AsciidocRender render = new AsciidocRender();
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+    ChangedOpenApi diff =
+        OpenApiCompare.fromLocations("range_statuscode_1.yaml", "range_statuscode_2.yaml");
+    render.render(diff, outputStreamWriter);
+    assertThat(outputStream.toString()).isNotBlank();
+  }
+
+  @Test
+  public void validateAsciiDocChangeFile() {
+    AsciidocRender render = new AsciidocRender();
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+    ChangedOpenApi diff =
+        OpenApiCompare.fromLocations("missing_property_1.yaml", "missing_property_2.yaml");
+    render.render(diff, outputStreamWriter);
+    assertThat(outputStream.toString())
+        .isEqualTo(
+            "= TITLE (v 1.0.0)\n"
+                + ":reproducible:\n"
+                + ":sectlinks:\n"
+                + ":toc:\n"
+                + "\n"
+                + "== What's Changed\n"
+                + "=== GET   /\n"
+                + "* Return Type:\n"
+                + "** Changed default \n"
+                + "** Media types:\n"
+                + "*** Changed application/json\n"
+                + "*** Schema:\n"
+                + "Backward compatible\n"
+                + "\n"
+                + "\n"
+                + "NOTE: API changes are backward compatible\n");
+  }
+
+  @Test
+  public void validateAsciiDocRangeStatus() {
+    AsciidocRender render = new AsciidocRender();
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+    ChangedOpenApi diff =
+        OpenApiCompare.fromLocations("range_statuscode_1.yaml", "range_statuscode_2.yaml");
+    render.render(diff, outputStreamWriter);
+    assertThat(outputStream.toString())
+        .isEqualTo(
+            "= PROJECTS API (v 1.0.0)\n"
+                + ":reproducible:\n"
+                + ":sectlinks:\n"
+                + ":toc:\n"
+                + "\n"
+                + "== What's Changed\n"
+                + "=== GET   /pet/\n"
+                + "* Return Type:\n"
+                + "** Add 4XX \n"
+                + "** Deleted 405 Method Not Allowed\n"
+                + "\n"
+                + "\n"
+                + "WARNING: API changes broke backward compatibility\n");
+  }
+}
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/output/ConsoleRenderTest.java b/core/src/test/java/org/openapitools/openapidiff/core/output/ConsoleRenderTest.java
new file mode 100644
index 000000000..675633fcd
--- /dev/null
+++ b/core/src/test/java/org/openapitools/openapidiff/core/output/ConsoleRenderTest.java
@@ -0,0 +1,79 @@
+package org.openapitools.openapidiff.core.output;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStreamWriter;
+import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.OpenApiCompare;
+import org.openapitools.openapidiff.core.model.ChangedOpenApi;
+
+public class ConsoleRenderTest {
+  @Test
+  public void renderDoesNotFailWhenPropertyHasBeenRemoved() {
+    ConsoleRender render = new ConsoleRender();
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+    ChangedOpenApi diff =
+        OpenApiCompare.fromLocations("missing_property_1.yaml", "missing_property_2.yaml");
+    render.render(diff, outputStreamWriter);
+    assertThat(outputStream.toString()).isNotBlank();
+  }
+
+  @Test
+  public void renderDoesNotFailWhenHTTPStatusCodeIsRange() {
+    ConsoleRender render = new ConsoleRender();
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+    ChangedOpenApi diff =
+        OpenApiCompare.fromLocations("range_statuscode_1.yaml", "range_statuscode_2.yaml");
+    render.render(diff, outputStreamWriter);
+    assertThat(outputStream.toString()).isNotBlank();
+  }
+
+  @Test
+  public void renderShowsWhatsDeletedSectionWhenEndpointIsDeleted() {
+    ConsoleRender render = new ConsoleRender();
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+    ChangedOpenApi diff =
+        OpenApiCompare.fromLocations("delete_endpoint_1.yaml", "delete_endpoint_2.yaml");
+    render.render(diff, outputStreamWriter);
+    assertThat(outputStream.toString()).contains("What's Deleted");
+  }
+
+  @Test
+  public void renderShowsWhatsNewSectionWhenEndpointIsAdded() {
+    ConsoleRender render = new ConsoleRender();
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+    ChangedOpenApi diff =
+        OpenApiCompare.fromLocations("add_endpoint_1.yaml", "add_endpoint_2.yaml");
+    render.render(diff, outputStreamWriter);
+    assertThat(outputStream.toString()).contains("What's New");
+  }
+
+  @Test
+  public void renderShowsWhatsDeprecatedSectionWhenEndpointIsDeprecated() {
+    ConsoleRender render = new ConsoleRender();
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+    ChangedOpenApi diff =
+        OpenApiCompare.fromLocations("deprecate_endpoint_1.yaml", "deprecate_endpoint_2.yaml");
+    render.render(diff, outputStreamWriter);
+    assertThat(outputStream.toString()).contains("What's Deprecated");
+  }
+
+  @Test
+  public void renderShowsWhatsChangedSectionWithCorrectFormattingWhenEndpointIsChanged() {
+    ConsoleRender render = new ConsoleRender();
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+    ChangedOpenApi diff =
+        OpenApiCompare.fromLocations("change_endpoint_1.yaml", "change_endpoint_2.yaml");
+    render.render(diff, outputStreamWriter);
+    assertThat(outputStream.toString())
+        .contains("What's Changed")
+        .containsSubsequence("- GET    /widgets", "Parameter:", "- Changed query-param-1 in query");
+  }
+}
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/HtmlRenderTest.java b/core/src/test/java/org/openapitools/openapidiff/core/output/HtmlRenderTest.java
similarity index 87%
rename from core/src/test/java/org/openapitools/openapidiff/core/HtmlRenderTest.java
rename to core/src/test/java/org/openapitools/openapidiff/core/output/HtmlRenderTest.java
index aa44725c4..e62268d10 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/HtmlRenderTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/output/HtmlRenderTest.java
@@ -1,12 +1,12 @@
-package org.openapitools.openapidiff.core;
+package org.openapitools.openapidiff.core.output;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStreamWriter;
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.OpenApiCompare;
 import org.openapitools.openapidiff.core.model.ChangedOpenApi;
-import org.openapitools.openapidiff.core.output.HtmlRender;
 
 public class HtmlRenderTest {
   @Test
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/JsonRenderTest.java b/core/src/test/java/org/openapitools/openapidiff/core/output/JsonRenderTest.java
similarity index 91%
rename from core/src/test/java/org/openapitools/openapidiff/core/JsonRenderTest.java
rename to core/src/test/java/org/openapitools/openapidiff/core/output/JsonRenderTest.java
index 280dce9d0..da5ce9ecc 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/JsonRenderTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/output/JsonRenderTest.java
@@ -1,12 +1,12 @@
-package org.openapitools.openapidiff.core;
+package org.openapitools.openapidiff.core.output;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStreamWriter;
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.OpenApiCompare;
 import org.openapitools.openapidiff.core.model.ChangedOpenApi;
-import org.openapitools.openapidiff.core.output.JsonRender;
 
 public class JsonRenderTest {
   @Test
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/MarkdownRenderTest.java b/core/src/test/java/org/openapitools/openapidiff/core/output/MarkdownRenderTest.java
similarity index 94%
rename from core/src/test/java/org/openapitools/openapidiff/core/MarkdownRenderTest.java
rename to core/src/test/java/org/openapitools/openapidiff/core/output/MarkdownRenderTest.java
index d30c6e0b1..fb1f24fef 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/MarkdownRenderTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/output/MarkdownRenderTest.java
@@ -1,12 +1,12 @@
-package org.openapitools.openapidiff.core;
+package org.openapitools.openapidiff.core.output;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStreamWriter;
 import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.OpenApiCompare;
 import org.openapitools.openapidiff.core.model.ChangedOpenApi;
-import org.openapitools.openapidiff.core.output.MarkdownRender;
 
 public class MarkdownRenderTest {
   @Test
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/output/RenderTest.java b/core/src/test/java/org/openapitools/openapidiff/core/output/RenderTest.java
new file mode 100644
index 000000000..86f1e5842
--- /dev/null
+++ b/core/src/test/java/org/openapitools/openapidiff/core/output/RenderTest.java
@@ -0,0 +1,27 @@
+package org.openapitools.openapidiff.core.output;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+import java.io.IOException;
+import org.junit.jupiter.api.Test;
+import org.openapitools.openapidiff.core.exception.RendererException;
+import org.openapitools.openapidiff.core.model.ChangedOpenApi;
+
+class RenderTest {
+
+  private final Render testRenderImpl =
+      (diff, outputStreamWriter) -> {
+        try {
+          outputStreamWriter.write("Output");
+          outputStreamWriter.close();
+        } catch (IOException e) {
+          throw new RendererException(e);
+        }
+      };
+
+  @Test
+  void testDefaultRenderMethod() {
+    ChangedOpenApi diff = new ChangedOpenApi(null);
+    assertThat(testRenderImpl.render(diff)).isEqualTo("Output");
+  }
+}
diff --git a/core/src/test/java/org/openapitools/openapidiff/core/utils/FileUtilsTest.java b/core/src/test/java/org/openapitools/openapidiff/core/utils/FileUtilsTest.java
index 5d9b4d79b..73c1e53b0 100644
--- a/core/src/test/java/org/openapitools/openapidiff/core/utils/FileUtilsTest.java
+++ b/core/src/test/java/org/openapitools/openapidiff/core/utils/FileUtilsTest.java
@@ -12,6 +12,7 @@
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.TempDir;
+import org.openapitools.openapidiff.core.compare.OpenApiDiffOptions;
 import org.openapitools.openapidiff.core.model.ChangedOpenApi;
 import org.openapitools.openapidiff.core.output.ConsoleRender;
 
@@ -20,7 +21,7 @@ class FileUtilsTest {
 
   @BeforeEach
   void setup() {
-    changedOpenApi = new ChangedOpenApi();
+    changedOpenApi = new ChangedOpenApi(OpenApiDiffOptions.builder().build());
     changedOpenApi.setChangedSchemas(Collections.emptyList());
     changedOpenApi.setChangedOperations(Collections.emptyList());
     changedOpenApi.setNewEndpoints(Collections.emptyList());
diff --git a/core/src/test/resources/add_endpoint_1.yaml b/core/src/test/resources/add_endpoint_1.yaml
new file mode 100644
index 000000000..0c544c7b4
--- /dev/null
+++ b/core/src/test/resources/add_endpoint_1.yaml
@@ -0,0 +1,35 @@
+openapi: 3.0.0
+servers:
+  - url: 'http://petstore.swagger.io/v2'
+info:
+  description: >-
+    This is a sample server Petstore server.  You can find out more about
+    Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
+    #swagger](http://swagger.io/irc/).  For this sample, you can use the api key
+    `special-key` to test the authorization filters.
+  version: 1.0.0
+  title: Swagger Petstore
+  termsOfService: 'http://swagger.io/terms/'
+  contact:
+    email: apiteam@swagger.io
+  license:
+    name: Apache 2.0
+    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
+paths:
+  /pet/{petId}:
+    get:
+      tags:
+        - pet
+      summary: gets a pet by id
+      description: ''
+      operationId: updatePetWithForm
+      parameters:
+        - name: petId
+          in: path
+          description: ID of pet that needs to be updated
+          required: true
+          schema:
+            type: integer
+      responses:
+        '405':
+          description: Invalid input
diff --git a/core/src/test/resources/add_endpoint_2.yaml b/core/src/test/resources/add_endpoint_2.yaml
new file mode 100644
index 000000000..95906047e
--- /dev/null
+++ b/core/src/test/resources/add_endpoint_2.yaml
@@ -0,0 +1,53 @@
+openapi: 3.0.0
+servers:
+  - url: 'http://petstore.swagger.io/v2'
+info:
+  description: >-
+    This is a sample server Petstore server.  You can find out more about
+    Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
+    #swagger](http://swagger.io/irc/).  For this sample, you can use the api key
+    `special-key` to test the authorization filters.
+  version: 1.0.0
+  title: Swagger Petstore
+  termsOfService: 'http://swagger.io/terms/'
+  contact:
+    email: apiteam@swagger.io
+  license:
+    name: Apache 2.0
+    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
+paths:
+  /pet/{petId}:
+    get:
+      tags:
+        - pet
+      summary: gets a pet by id
+      description: ''
+      operationId: updatePetWithForm
+      parameters:
+        - name: petId
+          in: path
+          description: ID of pet that needs to be updated
+          required: true
+          schema:
+            type: integer
+      responses:
+        '405':
+          description: Invalid input
+  /pet/{petId2}:
+    post:
+      tags:
+        - pet
+      summary: deletes a pet
+      description: ''
+      operationId: deletePet
+      deprecated: true
+      parameters:
+        - name: petId2
+          in: path
+          description: Pet ID to delete
+          required: true
+          schema:
+            type: integer
+      responses:
+        '405':
+          description: Invalid input
diff --git a/core/src/test/resources/bc_numericrange_changed_but_compatible.yaml b/core/src/test/resources/bc_numericrange_changed_but_compatible.yaml
index b38f2fe9e..f7e5057f4 100644
--- a/core/src/test/resources/bc_numericrange_changed_but_compatible.yaml
+++ b/core/src/test/resources/bc_numericrange_changed_but_compatible.yaml
@@ -14,7 +14,6 @@ paths:
               type: integer
               format: int32
               exclusiveMinimum: false
-              exclusiveMaximum: false
           application/text:
             schema:
               type: integer
@@ -25,10 +24,9 @@ paths:
             schema:
               type: integer
               format: int32
-              minimum: 9
-              maximum: 21
-              exclusiveMinimum: true
-              exclusiveMaximum: true
+              minimum: 10
+              maximum: 20
+              exclusiveMinimum: false
       responses:
         '200':
           description: successful operation
@@ -37,21 +35,20 @@ paths:
               schema:
                 type: integer
                 format: int32
-                exclusiveMinimum: false
-                exclusiveMaximum: false
+                exclusiveMinimum: true
             application/text:
               schema:
                 type: integer
                 format: int32
-                # TODO: Narrowing response range fails as incompatible, but shouldn't it be ok?
                 minimum: 10
                 maximum: 20
+                exclusiveMinimum: true
+                exclusiveMaximum: true
             application/xml:
               schema:
                 type: integer
                 format: int32
-                # TODO: Narrowing response range fails as incompatible, but shouldn't it be ok?
-                minimum: 10
-                maximum: 20
+                minimum: 11
+                maximum: 19
                 exclusiveMinimum: true
                 exclusiveMaximum: true
diff --git a/core/src/test/resources/bc_response_header_base.yaml b/core/src/test/resources/bc_response_header_base.yaml
index 17716ba06..1680fee21 100644
--- a/core/src/test/resources/bc_response_header_base.yaml
+++ b/core/src/test/resources/bc_response_header_base.yaml
@@ -19,3 +19,11 @@ paths:
             X-Header-2:
               schema:
                 type: integer
+            X-Header-3:
+              schema:
+                type: integer
+              explode: false
+            X-Header-4:
+              schema:
+                type: integer
+              explode: true
diff --git a/core/src/test/resources/bc_response_header_required_deleted.yaml b/core/src/test/resources/bc_response_header_changed_but_compatible.yaml
similarity index 57%
rename from core/src/test/resources/bc_response_header_required_deleted.yaml
rename to core/src/test/resources/bc_response_header_changed_but_compatible.yaml
index c227a3921..b660903db 100644
--- a/core/src/test/resources/bc_response_header_required_deleted.yaml
+++ b/core/src/test/resources/bc_response_header_changed_but_compatible.yaml
@@ -12,9 +12,20 @@ paths:
           description: successful operation
           headers:
             X-Header-1:
+              required: true
               schema:
                 type: integer
                 format: int32
+              deprecated: false
             X-Header-2:
               schema:
                 type: integer
+              deprecated: true
+            X-Header-3:
+              schema:
+                type: integer
+              explode: false
+            X-Header-4:
+              schema:
+                type: integer
+              explode: true
diff --git a/core/src/test/resources/bc_response_header_explode.yaml b/core/src/test/resources/bc_response_header_explode_changed.yaml
similarity index 72%
rename from core/src/test/resources/bc_response_header_explode.yaml
rename to core/src/test/resources/bc_response_header_explode_changed.yaml
index d48a726a7..3403c28eb 100644
--- a/core/src/test/resources/bc_response_header_explode.yaml
+++ b/core/src/test/resources/bc_response_header_explode_changed.yaml
@@ -20,3 +20,10 @@ paths:
               schema:
                 type: integer
               explode: true
+            X-Header-3:
+              schema:
+                type: integer
+            X-Header-4:
+              schema:
+                type: integer
+              explode: false
diff --git a/core/src/test/resources/bc_response_header_deprecated.yaml b/core/src/test/resources/bc_response_header_required_decreased.yaml
similarity index 66%
rename from core/src/test/resources/bc_response_header_deprecated.yaml
rename to core/src/test/resources/bc_response_header_required_decreased.yaml
index 0c60132bd..9b457cdc7 100644
--- a/core/src/test/resources/bc_response_header_deprecated.yaml
+++ b/core/src/test/resources/bc_response_header_required_decreased.yaml
@@ -12,11 +12,17 @@ paths:
           description: successful operation
           headers:
             X-Header-1:
-              required: true
               schema:
                 type: integer
                 format: int32
             X-Header-2:
-              deprecated: true
               schema:
                 type: integer
+            X-Header-3:
+              schema:
+                type: integer
+              explode: false
+            X-Header-4:
+              schema:
+                type: integer
+              explode: true
diff --git a/core/src/test/resources/bc_response_header_required_added.yaml b/core/src/test/resources/bc_response_header_required_increased.yaml
similarity index 69%
rename from core/src/test/resources/bc_response_header_required_added.yaml
rename to core/src/test/resources/bc_response_header_required_increased.yaml
index 83bceafe8..7d76aec7e 100644
--- a/core/src/test/resources/bc_response_header_required_added.yaml
+++ b/core/src/test/resources/bc_response_header_required_increased.yaml
@@ -17,6 +17,14 @@ paths:
                 type: integer
                 format: int32
             X-Header-2:
+              schema:
+                type: integer
               required: true
+            X-Header-3:
+              schema:
+                type: integer
+              explode: false
+            X-Header-4:
               schema:
                 type: integer
+              explode: true
diff --git a/core/src/test/resources/bc_response_headers_increased.yaml b/core/src/test/resources/bc_response_headers_changed_but_compatible.yaml
similarity index 100%
rename from core/src/test/resources/bc_response_headers_increased.yaml
rename to core/src/test/resources/bc_response_headers_changed_but_compatible.yaml
diff --git a/core/src/test/resources/bc_response_headers_missing.yaml b/core/src/test/resources/bc_response_headers_decreased.yaml
similarity index 100%
rename from core/src/test/resources/bc_response_headers_missing.yaml
rename to core/src/test/resources/bc_response_headers_decreased.yaml
diff --git a/core/src/test/resources/change_endpoint_1.yaml b/core/src/test/resources/change_endpoint_1.yaml
new file mode 100644
index 000000000..555015991
--- /dev/null
+++ b/core/src/test/resources/change_endpoint_1.yaml
@@ -0,0 +1,29 @@
+openapi: 3.0.0
+info:
+  description: myDesc
+  title: myTitle
+  version: 1.0.0
+paths:
+  /widgets:
+    get:
+      operationId: listWidgets
+      parameters:
+        - name: query-param-1
+          in: query
+          required: true
+          schema:
+            type: string
+        - name: query-param-2
+          in: query
+          style: form
+          explode: true
+          allowEmptyValue: true
+          schema:
+            type: string
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: string
diff --git a/core/src/test/resources/change_endpoint_2.yaml b/core/src/test/resources/change_endpoint_2.yaml
new file mode 100644
index 000000000..281fd0514
--- /dev/null
+++ b/core/src/test/resources/change_endpoint_2.yaml
@@ -0,0 +1,30 @@
+openapi: 3.0.0
+info:
+  description: myDesc
+  title: myTitle
+  version: 1.0.0
+paths:
+  /widgets:
+    get:
+      operationId: listWidgets
+      parameters:
+        - name: query-param-1
+          in: query
+          allowEmptyValue: true
+          required: false
+          schema:
+            type: string
+        - name: query-param-2
+          in: query
+          style: form
+          explode: true
+          allowEmptyValue: true
+          schema:
+            type: string
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: string
diff --git a/core/src/test/resources/delete_endpoint_1.yaml b/core/src/test/resources/delete_endpoint_1.yaml
new file mode 100644
index 000000000..59a315cd0
--- /dev/null
+++ b/core/src/test/resources/delete_endpoint_1.yaml
@@ -0,0 +1,52 @@
+openapi: 3.0.0
+servers:
+  - url: 'http://petstore.swagger.io/v2'
+info:
+  description: >-
+    This is a sample server Petstore server.  You can find out more about
+    Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
+    #swagger](http://swagger.io/irc/).  For this sample, you can use the api key
+    `special-key` to test the authorization filters.
+  version: 1.0.0
+  title: Swagger Petstore
+  termsOfService: 'http://swagger.io/terms/'
+  contact:
+    email: apiteam@swagger.io
+  license:
+    name: Apache 2.0
+    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
+paths:
+  /pet/{petId}:
+    get:
+      tags:
+        - pet
+      summary: gets a pet by id
+      description: ''
+      operationId: updatePetWithForm
+      parameters:
+        - name: petId
+          in: path
+          description: ID of pet that needs to be updated
+          required: true
+          schema:
+            type: integer
+      responses:
+        '405':
+          description: Invalid input
+  /pet/{petId2}:
+    get:
+      tags:
+        - pet
+      summary: gets a pet by id
+      description: ''
+      operationId: updatePetWithForm
+      parameters:
+        - name: petId2
+          in: path
+          description: ID of pet that needs to be updated
+          required: true
+          schema:
+            type: integer
+      responses:
+        '405':
+          description: Invalid input
diff --git a/core/src/test/resources/delete_endpoint_2.yaml b/core/src/test/resources/delete_endpoint_2.yaml
new file mode 100644
index 000000000..0c544c7b4
--- /dev/null
+++ b/core/src/test/resources/delete_endpoint_2.yaml
@@ -0,0 +1,35 @@
+openapi: 3.0.0
+servers:
+  - url: 'http://petstore.swagger.io/v2'
+info:
+  description: >-
+    This is a sample server Petstore server.  You can find out more about
+    Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
+    #swagger](http://swagger.io/irc/).  For this sample, you can use the api key
+    `special-key` to test the authorization filters.
+  version: 1.0.0
+  title: Swagger Petstore
+  termsOfService: 'http://swagger.io/terms/'
+  contact:
+    email: apiteam@swagger.io
+  license:
+    name: Apache 2.0
+    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
+paths:
+  /pet/{petId}:
+    get:
+      tags:
+        - pet
+      summary: gets a pet by id
+      description: ''
+      operationId: updatePetWithForm
+      parameters:
+        - name: petId
+          in: path
+          description: ID of pet that needs to be updated
+          required: true
+          schema:
+            type: integer
+      responses:
+        '405':
+          description: Invalid input
diff --git a/core/src/test/resources/deprecate_endpoint_1.yaml b/core/src/test/resources/deprecate_endpoint_1.yaml
new file mode 100644
index 000000000..6d08cb721
--- /dev/null
+++ b/core/src/test/resources/deprecate_endpoint_1.yaml
@@ -0,0 +1,52 @@
+openapi: 3.0.0
+servers:
+  - url: 'http://petstore.swagger.io/v2'
+info:
+  description: >-
+    This is a sample server Petstore server.  You can find out more about
+    Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
+    #swagger](http://swagger.io/irc/).  For this sample, you can use the api key
+    `special-key` to test the authorization filters.
+  version: 1.0.0
+  title: Swagger Petstore
+  termsOfService: 'http://swagger.io/terms/'
+  contact:
+    email: apiteam@swagger.io
+  license:
+    name: Apache 2.0
+    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
+paths:
+  /pet/{petId}:
+    get:
+      tags:
+        - pet
+      summary: gets a pet by id
+      description: ''
+      operationId: updatePetWithForm
+      parameters:
+        - name: petId
+          in: path
+          description: ID of pet that needs to be updated
+          required: true
+          schema:
+            type: integer
+      responses:
+        '405':
+          description: Invalid input
+  /pet/{petId2}:
+    post:
+      tags:
+        - pet
+      summary: deletes a pet
+      description: ''
+      operationId: deletePet
+      parameters:
+        - name: petId2
+          in: path
+          description: Pet ID to delete
+          required: true
+          schema:
+            type: integer
+      responses:
+        '405':
+          description: Invalid input
diff --git a/core/src/test/resources/deprecate_endpoint_2.yaml b/core/src/test/resources/deprecate_endpoint_2.yaml
new file mode 100644
index 000000000..95906047e
--- /dev/null
+++ b/core/src/test/resources/deprecate_endpoint_2.yaml
@@ -0,0 +1,53 @@
+openapi: 3.0.0
+servers:
+  - url: 'http://petstore.swagger.io/v2'
+info:
+  description: >-
+    This is a sample server Petstore server.  You can find out more about
+    Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
+    #swagger](http://swagger.io/irc/).  For this sample, you can use the api key
+    `special-key` to test the authorization filters.
+  version: 1.0.0
+  title: Swagger Petstore
+  termsOfService: 'http://swagger.io/terms/'
+  contact:
+    email: apiteam@swagger.io
+  license:
+    name: Apache 2.0
+    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
+paths:
+  /pet/{petId}:
+    get:
+      tags:
+        - pet
+      summary: gets a pet by id
+      description: ''
+      operationId: updatePetWithForm
+      parameters:
+        - name: petId
+          in: path
+          description: ID of pet that needs to be updated
+          required: true
+          schema:
+            type: integer
+      responses:
+        '405':
+          description: Invalid input
+  /pet/{petId2}:
+    post:
+      tags:
+        - pet
+      summary: deletes a pet
+      description: ''
+      operationId: deletePet
+      deprecated: true
+      parameters:
+        - name: petId2
+          in: path
+          description: Pet ID to delete
+          required: true
+          schema:
+            type: integer
+      responses:
+        '405':
+          description: Invalid input
diff --git a/core/src/test/resources/header_1.yaml b/core/src/test/resources/header_1.yaml
deleted file mode 100644
index 66f4a1665..000000000
--- a/core/src/test/resources/header_1.yaml
+++ /dev/null
@@ -1,129 +0,0 @@
-openapi: 3.0.0
-servers:
-  - url: 'http://petstore.swagger.io/v2'
-info:
-  description: >-
-    This is a sample server Petstore server.  You can find out more about
-    Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
-    #swagger](http://swagger.io/irc/).  For this sample, you can use the api key
-    `special-key` to test the authorization filters.
-  version: 1.0.0
-  title: Swagger Petstore
-  termsOfService: 'http://swagger.io/terms/'
-  contact:
-    email: apiteam@swagger.io
-  license:
-    name: Apache 2.0
-    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
-tags:
-  - name: pet
-    description: Everything about your Pets
-    externalDocs:
-      description: Find out more
-      url: 'http://swagger.io'
-  - name: store
-    description: Access to Petstore orders
-  - name: user
-    description: Operations about user
-    externalDocs:
-      description: Find out more about our store
-      url: 'http://swagger.io'
-paths:
-  /user/login:
-    get:
-      tags:
-        - user
-      summary: Logs user into the system
-      description: ''
-      operationId: loginUser
-      parameters:
-        - name: username
-          in: query
-          description: The user name for login
-          required: true
-          schema:
-            type: string
-      responses:
-        '200':
-          description: successful operation
-          headers:
-            X-Rate-Limit:
-              description: calls per hour allowed by the user
-              schema:
-                type: integer
-                format: int32
-            X-Expires-After:
-              description: date in UTC when token expires
-              schema:
-                type: integer
-          content:
-            application/xml:
-              schema:
-                type: integer
-            application/json:
-              schema:
-                type: string
-        '400':
-          description: Invalid username/password supplied
-externalDocs:
-  description: Find out more about Swagger
-  url: 'http://swagger.io'
-components:
-  requestBodies:
-    Pet:
-      content:
-        application/json:
-          schema:
-            $ref: '#/components/schemas/Pet'
-      description: Pet object that needs to be added to the store
-      required: true
-  securitySchemes:
-    petstore_auth:
-      type: oauth2
-      flows:
-        implicit:
-          authorizationUrl: 'http://petstore.swagger.io/oauth/dialog'
-          scopes:
-            'write:pets': modify pets in your account
-            'read:pets': read your pets
-    api_key:
-      type: apiKey
-      name: api_key
-      in: header
-  schemas:
-    Pet:
-      type: object
-      required:
-      - pet_type
-      properties:
-        pet_type:
-          type: string
-      discriminator:
-        propertyName: pet_type
-        mapping:
-          cachorro: Dog
-    Cat:
-      type: object
-      properties:
-        name:
-          type: string
-    Dog:
-      type: object
-      properties:
-        bark:
-          type: string
-    Lizard:
-      type: object
-      properties:
-        lovesRocks:
-          type: boolean
-
-    MyResponseType:
-      oneOf:
-      - $ref: '#/components/schemas/Cat'
-      - $ref: '#/components/schemas/Dog'
-      - $ref: '#/components/schemas/Lizard'
-      discriminator:
-        propertyName: pet_type
-        mapping:
-          dog: '#/components/schemas/Dog'
\ No newline at end of file
diff --git a/core/src/test/resources/header_2.yaml b/core/src/test/resources/header_2.yaml
deleted file mode 100644
index 124b75ef3..000000000
--- a/core/src/test/resources/header_2.yaml
+++ /dev/null
@@ -1,129 +0,0 @@
-openapi: 3.0.0
-servers:
-  - url: 'http://petstore.swagger.io/v2'
-info:
-  description: >-
-    This is a sample server Petstore server.  You can find out more about
-    Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
-    #swagger](http://swagger.io/irc/).  For this sample, you can use the api key
-    `special-key` to test the authorization filters.
-  version: 1.0.0
-  title: Swagger Petstore
-  termsOfService: 'http://swagger.io/terms/'
-  contact:
-    email: apiteam@swagger.io
-  license:
-    name: Apache 2.0
-    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
-tags:
-  - name: pet
-    description: Everything about your Pets
-    externalDocs:
-      description: Find out more
-      url: 'http://swagger.io'
-  - name: store
-    description: Access to Petstore orders
-  - name: user
-    description: Operations about user
-    externalDocs:
-      description: Find out more about our store
-      url: 'http://swagger.io'
-paths:
-  /user/login:
-    get:
-      tags:
-        - user
-      summary: Logs user into the system
-      description: ''
-      operationId: loginUser
-      parameters:
-        - name: username
-          in: query
-          description: The user name for login
-          required: true
-          schema:
-            type: string
-      responses:
-        '200':
-          description: successful operation
-          headers:
-            X-Rate-Limit-New:
-              description: calls per hour allowed by the user
-              schema:
-                type: integer
-                format: int32
-            X-Expires-After:
-              description: date in UTC when token expires
-              schema:
-                type: string
-          content:
-            application/xml:
-              schema:
-                type: integer
-            application/json:
-              schema:
-                type: string
-        '400':
-          description: Invalid username/password supplied
-externalDocs:
-  description: Find out more about Swagger
-  url: 'http://swagger.io'
-components:
-  requestBodies:
-    Pet:
-      content:
-        application/json:
-          schema:
-            $ref: '#/components/schemas/Pet'
-      description: Pet object that needs to be added to the store
-      required: true
-  securitySchemes:
-    petstore_auth:
-      type: oauth2
-      flows:
-        implicit:
-          authorizationUrl: 'http://petstore.swagger.io/oauth/dialog'
-          scopes:
-            'write:pets': modify pets in your account
-            'read:pets': read your pets
-    api_key:
-      type: apiKey
-      name: api_key
-      in: header
-  schemas:
-    Pet:
-      type: object
-      required:
-      - pet_type
-      properties:
-        pet_type:
-          type: string
-      discriminator:
-        propertyName: pet_type
-        mapping:
-          cachorro: Dog
-    Cat:
-      type: object
-      properties:
-        name:
-          type: string
-    Dog:
-      type: object
-      properties:
-        bark:
-          type: string
-    Lizard:
-      type: object
-      properties:
-        lovesRocks:
-          type: boolean
-
-    MyResponseType:
-      oneOf:
-      - $ref: '#/components/schemas/Cat'
-      - $ref: '#/components/schemas/Dog'
-      - $ref: '#/components/schemas/Lizard'
-      discriminator:
-        propertyName: pet_type
-        mapping:
-          dog: '#/components/schemas/Dog'
\ No newline at end of file
diff --git a/core/src/test/resources/issue-666-oas-3-0-examples-handling-1.yaml b/core/src/test/resources/issue-666-oas-3-0-examples-handling-1.yaml
new file mode 100644
index 000000000..041db37f6
--- /dev/null
+++ b/core/src/test/resources/issue-666-oas-3-0-examples-handling-1.yaml
@@ -0,0 +1,126 @@
+openapi: 3.0.2
+info:
+  description: Examples handling
+  title: Examples
+  version: 1.0.0
+paths:
+  /example/request/media-type:
+    post:
+      requestBody:
+        content:
+          application/json:
+            example: simple example
+            schema:
+              type: string
+      responses:
+        '200':
+          description: description
+          content:
+            application/json:
+              schema:
+                type: string
+  /example/response/media-type:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          description: description
+          content:
+            application/json:
+              example: simple example
+              schema:
+                type: string
+  /example/parameter/{id}:
+    post:
+      parameters:
+        - name: id
+          in: path
+          example: example
+          schema:
+            type: string
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          description: description
+          content:
+            application/json:
+              schema:
+                type: string
+  /example/response/header:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          description: description
+          headers:
+            X-Header:
+              example: example
+              schema:
+                type: integer
+                format: int32
+          content:
+            application/json:
+              schema:
+                type: string
+  /example/model/property:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/TestDTO"
+      responses:
+        '200':
+          description: description
+          content:
+            application/json:
+              schema:
+                type: string
+  /example/model/property/composed:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/TestComposedDTO"
+      responses:
+        '200':
+          description: description
+          content:
+            application/json:
+              schema:
+                type: string
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field1:
+          example: example
+          type: string
+    TestDTO2:
+      type: object
+      properties:
+        field2:
+          example: example
+          type: string
+    TestComposedDTO:
+      type: object
+      properties:
+        field1:
+          type: object
+          allOf:
+            - $ref: "#/components/schemas/TestDTO"
+            - $ref: "#/components/schemas/TestDTO2"
\ No newline at end of file
diff --git a/core/src/test/resources/issue-666-oas-3-0-examples-handling-2.yaml b/core/src/test/resources/issue-666-oas-3-0-examples-handling-2.yaml
new file mode 100644
index 000000000..e0d5914a5
--- /dev/null
+++ b/core/src/test/resources/issue-666-oas-3-0-examples-handling-2.yaml
@@ -0,0 +1,126 @@
+openapi: 3.0.2
+info:
+  description: Examples handling
+  title: Examples
+  version: 2.0.0
+paths:
+  /example/request/media-type:
+    post:
+      requestBody:
+        content:
+          application/json:
+            example: simple example updated
+            schema:
+              type: string
+      responses:
+        '200':
+          description: description
+          content:
+            application/json:
+              schema:
+                type: string
+  /example/response/media-type:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          description: description
+          content:
+            application/json:
+              example: simple example updated
+              schema:
+                type: string
+  /example/parameter/{id}:
+    post:
+      parameters:
+        - name: id
+          in: path
+          example: example updated
+          schema:
+            type: string
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          description: description
+          content:
+            application/json:
+              schema:
+                type: string
+  /example/response/header:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          description: description
+          headers:
+            X-Header:
+              example: updated example
+              schema:
+                type: integer
+                format: int32
+          content:
+            application/json:
+              schema:
+                type: string
+  /example/model/property:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/TestDTO"
+      responses:
+        '200':
+          description: description
+          content:
+            application/json:
+              schema:
+                type: string
+  /example/model/property/composed:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/TestComposedDTO"
+      responses:
+        '200':
+          description: description
+          content:
+            application/json:
+              schema:
+                type: string
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field1:
+          example: example updated
+          type: string
+    TestDTO2:
+      type: object
+      properties:
+        field2:
+          example: example updated
+          type: string
+    TestComposedDTO:
+      type: object
+      properties:
+        field1:
+          type: object
+          allOf:
+            - $ref: "#/components/schemas/TestDTO"
+            - $ref: "#/components/schemas/TestDTO2"
\ No newline at end of file
diff --git a/core/src/test/resources/issue-666-oas-3-1-examples-handling-1.yaml b/core/src/test/resources/issue-666-oas-3-1-examples-handling-1.yaml
new file mode 100644
index 000000000..e03ea0090
--- /dev/null
+++ b/core/src/test/resources/issue-666-oas-3-1-examples-handling-1.yaml
@@ -0,0 +1,152 @@
+openapi: 3.1.0
+info:
+  description: Examples handling
+  title: Examples
+  version: 1.0.0
+paths:
+  /example/request/media-type:
+    post:
+      requestBody:
+        content:
+          application/json:
+            example: simple example
+            schema:
+              type: string
+      responses:
+        '200':
+          content:
+            application/json:
+              schema:
+                type: string
+  /examples/request/media-type:
+    post:
+      requestBody:
+        content:
+          application/json:
+            examples:
+              first: example
+              second: example
+            schema:
+              type: string
+      responses:
+        '200':
+          content:
+            application/json:
+              schema:
+                type: string
+  /example/response/media-type:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          content:
+            application/json:
+              example: simple example
+              schema:
+                type: string
+  /examples/response/media-type:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          content:
+            application/json:
+              examples:
+                first: example
+                second: example
+              schema:
+                type: string
+  /example/parameter/{id}:
+    post:
+      parameters:
+        - name: id
+          in: path
+          example: example
+          schema:
+            type: string
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          content:
+            application/json:
+              schema:
+                type: string
+  /examples/parameter/{id}:
+    post:
+      parameters:
+        - name: id
+          in: path
+          examples:
+            first: example
+            second: example
+          schema:
+            type: string
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          content:
+            application/json:
+              schema:
+                type: string
+  /examples/response/header:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          description: description
+          headers:
+            X-Header:
+              examples:
+                first: example
+                second: example
+              schema:
+                type: integer
+                format: int32
+          content:
+            application/json:
+              schema:
+                type: string
+  /examples/model/property:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/TestDTO"
+      responses:
+        '200':
+          description: description
+          content:
+            application/json:
+              schema:
+                type: string
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field1:
+          examples:
+            - first example
+            - second example
+          type: string
\ No newline at end of file
diff --git a/core/src/test/resources/issue-666-oas-3-1-examples-handling-2.yaml b/core/src/test/resources/issue-666-oas-3-1-examples-handling-2.yaml
new file mode 100644
index 000000000..26d11d91d
--- /dev/null
+++ b/core/src/test/resources/issue-666-oas-3-1-examples-handling-2.yaml
@@ -0,0 +1,152 @@
+openapi: 3.1.0
+info:
+  description: Examples handling
+  title: Examples
+  version: 2.0.0
+paths:
+  /example/request/media-type:
+    post:
+      requestBody:
+        content:
+          application/json:
+            example: simple example updated
+            schema:
+              type: string
+      responses:
+        '200':
+          content:
+            application/json:
+              schema:
+                type: string
+  /examples/request/media-type:
+    post:
+      requestBody:
+        content:
+          application/json:
+            examples:
+              first: example updated
+              second: example updated
+            schema:
+              type: string
+      responses:
+        '200':
+          content:
+            application/json:
+              schema:
+                type: string
+  /example/response/media-type:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          content:
+            application/json:
+              example: simple example updated
+              schema:
+                type: string
+  /examples/response/media-type:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          content:
+            application/json:
+              examples:
+                first: example updated
+                second: example updated
+              schema:
+                type: string
+  /example/parameter/{id}:
+    post:
+      parameters:
+        - name: id
+          in: path
+          example: example updated
+          schema:
+            type: string
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          content:
+            application/json:
+              schema:
+                type: string
+  /examples/parameter/{id}:
+    post:
+      parameters:
+        - name: id
+          in: path
+          examples:
+            first: example updated
+            second: example updated
+          schema:
+            type: string
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          content:
+            application/json:
+              schema:
+                type: string
+  /examples/response/header:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: string
+      responses:
+        '200':
+          description: description
+          headers:
+            X-Header:
+              examples:
+                first: example updated
+                second: example updated
+              schema:
+                type: integer
+                format: int32
+          content:
+            application/json:
+              schema:
+                type: string
+  /examples/model/property:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/TestDTO"
+      responses:
+        '200':
+          description: description
+          content:
+            application/json:
+              schema:
+                type: string
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field1:
+          examples:
+            - first example updated
+            - second example updated
+          type: string
\ No newline at end of file
diff --git a/core/src/main/resources/logback.xml b/core/src/test/resources/logback-test.xml
similarity index 100%
rename from core/src/main/resources/logback.xml
rename to core/src/test/resources/logback-test.xml
diff --git a/core/src/test/resources/operationDiff/operation_diff_1.yaml b/core/src/test/resources/operationDiff/operation_diff_1.yaml
new file mode 100644
index 000000000..e0faf2df2
--- /dev/null
+++ b/core/src/test/resources/operationDiff/operation_diff_1.yaml
@@ -0,0 +1,54 @@
+---
+openapi: "3.0.1"
+info:
+  title: "Test title"
+  description: "This is a test metadata"
+  termsOfService: "http://test.com"
+  contact:
+    name: "Mark Snijder"
+    url: "marksnijder.nl"
+    email: "snijderd@gmail.com"
+  license:
+    name: "To be decided"
+    url: "http://test.com"
+  version: "version 1.0"
+paths:
+  /operation/operation-id:
+    get:
+      operationId: operation
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: {}
+  /operation/summary:
+    get:
+      summary: summary
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /operation/description:
+    get:
+      description: description
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /operation/becomes-deprecated:
+    get:
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /operation/becomes-not-deprecated:
+    get:
+      deprecated: true
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
diff --git a/core/src/test/resources/operationDiff/operation_diff_2.yaml b/core/src/test/resources/operationDiff/operation_diff_2.yaml
new file mode 100644
index 000000000..8f5124955
--- /dev/null
+++ b/core/src/test/resources/operationDiff/operation_diff_2.yaml
@@ -0,0 +1,55 @@
+---
+openapi: "3.0.1"
+info:
+  title: "Test title"
+  description: "This is a test metadata"
+  termsOfService: "http://test.com"
+  contact:
+    name: "Mark Snijder"
+    url: "marksnijder.nl"
+    email: "snijderd@gmail.com"
+  license:
+    name: "To be decided"
+    url: "http://test.com"
+  version: "version 1.0"
+paths:
+  /operation/operation-id:
+    get:
+      operationId: changed
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: {}
+  /operation/summary:
+    get:
+      summary: changed
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /operation/description:
+    get:
+      description: changed
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /operation/becomes-deprecated:
+    get:
+      deprecated: true
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /operation/becomes-not-deprecated:
+    get:
+      deprecated: false
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
diff --git a/core/src/test/resources/operation_diff_1.yaml b/core/src/test/resources/operation_diff_1.yaml
deleted file mode 100644
index 0618b58e6..000000000
--- a/core/src/test/resources/operation_diff_1.yaml
+++ /dev/null
@@ -1,24 +0,0 @@
----
-openapi: "3.0.1"
-info:
-  title: "Test title"
-  description: "This is a test metadata"
-  termsOfService: "http://test.com"
-  contact:
-    name: "Mark Snijder"
-    url: "marksnijder.nl"
-    email: "snijderd@gmail.com"
-  license:
-    name: "To be decided"
-    url: "http://test.com"
-  version: "version 1.0"
-paths:
-  /pets/{id}:
-    get:
-      description: Returns a user based on a single ID, if the user does not have access to the pet
-      operationId: operation
-      responses:
-        '200':
-          description: response
-          content:
-            application/json: {}
diff --git a/core/src/test/resources/operation_diff_2.yaml b/core/src/test/resources/operation_diff_2.yaml
deleted file mode 100644
index 8d60a2dc1..000000000
--- a/core/src/test/resources/operation_diff_2.yaml
+++ /dev/null
@@ -1,24 +0,0 @@
----
-openapi: "3.0.1"
-info:
-  title: "Test title"
-  description: "This is a test metadata"
-  termsOfService: "http://test.com"
-  contact:
-    name: "Mark Snijder"
-    url: "marksnijder.nl"
-    email: "snijderd@gmail.com"
-  license:
-    name: "To be decided"
-    url: "http://test.com"
-  version: "version 1.0"
-paths:
-  /pets/{id}:
-    get:
-      description: Returns a user based on a single ID, if the user does not have access to the pet
-      operationId: changed
-      responses:
-        '200':
-          description: response
-          content:
-            application/json: {}
diff --git a/core/src/test/resources/issue-458-integer-limits_1.yaml b/core/src/test/resources/parameterDiff/issue-458-integer-limits_1.yaml
similarity index 100%
rename from core/src/test/resources/issue-458-integer-limits_1.yaml
rename to core/src/test/resources/parameterDiff/issue-458-integer-limits_1.yaml
diff --git a/core/src/test/resources/issue-458-integer-limits_10.yaml b/core/src/test/resources/parameterDiff/issue-458-integer-limits_10.yaml
similarity index 100%
rename from core/src/test/resources/issue-458-integer-limits_10.yaml
rename to core/src/test/resources/parameterDiff/issue-458-integer-limits_10.yaml
diff --git a/core/src/test/resources/issue-458-integer-limits_11.yaml b/core/src/test/resources/parameterDiff/issue-458-integer-limits_11.yaml
similarity index 100%
rename from core/src/test/resources/issue-458-integer-limits_11.yaml
rename to core/src/test/resources/parameterDiff/issue-458-integer-limits_11.yaml
diff --git a/core/src/test/resources/issue-458-integer-limits_12.yaml b/core/src/test/resources/parameterDiff/issue-458-integer-limits_12.yaml
similarity index 100%
rename from core/src/test/resources/issue-458-integer-limits_12.yaml
rename to core/src/test/resources/parameterDiff/issue-458-integer-limits_12.yaml
diff --git a/core/src/test/resources/issue-458-integer-limits_13.yaml b/core/src/test/resources/parameterDiff/issue-458-integer-limits_13.yaml
similarity index 100%
rename from core/src/test/resources/issue-458-integer-limits_13.yaml
rename to core/src/test/resources/parameterDiff/issue-458-integer-limits_13.yaml
diff --git a/core/src/test/resources/issue-458-integer-limits_14.yaml b/core/src/test/resources/parameterDiff/issue-458-integer-limits_14.yaml
similarity index 100%
rename from core/src/test/resources/issue-458-integer-limits_14.yaml
rename to core/src/test/resources/parameterDiff/issue-458-integer-limits_14.yaml
diff --git a/core/src/test/resources/issue-458-integer-limits_15.yaml b/core/src/test/resources/parameterDiff/issue-458-integer-limits_15.yaml
similarity index 100%
rename from core/src/test/resources/issue-458-integer-limits_15.yaml
rename to core/src/test/resources/parameterDiff/issue-458-integer-limits_15.yaml
diff --git a/core/src/test/resources/issue-458-integer-limits_2.yaml b/core/src/test/resources/parameterDiff/issue-458-integer-limits_2.yaml
similarity index 100%
rename from core/src/test/resources/issue-458-integer-limits_2.yaml
rename to core/src/test/resources/parameterDiff/issue-458-integer-limits_2.yaml
diff --git a/core/src/test/resources/issue-458-integer-limits_3.yaml b/core/src/test/resources/parameterDiff/issue-458-integer-limits_3.yaml
similarity index 100%
rename from core/src/test/resources/issue-458-integer-limits_3.yaml
rename to core/src/test/resources/parameterDiff/issue-458-integer-limits_3.yaml
diff --git a/core/src/test/resources/issue-458-integer-limits_4.yaml b/core/src/test/resources/parameterDiff/issue-458-integer-limits_4.yaml
similarity index 100%
rename from core/src/test/resources/issue-458-integer-limits_4.yaml
rename to core/src/test/resources/parameterDiff/issue-458-integer-limits_4.yaml
diff --git a/core/src/test/resources/issue-458-integer-limits_5.yaml b/core/src/test/resources/parameterDiff/issue-458-integer-limits_5.yaml
similarity index 100%
rename from core/src/test/resources/issue-458-integer-limits_5.yaml
rename to core/src/test/resources/parameterDiff/issue-458-integer-limits_5.yaml
diff --git a/core/src/test/resources/issue-458-integer-limits_6.yaml b/core/src/test/resources/parameterDiff/issue-458-integer-limits_6.yaml
similarity index 100%
rename from core/src/test/resources/issue-458-integer-limits_6.yaml
rename to core/src/test/resources/parameterDiff/issue-458-integer-limits_6.yaml
diff --git a/core/src/test/resources/issue-458-integer-limits_7.yaml b/core/src/test/resources/parameterDiff/issue-458-integer-limits_7.yaml
similarity index 100%
rename from core/src/test/resources/issue-458-integer-limits_7.yaml
rename to core/src/test/resources/parameterDiff/issue-458-integer-limits_7.yaml
diff --git a/core/src/test/resources/issue-458-integer-limits_8.yaml b/core/src/test/resources/parameterDiff/issue-458-integer-limits_8.yaml
similarity index 100%
rename from core/src/test/resources/issue-458-integer-limits_8.yaml
rename to core/src/test/resources/parameterDiff/issue-458-integer-limits_8.yaml
diff --git a/core/src/test/resources/issue-458-integer-limits_9.yaml b/core/src/test/resources/parameterDiff/issue-458-integer-limits_9.yaml
similarity index 100%
rename from core/src/test/resources/issue-458-integer-limits_9.yaml
rename to core/src/test/resources/parameterDiff/issue-458-integer-limits_9.yaml
diff --git a/core/src/test/resources/parameterDiff/issue-488-1.json b/core/src/test/resources/parameterDiff/issue-488-1.json
new file mode 100644
index 000000000..22e0009dd
--- /dev/null
+++ b/core/src/test/resources/parameterDiff/issue-488-1.json
@@ -0,0 +1,98 @@
+{
+  "openapi": "3.0.1",
+  "info": {
+    "title": "Test-API",
+    "description": "Testdescription",
+    "version": "v1"
+  },
+  "paths": {
+    "/api/v1/test": {
+      "get": {
+        "tags": [
+          "TestTag"
+        ],
+        "summary": "Retrieve a list Test objects",
+        "description": "Usage with testId parameter is recommended.",
+        "parameters": [
+          {
+            "name": "testId",
+            "in": "query",
+            "description": "rename of prop before",
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "dateFrom",
+            "in": "query",
+            "description": "Searches documents with creation date equal or younger specified timestamp",
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "dateTo",
+            "in": "query",
+            "description": "Searches documents with creation date equal or older than specified timestamp",
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/TestDTO"
+                  }
+                }
+              }
+            }
+          },
+          "401": {
+            "description": "Unauthorized"
+          }
+        }
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "TestDTO": {
+        "type": "object",
+        "properties": {
+          "Id": {
+            "type": "string",
+            "nullable": true
+          },
+          "Timestamp": {
+            "type": "string",
+            "format": "date-time"
+          },
+          "Test": {
+            "type": "string",
+            "nullable": true
+          }
+        },
+        "additionalProperties": false
+      }
+    },
+    "securitySchemes": {
+      "BearerAuth": {
+        "type": "apiKey",
+        "description": "Fill in your acquired bearer token here, must be like 'Bearer TOKEN_HERE'",
+        "name": "Authorization",
+        "in": "header"
+      }
+    }
+  },
+  "security": [
+    {
+      "BearerAuth": [ ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/core/src/test/resources/parameterDiff/issue-488-2.json b/core/src/test/resources/parameterDiff/issue-488-2.json
new file mode 100644
index 000000000..463e210c7
--- /dev/null
+++ b/core/src/test/resources/parameterDiff/issue-488-2.json
@@ -0,0 +1,98 @@
+{
+  "openapi": "3.0.1",
+  "info": {
+    "title": "Test-API",
+    "description": "Testdescription",
+    "version": "v1"
+  },
+  "paths": {
+    "/api/v1/test": {
+      "get": {
+        "tags": [
+          "TestTag"
+        ],
+        "summary": "Retrieve a list Test objects",
+        "description": "Usage with testId parameter is recommended.",
+        "parameters": [
+          {
+            "name": "testIdWillBreak",
+            "in": "query",
+            "description": "rename of prop after",
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "dateFrom",
+            "in": "query",
+            "description": "Searches documents with creation date equal or younger specified timestamp",
+            "schema": {
+              "type": "string"
+            }
+          },
+          {
+            "name": "dateTo",
+            "in": "query",
+            "description": "Searches documents with creation date equal or older than specified timestamp",
+            "schema": {
+              "type": "string"
+            }
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "OK",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/TestDTO"
+                  }
+                }
+              }
+            }
+          },
+          "401": {
+            "description": "Unauthorized"
+          }
+        }
+      }
+    }
+  },
+  "components": {
+    "schemas": {
+      "TestDTO": {
+        "type": "object",
+        "properties": {
+          "Id": {
+            "type": "string",
+            "nullable": true
+          },
+          "Timestamp": {
+            "type": "string",
+            "format": "date-time"
+          },
+          "Test": {
+            "type": "string",
+            "nullable": true
+          }
+        },
+        "additionalProperties": false
+      }
+    },
+    "securitySchemes": {
+      "BearerAuth": {
+        "type": "apiKey",
+        "description": "Fill in your acquired bearer token here, must be like 'Bearer TOKEN_HERE'",
+        "name": "Authorization",
+        "in": "header"
+      }
+    }
+  },
+  "security": [
+    {
+      "BearerAuth": [ ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/core/src/test/resources/parameterDiff/parameter_diff_1.yaml b/core/src/test/resources/parameterDiff/parameter_diff_1.yaml
new file mode 100644
index 000000000..c17217338
--- /dev/null
+++ b/core/src/test/resources/parameterDiff/parameter_diff_1.yaml
@@ -0,0 +1,102 @@
+openapi: "3.1.0"
+info:
+  title: "Parameters diff test"
+  description: "TParameters diff test"
+  version: "1.0"
+paths:
+  /parameter/added:
+    get:
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /parameter/removed:
+    get:
+      parameters:
+        - in: query
+          name: param
+          schema:
+            type: string
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /parameter/becomes-deprecated:
+    get:
+      parameters:
+        - in: header
+          name: X-Header
+          schema:
+            type: string
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /parameter/becomes-not-deprecated:
+    get:
+      parameters:
+        - in: header
+          name: X-Header
+          deprecated: true
+          schema:
+            type: string
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /parameter/required:
+    get:
+      parameters:
+        - in: query
+          name: param
+          required: true
+          schema:
+            type: string
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /parameter/description:
+    get:
+      parameters:
+        - in: query
+          name: param
+          description: description
+          schema:
+            type: string
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /parameter/explode:
+    get:
+      parameters:
+        - in: query
+          name: param
+          schema:
+            type: string
+          explode: true
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /parameter/style:
+    get:
+      parameters:
+        - in: query
+          name: param
+          schema:
+            type: string
+          style: simple
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
\ No newline at end of file
diff --git a/core/src/test/resources/parameterDiff/parameter_diff_2.yaml b/core/src/test/resources/parameterDiff/parameter_diff_2.yaml
new file mode 100644
index 000000000..0c30b6b1d
--- /dev/null
+++ b/core/src/test/resources/parameterDiff/parameter_diff_2.yaml
@@ -0,0 +1,102 @@
+openapi: "3.1.0"
+info:
+  title: "Parameters diff test"
+  description: "TParameters diff test"
+  version: "1.0"
+paths:
+  /parameter/added:
+    get:
+      parameters:
+        - in: query
+          name: param
+          schema:
+            type: string
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: {}
+  /parameter/removed:
+    get:
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /parameter/becomes-deprecated:
+    get:
+      parameters:
+        - in: header
+          name: X-Header
+          deprecated: true
+          schema:
+            type: string
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /parameter/becomes-not-deprecated:
+    get:
+      parameters:
+        - in: header
+          name: X-Header
+          schema:
+            type: string
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /parameter/required:
+    get:
+      parameters:
+        - in: query
+          name: param
+          required: false
+          schema:
+            type: string
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /parameter/description:
+    get:
+      parameters:
+        - in: query
+          name: param
+          description: changed
+          schema:
+            type: string
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /parameter/explode:
+    get:
+      parameters:
+        - in: query
+          name: param
+          schema:
+            type: string
+          explode: false
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
+  /parameter/style:
+    get:
+      parameters:
+        - in: query
+          name: param
+          schema:
+            type: string
+          style: matrix
+      responses:
+        '200':
+          description: response
+          content:
+            application/json: { }
\ No newline at end of file
diff --git a/core/src/test/resources/parameters_overloading.yaml b/core/src/test/resources/parameterDiff/parameters_overloading.yaml
similarity index 56%
rename from core/src/test/resources/parameters_overloading.yaml
rename to core/src/test/resources/parameterDiff/parameters_overloading.yaml
index bd3bee96c..061444451 100644
--- a/core/src/test/resources/parameters_overloading.yaml
+++ b/core/src/test/resources/parameterDiff/parameters_overloading.yaml
@@ -3,6 +3,21 @@ info:
   title: Projects API
   version: 1.0.0
 paths:
+  /projects/{key}:
+    get:
+      parameters:
+        - in: path
+          name: key
+          required: true
+          schema:
+            type: string
+      responses:
+        '200':
+          description: 'Success'
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SampleResponse'
   /projects/{id}:
     get:
       parameters:
@@ -35,6 +50,26 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/SampleResponse'
+  /projects/{id}.{idPostfix}:
+    get:
+      parameters:
+        - in: path
+          name: id
+          required: true
+          schema:
+            type: string
+        - in: path
+          name: idPostfix
+          required: true
+          schema:
+            type: string
+      responses:
+        '200':
+          description: 'Success'
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SampleResponse'
 components:
   schemas:
     SampleResponse:
diff --git a/core/src/test/resources/parameters_overloading_2.yaml b/core/src/test/resources/parameterDiff/parameters_overloading_2.yaml
similarity index 100%
rename from core/src/test/resources/parameters_overloading_2.yaml
rename to core/src/test/resources/parameterDiff/parameters_overloading_2.yaml
diff --git a/core/src/test/resources/path_parameter_diff_param_name_diff_new.yaml b/core/src/test/resources/parameterDiff/path_parameter_diff_param_name_diff_new.yaml
similarity index 100%
rename from core/src/test/resources/path_parameter_diff_param_name_diff_new.yaml
rename to core/src/test/resources/parameterDiff/path_parameter_diff_param_name_diff_new.yaml
diff --git a/core/src/test/resources/path_parameter_diff_param_name_diff_old.yaml b/core/src/test/resources/parameterDiff/path_parameter_diff_param_name_diff_old.yaml
similarity index 100%
rename from core/src/test/resources/path_parameter_diff_param_name_diff_old.yaml
rename to core/src/test/resources/parameterDiff/path_parameter_diff_param_name_diff_old.yaml
diff --git a/core/src/test/resources/path_parameter_diff_param_schema_diff_new.yaml b/core/src/test/resources/parameterDiff/path_parameter_diff_param_schema_diff_new.yaml
similarity index 100%
rename from core/src/test/resources/path_parameter_diff_param_schema_diff_new.yaml
rename to core/src/test/resources/parameterDiff/path_parameter_diff_param_schema_diff_new.yaml
diff --git a/core/src/test/resources/path_parameter_diff_param_schema_diff_old.yaml b/core/src/test/resources/parameterDiff/path_parameter_diff_param_schema_diff_old.yaml
similarity index 100%
rename from core/src/test/resources/path_parameter_diff_param_schema_diff_old.yaml
rename to core/src/test/resources/parameterDiff/path_parameter_diff_param_schema_diff_old.yaml
diff --git a/core/src/test/resources/parameters_diff.yaml b/core/src/test/resources/parameters_diff.yaml
deleted file mode 100644
index 97cc8e9b9..000000000
--- a/core/src/test/resources/parameters_diff.yaml
+++ /dev/null
@@ -1,185 +0,0 @@
-openapi: 3.0.0
-servers:
-  - url: 'http://petstore.swagger.io/v2'
-info:
-  description: >-
-    This is a sample server Petstore server.  You can find out more about
-    Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
-    #swagger](http://swagger.io/irc/).  For this sample, you can use the api key
-    `special-key` to test the authorization filters.
-  version: 1.0.0
-  title: Swagger Petstore
-  termsOfService: 'http://swagger.io/terms/'
-  contact:
-    email: apiteam@swagger.io
-  license:
-    name: Apache 2.0
-    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
-tags:
-  - name: pet
-    description: Everything about your Pets
-    externalDocs:
-      description: Find out more
-      url: 'http://swagger.io'
-  - name: store
-    description: Access to Petstore orders
-  - name: user
-    description: Operations about user
-    externalDocs:
-      description: Find out more about our store
-      url: 'http://swagger.io'
-paths:
-  '/pet/{petId}':
-    parameters:
-      - name: newHeaderParam
-        in: header
-        required: false
-        schema:
-          type: integer
-    delete:
-      tags:
-        - pet
-      summary: Deletes a pet
-      description: ''
-      operationId: deletePet
-      parameters:
-        - name: api_key
-          in: header
-          required: false
-          schema:
-            type: string
-        - name: newHeaderParam
-          in: header
-          required: false
-          schema:
-            type: string
-        - name: petId
-          in: path
-          description: Pet id to delete
-          required: true
-          schema:
-            type: integer
-            format: int64
-      responses:
-        '400':
-          description: Invalid ID supplied
-        '404':
-          description: Pet not found
-  /pet:
-    post:
-      tags:
-        - pet
-      summary: Add a new pet to the store
-      description: ''
-      operationId: addPet
-      responses:
-        '405':
-          description: Invalid input
-      requestBody:
-        $ref: '#/components/requestBodies/Pet'
-  /pet/findByStatus2:
-    get:
-      tags:
-        - pet
-      summary: Finds Pets by status
-      description: Multiple status values can be provided with comma separated strings
-      operationId: findPetsByStatus
-      parameters:
-        - name: status
-          in: query
-          deprecated: true
-          description: Status values that need to be considered for filter
-          required: true
-          explode: true
-          schema:
-            type: array
-            items:
-              type: string
-              enum:
-                - available
-                - pending
-                - sold
-              default: available
-      responses:
-        '200':
-          description: successful operation
-          content:
-            application/xml:
-              schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/Pet'
-            application/json:
-              schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/Pet'
-        '400':
-          description: Invalid status value
-externalDocs:
-  description: Find out more about Swagger
-  url: 'http://swagger.io'
-components:
-  requestBodies:
-    Pet:
-      content:
-        application/json:
-          schema:
-            $ref: '#/components/schemas/Pet'
-        application/xml:
-          schema:
-            $ref: '#/components/schemas/Pet'
-      description: Pet object that needs to be added to the store
-      required: true
-  schemas:
-    Tag:
-      type: object
-      properties:
-        id:
-          type: integer
-          format: int64
-        name:
-          type: string
-      xml:
-        name: Tag
-    Pet:
-      type: object
-      required:
-        - name
-        - photoUrls
-      properties:
-        id:
-          type: integer
-          format: int64
-        category:
-          type: string
-        name:
-          type: string
-          example: doggie
-        newField:
-          type: string
-          example: a field demo
-          description: a field demo
-        photoUrls:
-          type: array
-          xml:
-            name: photoUrl
-            wrapped: true
-          items:
-            type: string
-        tags:
-          type: array
-          xml:
-            name: tag
-            wrapped: true
-          items:
-            $ref: '#/components/schemas/Tag'
-        status:
-          type: string
-          description: pet status in the store
-          enum:
-            - available
-            - pending
-            - sold
-      xml:
-        name: Pet
\ No newline at end of file
diff --git a/core/src/test/resources/parameters_diff_1.yaml b/core/src/test/resources/parameters_diff_1.yaml
deleted file mode 100644
index 97cc8e9b9..000000000
--- a/core/src/test/resources/parameters_diff_1.yaml
+++ /dev/null
@@ -1,185 +0,0 @@
-openapi: 3.0.0
-servers:
-  - url: 'http://petstore.swagger.io/v2'
-info:
-  description: >-
-    This is a sample server Petstore server.  You can find out more about
-    Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
-    #swagger](http://swagger.io/irc/).  For this sample, you can use the api key
-    `special-key` to test the authorization filters.
-  version: 1.0.0
-  title: Swagger Petstore
-  termsOfService: 'http://swagger.io/terms/'
-  contact:
-    email: apiteam@swagger.io
-  license:
-    name: Apache 2.0
-    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
-tags:
-  - name: pet
-    description: Everything about your Pets
-    externalDocs:
-      description: Find out more
-      url: 'http://swagger.io'
-  - name: store
-    description: Access to Petstore orders
-  - name: user
-    description: Operations about user
-    externalDocs:
-      description: Find out more about our store
-      url: 'http://swagger.io'
-paths:
-  '/pet/{petId}':
-    parameters:
-      - name: newHeaderParam
-        in: header
-        required: false
-        schema:
-          type: integer
-    delete:
-      tags:
-        - pet
-      summary: Deletes a pet
-      description: ''
-      operationId: deletePet
-      parameters:
-        - name: api_key
-          in: header
-          required: false
-          schema:
-            type: string
-        - name: newHeaderParam
-          in: header
-          required: false
-          schema:
-            type: string
-        - name: petId
-          in: path
-          description: Pet id to delete
-          required: true
-          schema:
-            type: integer
-            format: int64
-      responses:
-        '400':
-          description: Invalid ID supplied
-        '404':
-          description: Pet not found
-  /pet:
-    post:
-      tags:
-        - pet
-      summary: Add a new pet to the store
-      description: ''
-      operationId: addPet
-      responses:
-        '405':
-          description: Invalid input
-      requestBody:
-        $ref: '#/components/requestBodies/Pet'
-  /pet/findByStatus2:
-    get:
-      tags:
-        - pet
-      summary: Finds Pets by status
-      description: Multiple status values can be provided with comma separated strings
-      operationId: findPetsByStatus
-      parameters:
-        - name: status
-          in: query
-          deprecated: true
-          description: Status values that need to be considered for filter
-          required: true
-          explode: true
-          schema:
-            type: array
-            items:
-              type: string
-              enum:
-                - available
-                - pending
-                - sold
-              default: available
-      responses:
-        '200':
-          description: successful operation
-          content:
-            application/xml:
-              schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/Pet'
-            application/json:
-              schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/Pet'
-        '400':
-          description: Invalid status value
-externalDocs:
-  description: Find out more about Swagger
-  url: 'http://swagger.io'
-components:
-  requestBodies:
-    Pet:
-      content:
-        application/json:
-          schema:
-            $ref: '#/components/schemas/Pet'
-        application/xml:
-          schema:
-            $ref: '#/components/schemas/Pet'
-      description: Pet object that needs to be added to the store
-      required: true
-  schemas:
-    Tag:
-      type: object
-      properties:
-        id:
-          type: integer
-          format: int64
-        name:
-          type: string
-      xml:
-        name: Tag
-    Pet:
-      type: object
-      required:
-        - name
-        - photoUrls
-      properties:
-        id:
-          type: integer
-          format: int64
-        category:
-          type: string
-        name:
-          type: string
-          example: doggie
-        newField:
-          type: string
-          example: a field demo
-          description: a field demo
-        photoUrls:
-          type: array
-          xml:
-            name: photoUrl
-            wrapped: true
-          items:
-            type: string
-        tags:
-          type: array
-          xml:
-            name: tag
-            wrapped: true
-          items:
-            $ref: '#/components/schemas/Tag'
-        status:
-          type: string
-          description: pet status in the store
-          enum:
-            - available
-            - pending
-            - sold
-      xml:
-        name: Pet
\ No newline at end of file
diff --git a/core/src/test/resources/parameters_diff_2.yaml b/core/src/test/resources/parameters_diff_2.yaml
deleted file mode 100644
index a4e38e85d..000000000
--- a/core/src/test/resources/parameters_diff_2.yaml
+++ /dev/null
@@ -1,183 +0,0 @@
-openapi: 3.0.0
-servers:
-  - url: 'http://petstore.swagger.io/v2'
-info:
-  description: >-
-    This is a sample server Petstore server.  You can find out more about
-    Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
-    #swagger](http://swagger.io/irc/).  For this sample, you can use the api key
-    `special-key` to test the authorization filters.
-  version: 2.0.0
-  title: Swagger Petstore
-  termsOfService: 'http://swagger.io/terms/'
-  contact:
-    email: apiteam@swagger.io
-  license:
-    name: Apache 2.0
-    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
-tags:
-  - name: pet
-    description: Everything about your Pets
-    externalDocs:
-      description: Find out more
-      url: 'http://swagger.io'
-  - name: store
-    description: Access to Petstore orders
-  - name: user
-    description: Operations about user
-    externalDocs:
-      description: Find out more about our store
-      url: 'http://swagger.io'
-paths:
-  '/pet/{petId}':
-    delete:
-      tags:
-        - pet
-      summary: Deletes a pet
-      description: ''
-      operationId: deletePet
-      parameters:
-        - name: api_key
-          in: header
-          required: false
-          schema:
-            type: string
-        - name: petId
-          in: path
-          description: Pet id to delete
-          required: true
-          schema:
-            type: integer
-            format: int64
-      responses:
-        '400':
-          description: Invalid ID supplied
-        '404':
-          description: Pet not found
-  /pet:
-    post:
-      tags:
-        - pet
-      summary: Add a new pet to the store
-      description: ''
-      operationId: addPet
-      parameters:
-        - name: tags
-          in: query
-          description: add new query param demo
-          required: true
-          explode: true
-          schema:
-            type: array
-            items:
-              type: string
-      responses:
-        '405':
-          description: Invalid input
-      requestBody:
-        $ref: '#/components/requestBodies/Pet'
-  /pet/findByStatus2:
-    get:
-      tags:
-        - pet
-      summary: Finds Pets by status
-      description: Multiple status values can be provided with comma separated strings
-      operationId: findPetsByStatus
-      parameters:
-        - name: status
-          in: query
-          description: Status values that need to be considered for filter
-          required: true
-          explode: true
-          schema:
-            type: array
-            items:
-              type: string
-              enum:
-                - available
-                - pending
-                - sold
-              default: available
-      responses:
-        '200':
-          description: successful operation
-          content:
-            application/xml:
-              schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/Pet'
-            application/json:
-              schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/Pet'
-        '400':
-          description: Invalid status value
-externalDocs:
-  description: Find out more about Swagger
-  url: 'http://swagger.io'
-components:
-  requestBodies:
-    Pet:
-      content:
-        application/json:
-          schema:
-            $ref: '#/components/schemas/Pet'
-        application/xml:
-          schema:
-            $ref: '#/components/schemas/Pet'
-      description: Pet object that needs to be added to the store
-      required: true
-  schemas:
-    Tag:
-      type: object
-      properties:
-        id:
-          type: integer
-          format: int64
-        name:
-          type: string
-      xml:
-        name: Tag
-    Pet:
-      type: object
-      required:
-        - name
-        - photoUrls
-      properties:
-        id:
-          type: integer
-          format: int64
-        category:
-          type: string
-        name:
-          type: string
-          example: doggie
-        newField:
-          type: string
-          example: a field demo
-          description: a field demo
-        photoUrls:
-          type: array
-          xml:
-            name: photoUrl
-            wrapped: true
-          items:
-            type: string
-        tags:
-          type: array
-          xml:
-            name: tag
-            wrapped: true
-          items:
-            $ref: '#/components/schemas/Tag'
-        status:
-          type: string
-          description: pet status in the store
-          enum:
-            - available
-            - pending
-            - sold
-      xml:
-        name: Pet
\ No newline at end of file
diff --git a/core/src/test/resources/recursive_model_1.yaml b/core/src/test/resources/recursive_model_1.yaml
index 24f545186..88742b135 100644
--- a/core/src/test/resources/recursive_model_1.yaml
+++ b/core/src/test/resources/recursive_model_1.yaml
@@ -25,6 +25,17 @@ components:
           type: string
         message2:
           type: string
+        recursiveDirect:
+          $ref: '#/components/schemas/B'
+        recursiveAllOf:
+          allOf:
+            - $ref: '#/components/schemas/B'
+        recursiveOneOf:
+          oneOf:
+            - $ref: '#/components/schemas/B'
+        recursiveAnyOf:
+          anyOf:
+            - $ref: '#/components/schemas/B'
         details:
           type: array
           items:
diff --git a/core/src/test/resources/responseHeaderDiff/response_header_1.yaml b/core/src/test/resources/responseHeaderDiff/response_header_1.yaml
new file mode 100644
index 000000000..d668deb9a
--- /dev/null
+++ b/core/src/test/resources/responseHeaderDiff/response_header_1.yaml
@@ -0,0 +1,64 @@
+openapi: 3.1.0
+info:
+  description: Response headers handling
+  title: response headers
+  version: 1.0.0
+paths:
+  /response/headers/deprecated:
+    get:
+      responses:
+        '200':
+          description: some description
+          headers:
+            x-header-becomes-deprecated:
+              schema:
+                type: string
+            x-header-becomes-not-deprecated:
+              deprecated: true
+              schema:
+                type: string
+          content:
+            application/json: { }
+  /response/headers/description:
+    get:
+      responses:
+        '200':
+          description: some description
+          headers:
+            x-header-description-changed:
+              description: old description
+              schema:
+                type: string
+            x-header-description-added:
+              schema:
+                type: string
+            x-header-description-removed:
+              description: old description
+              schema:
+                type: string
+          content:
+            application/json: { }
+  /response/headers/required:
+    get:
+      responses:
+        '200':
+          description: some description
+          headers:
+            x-header-required-changed:
+              required: true
+              schema:
+                type: string
+          content:
+            application/json: { }
+  /response/headers/explode:
+    get:
+      responses:
+        '200':
+          description: some description
+          headers:
+            x-header-explode-changed:
+              explode: false
+              schema:
+                type: string
+          content:
+            application/json: { }
\ No newline at end of file
diff --git a/core/src/test/resources/responseHeaderDiff/response_header_2.yaml b/core/src/test/resources/responseHeaderDiff/response_header_2.yaml
new file mode 100644
index 000000000..fc2175233
--- /dev/null
+++ b/core/src/test/resources/responseHeaderDiff/response_header_2.yaml
@@ -0,0 +1,64 @@
+openapi: 3.1.0
+info:
+  description: Response headers handling
+  title: response headers
+  version: 1.0.0
+paths:
+  /response/headers/deprecated:
+    get:
+      responses:
+        '200':
+          description: some description
+          headers:
+            x-header-becomes-deprecated:
+              deprecated: true
+              schema:
+                type: string
+            x-header-becomes-not-deprecated:
+              schema:
+                type: string
+          content:
+            application/json: {}
+  /response/headers/description:
+    get:
+      responses:
+        '200':
+          description: some description
+          headers:
+            x-header-description-changed:
+              description: new description
+              schema:
+                type: string
+            x-header-description-added:
+              description: added description
+              schema:
+                type: string
+            x-header-description-removed:
+              schema:
+                type: string
+          content:
+            application/json: { }
+  /response/headers/required:
+    get:
+      responses:
+        '200':
+          description: some description
+          headers:
+            x-header-required-changed:
+              required: false
+              schema:
+                type: string
+          content:
+            application/json: { }
+  /response/headers/explode:
+    get:
+      responses:
+        '200':
+          description: some description
+          headers:
+            x-header-explode-changed:
+              explode: true
+              schema:
+                type: string
+          content:
+            application/json: { }
\ No newline at end of file
diff --git a/core/src/test/resources/schemaDiff/allOf-diff-1.yaml b/core/src/test/resources/schemaDiff/allOf-diff-1.yaml
new file mode 100644
index 000000000..9351c8325
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/allOf-diff-1.yaml
@@ -0,0 +1,35 @@
+openapi: 3.0.0
+info:
+  title: AllOf Diff Test - Version 1
+  version: 1.0.0
+paths:
+  /allof/test:
+    post:
+      summary: Test endpoint for allOf diff
+      requestBody:
+        required: true
+        content:
+          application/json:
+            schema:
+              allOf:
+                - $ref: '#/components/schemas/TypeA'
+                - $ref: '#/components/schemas/TypeB'
+      responses:
+        '200':
+          description: OK
+components:
+  schemas:
+    TypeA:
+      type: object
+      required:
+        - fieldA
+      properties:
+        fieldA:
+          type: string
+        commonField:
+          type: integer
+    TypeB:
+      type: object
+      properties:
+        fieldB:
+          type: boolean
diff --git a/core/src/test/resources/schemaDiff/allOf-diff-2.yaml b/core/src/test/resources/schemaDiff/allOf-diff-2.yaml
new file mode 100644
index 000000000..d3f808e72
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/allOf-diff-2.yaml
@@ -0,0 +1,34 @@
+openapi: 3.0.0
+info:
+  title: AllOf Diff Test - Version 2
+  version: 1.0.0
+paths:
+  /allof/test:
+    post:
+      summary: Test endpoint for allOf diff
+      requestBody:
+        required: true
+        content:
+          application/json:
+            schema:
+              allOf:
+                - $ref: '#/components/schemas/TypeA'
+                - $ref: '#/components/schemas/TypeC'
+      responses:
+        '200':
+          description: OK
+components:
+  schemas:
+    TypeA:
+      type: object
+      # fieldA is no longer required here
+      properties:
+        fieldA:
+          type: string
+        commonField:
+          type: integer
+    TypeC:
+      type: object
+      properties:
+        fieldC:
+          type: number
diff --git a/core/src/test/resources/schemaDiff/anyOf-diff-1.yaml b/core/src/test/resources/schemaDiff/anyOf-diff-1.yaml
new file mode 100644
index 000000000..4420283ef
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/anyOf-diff-1.yaml
@@ -0,0 +1,35 @@
+openapi: 3.0.0
+info:
+  title: AnyOf Diff Test - Version 1
+  version: 1.0.0
+paths:
+  /anyof/test:
+    post:
+      summary: Test endpoint for anyOf diff
+      requestBody:
+        required: true
+        content:
+          application/json:
+            schema:
+              anyOf:
+                - $ref: '#/components/schemas/TypeA'
+                - $ref: '#/components/schemas/TypeB'
+      responses:
+        '200':
+          description: OK
+components:
+  schemas:
+    TypeA:
+      type: object
+      properties:
+        fieldA:
+          type: string
+        commonField:
+          type: integer
+      required:
+        - fieldA
+    TypeB:
+      type: object
+      properties:
+        fieldB:
+          type: boolean
diff --git a/core/src/test/resources/schemaDiff/anyOf-diff-2.yaml b/core/src/test/resources/schemaDiff/anyOf-diff-2.yaml
new file mode 100644
index 000000000..4991cf45f
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/anyOf-diff-2.yaml
@@ -0,0 +1,33 @@
+openapi: 3.0.0
+info:
+  title: AnyOf Diff Test - Version 2
+  version: 1.0.0
+paths:
+  /anyof/test:
+    post:
+      summary: Test endpoint for anyOf diff
+      requestBody:
+        required: true
+        content:
+          application/json:
+            schema:
+              anyOf:
+                - $ref: '#/components/schemas/TypeA'
+                - $ref: '#/components/schemas/TypeC'
+      responses:
+        '200':
+          description: OK
+components:
+  schemas:
+    TypeA:
+      type: object
+      properties:
+        fieldA:
+          type: string
+        commonField:
+          type: integer
+    TypeC:
+      type: object
+      properties:
+        fieldC:
+          type: number
diff --git a/core/src/test/resources/schemaDiff/required-property-1.yaml b/core/src/test/resources/schemaDiff/required-property-1.yaml
new file mode 100644
index 000000000..5a1cb48be
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/required-property-1.yaml
@@ -0,0 +1,39 @@
+openapi: 3.0.0
+info:
+  title: Required Property Test API
+  version: 1.0.0
+paths:
+  /schema/required:
+    post:
+      requestBody:
+        required: true
+        content:
+          application/json:
+            schema:
+              type: object
+              required: [becomesOptional, unchanged]
+              properties:
+                becomesRequired:
+                  type: string
+                  description: Property that changes from optional to required (breaking for requests)
+                becomesOptional:
+                  type: string
+                  description: Property that changes from required to optional (breaking for responses)
+                unchanged:
+                  type: string
+                  description: Property that remains unchanged in terms of required status
+      responses:
+        '200':
+          description: Success response
+          content:
+            application/json:
+              schema:
+                type: object
+                required: [becomesOptional, unchanged]
+                properties:
+                  becomesRequired:
+                    type: string
+                  becomesOptional:
+                    type: string
+                  unchanged:
+                    type: string
\ No newline at end of file
diff --git a/core/src/test/resources/schemaDiff/required-property-2.yaml b/core/src/test/resources/schemaDiff/required-property-2.yaml
new file mode 100644
index 000000000..7a865eea6
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/required-property-2.yaml
@@ -0,0 +1,39 @@
+openapi: 3.0.0
+info:
+  title: Required Property Test API
+  version: 1.0.0
+paths:
+  /schema/required:
+    post:
+      requestBody:
+        required: true
+        content:
+          application/json:
+            schema:
+              type: object
+              required: [becomesRequired, unchanged]
+              properties:
+                becomesRequired:
+                  type: string
+                  description: Property that changes from optional to required (breaking for requests)
+                becomesOptional:
+                  type: string
+                  description: Property that changes from required to optional (breaking for responses)
+                unchanged:
+                  type: string
+                  description: Property that remains unchanged in terms of required status
+      responses:
+        '200':
+          description: Success response
+          content:
+            application/json:
+              schema:
+                type: object
+                required: [becomesRequired, unchanged]
+                properties:
+                  becomesRequired:
+                    type: string
+                  becomesOptional:
+                    type: string
+                  unchanged:
+                    type: string
\ No newline at end of file
diff --git a/core/src/test/resources/add-prop-1.yaml b/core/src/test/resources/schemaDiff/schema-add-property-1.yaml
similarity index 100%
rename from core/src/test/resources/add-prop-1.yaml
rename to core/src/test/resources/schemaDiff/schema-add-property-1.yaml
diff --git a/core/src/test/resources/add-prop-2.yaml b/core/src/test/resources/schemaDiff/schema-add-property-2.yaml
similarity index 100%
rename from core/src/test/resources/add-prop-2.yaml
rename to core/src/test/resources/schemaDiff/schema-add-property-2.yaml
diff --git a/core/src/test/resources/add-prop-put-1.yaml b/core/src/test/resources/schemaDiff/schema-add-property-put-1.yaml
similarity index 100%
rename from core/src/test/resources/add-prop-put-1.yaml
rename to core/src/test/resources/schemaDiff/schema-add-property-put-1.yaml
diff --git a/core/src/test/resources/add-prop-put-2.yaml b/core/src/test/resources/schemaDiff/schema-add-property-put-2.yaml
similarity index 100%
rename from core/src/test/resources/add-prop-put-2.yaml
rename to core/src/test/resources/schemaDiff/schema-add-property-put-2.yaml
diff --git a/core/src/test/resources/issue-256_1.json b/core/src/test/resources/schemaDiff/schema-additional-properties-1.json
similarity index 100%
rename from core/src/test/resources/issue-256_1.json
rename to core/src/test/resources/schemaDiff/schema-additional-properties-1.json
diff --git a/core/src/test/resources/issue-256_2.json b/core/src/test/resources/schemaDiff/schema-additional-properties-2.json
similarity index 100%
rename from core/src/test/resources/issue-256_2.json
rename to core/src/test/resources/schemaDiff/schema-additional-properties-2.json
diff --git a/core/src/test/resources/schemaDiff/schema-deprecated-handling-1.yaml b/core/src/test/resources/schemaDiff/schema-deprecated-handling-1.yaml
new file mode 100644
index 000000000..48dcd021e
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-deprecated-handling-1.yaml
@@ -0,0 +1,33 @@
+openapi: 3.1.0
+info:
+  description: Schema deprecated handling
+  title: defaults
+  version: 1.0.0
+paths:
+  /schema-diff/deprecated/added:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/DeprecatedAdded"
+  /schema-diff/deprecated/removed:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/DeprecatedRemoved"
+components:
+  schemas:
+    DeprecatedAdded:
+      type: object
+      properties:
+        field1:
+          type: string
+    DeprecatedRemoved:
+      type: object
+      deprecated: true
+      properties:
+        field1:
+          type: string
\ No newline at end of file
diff --git a/core/src/test/resources/schemaDiff/schema-deprecated-handling-2.yaml b/core/src/test/resources/schemaDiff/schema-deprecated-handling-2.yaml
new file mode 100644
index 000000000..00432216c
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-deprecated-handling-2.yaml
@@ -0,0 +1,33 @@
+openapi: 3.1.0
+info:
+  description: Schema deprecated handling
+  title: defaults
+  version: 1.0.0
+paths:
+  /schema-diff/deprecated/added:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/DeprecatedAdded"
+  /schema-diff/deprecated/removed:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: "#/components/schemas/DeprecatedRemoved"
+components:
+  schemas:
+    DeprecatedAdded:
+      deprecated: true
+      type: object
+      properties:
+        field1:
+          type: string
+    DeprecatedRemoved:
+      type: object
+      properties:
+        field1:
+          type: string
\ No newline at end of file
diff --git a/core/src/test/resources/schemaDiff/schema-min-max-items-diff-1.yaml b/core/src/test/resources/schemaDiff/schema-min-max-items-diff-1.yaml
new file mode 100644
index 000000000..a7426987d
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-min-max-items-diff-1.yaml
@@ -0,0 +1,58 @@
+openapi: 3.1.0
+info:
+  description: Schema diff
+  title: schema diff
+  version: 1.0.0
+paths:
+  /schema/array/items:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/TestDTO'
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field0:
+          type: array
+          items:
+            type: string
+          minItems: 1
+          maxItems: 10
+        field1:
+          type: array
+          items:
+            type: string
+          minItems: 1
+          maxItems: 100
+        field2:
+          type: array
+          items:
+            type: string
+          minItems: 20
+          maxItems: 100
+        field3:
+          type: array
+          items:
+            type: string
+          minItems: 1
+          maxItems: 90
+        field4:
+          type: array
+          items:
+            type: string
+          minItems: 1
+          maxItems: 100
+        field5:
+          type: array
+          items:
+            type: string
+          minItems: 1
+          maxItems: 100
+        field6:
+          type: array
+          items:
+            type: string
diff --git a/core/src/test/resources/schemaDiff/schema-min-max-items-diff-2.yaml b/core/src/test/resources/schemaDiff/schema-min-max-items-diff-2.yaml
new file mode 100644
index 000000000..5e58f5731
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-min-max-items-diff-2.yaml
@@ -0,0 +1,58 @@
+openapi: 3.1.0
+info:
+  description: Schema diff
+  title: schema diff
+  version: 1.0.0
+paths:
+  /schema/array/items:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/TestDTO'
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field0:
+          type: array
+          items:
+            type: string
+          minItems: 1
+          maxItems: 10
+        field1:
+          type: array
+          items:
+            type: string
+          minItems: 2
+          maxItems: 100
+        field2:
+          type: array
+          items:
+            type: string
+          minItems: 10
+          maxItems: 100
+        field3:
+          type: array
+          items:
+            type: string
+          minItems: 1
+          maxItems: 100
+        field4:
+          type: array
+          items:
+            type: string
+          minItems: 1
+          maxItems: 90
+        field5:
+          type: array
+          items:
+            type: string
+        field6:
+          type: array
+          items:
+            type: string
+          minItems: 1
+          maxItems: 100
diff --git a/core/src/test/resources/schemaDiff/schema-min-max-properties-diff-1.yaml b/core/src/test/resources/schemaDiff/schema-min-max-properties-diff-1.yaml
new file mode 100644
index 000000000..263d710f7
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-min-max-properties-diff-1.yaml
@@ -0,0 +1,30 @@
+openapi: 3.0.1
+info:
+  description: Schema diff
+  title: schema diff
+  version: 1.0.0
+paths:
+  /schema/object/min-max-properties:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/TestDTO'
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field1:
+          type: object
+          minProperties: 1
+        field2:
+          type: object
+          minProperties: 10
+        field3:
+          type: object
+          maxProperties: 10
+        field4:
+          type: object
+          maxProperties: 100
diff --git a/core/src/test/resources/schemaDiff/schema-min-max-properties-diff-2.yaml b/core/src/test/resources/schemaDiff/schema-min-max-properties-diff-2.yaml
new file mode 100644
index 000000000..17183d8a5
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-min-max-properties-diff-2.yaml
@@ -0,0 +1,30 @@
+openapi: 3.0.1
+info:
+  description: Schema diff
+  title: schema diff
+  version: 1.0.0
+paths:
+  /schema/object/min-max-properties:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/TestDTO'
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field1:
+          type: object
+          minProperties: 10
+        field2:
+          type: object
+          minProperties: 1
+        field3:
+          type: object
+          maxProperties: 100
+        field4:
+          type: object
+          maxProperties: 10
diff --git a/core/src/test/resources/schemaDiff/schema-multiple-of-diff-1.yaml b/core/src/test/resources/schemaDiff/schema-multiple-of-diff-1.yaml
new file mode 100644
index 000000000..49d3f3b17
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-multiple-of-diff-1.yaml
@@ -0,0 +1,29 @@
+openapi: 3.1.0
+info:
+  description: Schema diff
+  title: schema diff
+  version: 1.0.0
+paths:
+  /schema/numeric/multiple-of:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/TestDTO'
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field1:
+          type: integer
+          multipleOf: 10
+        field2:
+          type: integer
+          multipleOf: 0.01
+        field3:
+          type: integer
+        field4:
+          type: integer
+          multipleOf: 10 
\ No newline at end of file
diff --git a/core/src/test/resources/schemaDiff/schema-multiple-of-diff-2.yaml b/core/src/test/resources/schemaDiff/schema-multiple-of-diff-2.yaml
new file mode 100644
index 000000000..58311d082
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-multiple-of-diff-2.yaml
@@ -0,0 +1,29 @@
+openapi: 3.1.0
+info:
+  description: Schema diff
+  title: schema diff
+  version: 1.0.0
+paths:
+  /schema/numeric/multiple-of:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/TestDTO'
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field1:
+          type: integer
+          multipleOf: 20
+        field2:
+          type: integer
+          multipleOf: 0.1
+        field3:
+          type: integer
+          multipleOf: 10 
+        field4:
+          type: integer           
\ No newline at end of file
diff --git a/core/src/test/resources/schemaDiff/schema-nullable-diff-1.yaml b/core/src/test/resources/schemaDiff/schema-nullable-diff-1.yaml
new file mode 100644
index 000000000..b467c3746
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-nullable-diff-1.yaml
@@ -0,0 +1,28 @@
+openapi: 3.0.1
+info:
+  description: Schema diff nullable
+  title: schema diff nullable
+  version: 1.0.0
+paths:
+  /schema/nullable:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/TestDTO'
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field0:
+          type: integer
+        field1:
+          type: integer
+          nullable: true
+        field2:
+          type: integer
+          nullable: true
+        field3:
+          type: integer
\ No newline at end of file
diff --git a/core/src/test/resources/schemaDiff/schema-nullable-diff-2.yaml b/core/src/test/resources/schemaDiff/schema-nullable-diff-2.yaml
new file mode 100644
index 000000000..e186f76e6
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-nullable-diff-2.yaml
@@ -0,0 +1,28 @@
+openapi: 3.0.1
+info:
+  description: Schema diff nullable
+  title: schema diff nullable
+  version: 1.0.0
+paths:
+  /schema/nullable:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/TestDTO'
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field0:
+          type: integer
+        field1:
+          type: integer
+          nullable: false
+        field2:
+          type: integer
+        field3:
+          type: integer
+          nullable: true
\ No newline at end of file
diff --git a/core/src/test/resources/schemaDiff/schema-pattern-diff-1.yaml b/core/src/test/resources/schemaDiff/schema-pattern-diff-1.yaml
new file mode 100644
index 000000000..909ac8fae
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-pattern-diff-1.yaml
@@ -0,0 +1,24 @@
+openapi: 3.0.0
+info:
+  title: Schema Pattern Diff Test - Old
+  version: 1.0.0
+paths:
+  /schema/pattern:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                patternUnchanged:
+                  type: string
+                  pattern: "^[a-z]+$"
+                patternModified:
+                  type: string
+                  pattern: "^[a-z]+$"
+                patternRemoved:
+                  type: string
+                  pattern: "^[0-9]+$"
+                patternAdded:
+                  type: string
diff --git a/core/src/test/resources/schemaDiff/schema-pattern-diff-2.yaml b/core/src/test/resources/schemaDiff/schema-pattern-diff-2.yaml
new file mode 100644
index 000000000..05ee63f3c
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-pattern-diff-2.yaml
@@ -0,0 +1,24 @@
+openapi: 3.0.0
+info:
+  title: Schema Pattern Diff Test - New
+  version: 1.0.0
+paths:
+  /schema/pattern:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              type: object
+              properties:
+                patternUnchanged:
+                  type: string
+                  pattern: "^[a-z]+$"
+                patternModified:
+                  type: string
+                  pattern: "^[a-zA-Z]+$"
+                patternRemoved:
+                  type: string
+                patternAdded:
+                  type: string
+                  pattern: "^\\d{3}-\\d{2}-\\d{4}$?"
diff --git a/core/src/test/resources/schemaDiff/schema-props-defaults-handling-1.yaml b/core/src/test/resources/schemaDiff/schema-props-defaults-handling-1.yaml
new file mode 100644
index 000000000..3ecee6886
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-props-defaults-handling-1.yaml
@@ -0,0 +1,21 @@
+openapi: 3.1.0
+info:
+  description: Schema defaults handling
+  title: defaults
+  version: 1.0.0
+paths:
+  /defaults/property-schema/:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/TestDTO'
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field1:
+          default: default value
+          type: string
\ No newline at end of file
diff --git a/core/src/test/resources/schemaDiff/schema-props-defaults-handling-2.yaml b/core/src/test/resources/schemaDiff/schema-props-defaults-handling-2.yaml
new file mode 100644
index 000000000..143174770
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-props-defaults-handling-2.yaml
@@ -0,0 +1,21 @@
+openapi: 3.1.0
+info:
+  description: Schema defaults handling
+  title: defaults
+  version: 1.0.0
+paths:
+  /defaults/property-schema/:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/TestDTO'
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field1:
+          default: default value updated
+          type: string
\ No newline at end of file
diff --git a/core/src/test/resources/schemaDiff/schema-props-type-handling-1.yaml b/core/src/test/resources/schemaDiff/schema-props-type-handling-1.yaml
new file mode 100644
index 000000000..37d612e33
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-props-type-handling-1.yaml
@@ -0,0 +1,23 @@
+openapi: 3.0.0
+info:
+  title: Schema Type Handling Test - Before
+  version: 1.0.0
+paths:
+  /test:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/TestSchema'
+      responses:
+        '200':
+          description: OK
+components:
+  schemas:
+    TestSchema:
+      type: object
+      properties:
+        field1:
+          type: string
+          description: A field that will change type
diff --git a/core/src/test/resources/schemaDiff/schema-props-type-handling-2.yaml b/core/src/test/resources/schemaDiff/schema-props-type-handling-2.yaml
new file mode 100644
index 000000000..efe131d80
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-props-type-handling-2.yaml
@@ -0,0 +1,23 @@
+openapi: 3.0.0
+info:
+  title: Schema Type Handling Test - After
+  version: 1.0.0
+paths:
+  /test:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/TestSchema'
+      responses:
+        '200':
+          description: OK
+components:
+  schemas:
+    TestSchema:
+      type: object
+      properties:
+        field1:
+          type: integer # Changed from string to integer
+          description: A field that has changed type
diff --git a/core/src/test/resources/schemaDiff/schema-uniqueItems-diff-1.yaml b/core/src/test/resources/schemaDiff/schema-uniqueItems-diff-1.yaml
new file mode 100644
index 000000000..dc0e60dec
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-uniqueItems-diff-1.yaml
@@ -0,0 +1,31 @@
+openapi: 3.0.1
+info:
+  description: Schema diff uniqueItems
+  title: schema diff uniqueItems
+  version: 1.0.0
+paths:
+  /schema/uniqueItems:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/TestDTO'
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field0:
+          type: integer
+        field1:
+          type: integer
+          uniqueItems: true
+        field2:
+          type: integer
+          uniqueItems: false
+        field3:
+          type: integer
+          uniqueItems: true
+        field4:
+          type: integer
\ No newline at end of file
diff --git a/core/src/test/resources/schemaDiff/schema-uniqueItems-diff-2.yaml b/core/src/test/resources/schemaDiff/schema-uniqueItems-diff-2.yaml
new file mode 100644
index 000000000..12e2b906e
--- /dev/null
+++ b/core/src/test/resources/schemaDiff/schema-uniqueItems-diff-2.yaml
@@ -0,0 +1,31 @@
+openapi: 3.0.1
+info:
+  description: Schema diff uniqueItems
+  title: schema diff uniqueItems
+  version: 1.0.0
+paths:
+  /schema/uniqueItems:
+    post:
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/TestDTO'
+components:
+  schemas:
+    TestDTO:
+      type: object
+      properties:
+        field0:
+          type: integer
+        field1:
+          type: integer
+          uniqueItems: false
+        field2:
+          type: integer
+          uniqueItems: true
+        field3:
+          type: integer
+        field4:
+          type: integer
+          uniqueItems: true
\ No newline at end of file
diff --git a/maven-example/pom.xml b/maven-example/pom.xml
index bb3d9c7c5..b88b4c651 100644
--- a/maven-example/pom.xml
+++ b/maven-example/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <artifactId>openapi-diff-parent</artifactId>
         <groupId>org.openapitools.openapidiff</groupId>
-        <version>2.1.0-SNAPSHOT</version>
+        <version>2.2.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -23,7 +23,7 @@
             <plugin>
                 <groupId>org.openapitools.openapidiff</groupId>
                 <artifactId>openapi-diff-maven</artifactId>
-                <version>2.1.0-SNAPSHOT</version>
+                <version>2.2.0-SNAPSHOT</version>
                 <executions>
                     <execution>
                         <goals>
@@ -36,6 +36,12 @@
                             <consoleOutputFileName>${project.basedir}/../maven/target/diff.txt</consoleOutputFileName>
                             <jsonOutputFileName>${project.basedir}/../maven/target/diff.json</jsonOutputFileName>
                             <markdownOutputFileName>${project.basedir}/../maven/target/diff.md</markdownOutputFileName>
+                            <configFiles>
+                                <configFile>${project.basedir}/../maven/src/test/resources/test-config-file.yaml</configFile>
+                            </configFiles>
+                            <configProps>
+                                <incompatible.request.params.required.increased>false</incompatible.request.params.required.increased>
+                            </configProps>
                         </configuration>
                     </execution>
                 </executions>
diff --git a/maven/pom.xml b/maven/pom.xml
index f5e88ea50..ff231c206 100644
--- a/maven/pom.xml
+++ b/maven/pom.xml
@@ -5,7 +5,7 @@
   <parent>
     <groupId>org.openapitools.openapidiff</groupId>
     <artifactId>openapi-diff-parent</artifactId>
-    <version>2.1.0-SNAPSHOT</version>
+    <version>2.2.0-SNAPSHOT</version>
   </parent>
 
   <artifactId>openapi-diff-maven</artifactId>
@@ -56,12 +56,15 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-plugin-plugin</artifactId>
-          <version>3.8.1</version>
+          <version>3.13.1</version>
+          <configuration>
+            <goalPrefix>openapi-diff</goalPrefix>
+          </configuration>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-site-plugin</artifactId>
-          <version>3.12.1</version>
+          <version>3.21.0</version>
         </plugin>
       </plugins>
     </pluginManagement>
diff --git a/maven/src/main/java/org/openapitools/openapidiff/maven/OpenApiDiffMojo.java b/maven/src/main/java/org/openapitools/openapidiff/maven/OpenApiDiffMojo.java
index 7e0e82fb7..4fd7d9e14 100644
--- a/maven/src/main/java/org/openapitools/openapidiff/maven/OpenApiDiffMojo.java
+++ b/maven/src/main/java/org/openapitools/openapidiff/maven/OpenApiDiffMojo.java
@@ -3,9 +3,12 @@
 import static org.openapitools.openapidiff.core.utils.FileUtils.writeToFile;
 
 import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.io.UncheckedIOException;
+import java.util.List;
+import java.util.Map;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
@@ -13,7 +16,9 @@
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.openapitools.openapidiff.core.OpenApiCompare;
+import org.openapitools.openapidiff.core.compare.OpenApiDiffOptions;
 import org.openapitools.openapidiff.core.model.ChangedOpenApi;
+import org.openapitools.openapidiff.core.output.AsciidocRender;
 import org.openapitools.openapidiff.core.output.ConsoleRender;
 import org.openapitools.openapidiff.core.output.JsonRender;
 import org.openapitools.openapidiff.core.output.MarkdownRender;
@@ -46,6 +51,15 @@ public class OpenApiDiffMojo extends AbstractMojo {
   @Parameter(property = "markdownOutputFileName")
   String markdownOutputFileName;
 
+  @Parameter(property = "configFiles")
+  List<File> configFiles;
+
+  @Parameter(property = "configProps")
+  Map<String, String> configProps;
+
+  @Parameter(property = "asciidocOutputFileName")
+  String asciidocOutputFileName;
+
   @Override
   public void execute() throws MojoExecutionException, MojoFailureException {
     if (Boolean.TRUE.equals(skip)) {
@@ -54,7 +68,16 @@ public void execute() throws MojoExecutionException, MojoFailureException {
     }
 
     try {
-      final ChangedOpenApi diff = OpenApiCompare.fromLocations(oldSpec, newSpec);
+      OpenApiDiffOptions.Builder optionBuilder = OpenApiDiffOptions.builder();
+      if (configFiles != null) {
+        configFiles.forEach(optionBuilder::configYaml);
+      }
+      if (configProps != null) {
+        configProps.forEach(optionBuilder::configProperty);
+      }
+      OpenApiDiffOptions options = optionBuilder.build();
+
+      final ChangedOpenApi diff = OpenApiCompare.fromLocations(oldSpec, newSpec, null, options);
 
       try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
           OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream)) {
@@ -67,6 +90,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
       writeDiffAsTextToFile(diff);
       writeDiffAsJsonToFile(diff);
       writeDiffAsMarkdownToFile(diff);
+      writeDiffAsAsciidocToFile(diff);
 
       if (failOnIncompatible && diff.isIncompatible()) {
         throw new BackwardIncompatibilityException("The API changes broke backward compatibility");
@@ -91,4 +115,8 @@ private void writeDiffAsJsonToFile(final ChangedOpenApi diff) {
   private void writeDiffAsMarkdownToFile(final ChangedOpenApi diff) {
     writeToFile(new MarkdownRender(), diff, markdownOutputFileName);
   }
+
+  private void writeDiffAsAsciidocToFile(final ChangedOpenApi diff) {
+    writeToFile(new AsciidocRender(), diff, asciidocOutputFileName);
+  }
 }
diff --git a/maven/src/test/java/org/openapitools/openapidiff/maven/OpenApiDiffMojoTest.java b/maven/src/test/java/org/openapitools/openapidiff/maven/OpenApiDiffMojoTest.java
index 10bd186e5..d38c66bde 100644
--- a/maven/src/test/java/org/openapitools/openapidiff/maven/OpenApiDiffMojoTest.java
+++ b/maven/src/test/java/org/openapitools/openapidiff/maven/OpenApiDiffMojoTest.java
@@ -8,6 +8,7 @@
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Paths;
+import java.util.Collections;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
@@ -21,10 +22,12 @@ class OpenApiDiffMojoTest {
 
   private final File oldSpecFile = new File("src/test/resources/oldspec.yaml");
   private final File newSpecFile = new File("src/test/resources/newspec.yaml");
+  private final File configFile = new File("src/test/resources/test-config-file.yaml");
 
   private final File consoleOutputfile = new File("target/diff.txt");
   private final File markdownOutputfile = new File("target/diff.md");
   private final File jsonOutputfile = new File("target/diff.json");
+  private final File asciidocOutputfile = new File("target/diff.adoc");
 
   @BeforeEach
   void setup() {
@@ -105,6 +108,19 @@ void Should_BackwardIncompatibilityException_When_WantsExceptionAndSpecIsIncompa
     assertThrows(BackwardIncompatibilityException.class, mojo::execute);
   }
 
+  @Test
+  void Should_NotThrow_When_ConfigWithIncompatibleChecksDisabled() {
+    final OpenApiDiffMojo mojo = new OpenApiDiffMojo();
+    mojo.oldSpec = newSpecFile.getAbsolutePath();
+    mojo.newSpec = oldSpecFile.getAbsolutePath();
+    mojo.failOnIncompatible = true;
+    mojo.configFiles = Collections.singletonList(configFile);
+    mojo.configProps =
+        Collections.singletonMap("incompatible.request.params.required.increased", "false");
+
+    assertDoesNotThrow(mojo::execute);
+  }
+
   @Test
   void Should_Skip_Mojo_WhenSkipIsTrue() {
     final OpenApiDiffMojo mojo = new OpenApiDiffMojo();
@@ -158,6 +174,20 @@ void Should_outputToJsonFile_When_SpecIsDifferent() {
     assertTrue(Files.exists(jsonOutputfile.toPath()));
   }
 
+  @Test
+  void Should_outputToAsccidocFile_When_SpecIsDifferent() {
+    final OpenApiDiffMojo mojo = new OpenApiDiffMojo();
+    mojo.oldSpec = oldSpecFile.getAbsolutePath();
+    mojo.newSpec = newSpecFile.getAbsolutePath();
+
+    mojo.asciidocOutputFileName = asciidocOutputfile.getAbsolutePath();
+    mojo.failOnChanged = true;
+
+    assertThrows(ApiChangedException.class, mojo::execute);
+
+    assertTrue(Files.exists(asciidocOutputfile.toPath()));
+  }
+
   private void cleanupGeneratedFiles() {
     try {
       Files.deleteIfExists(Paths.get(consoleOutputfile.getPath()));
diff --git a/maven/src/test/resources/newspec.yaml b/maven/src/test/resources/newspec.yaml
index e95978f04..7d326b882 100644
--- a/maven/src/test/resources/newspec.yaml
+++ b/maven/src/test/resources/newspec.yaml
@@ -1,15 +1,33 @@
----
-openapi: 3.0.3
+openapi: 3.0.0
 info:
-  title: Generated API
-  version: "1.0"
+  description: myDesc
+  title: myTitle
+  version: 1.0.0
 paths:
-  /hello:
+  /widgets:
     get:
+      operationId: listWidgets
+      parameters:
+        - name: query-param-1
+          in: query
+          schema:
+            type: string
+        - name: query-param-2
+          in: query
+          schema:
+            type: string
       responses:
-        "200":
-          description: OK
+        '200':
+          description: successful operation
           content:
-            text/plain:
+            application/json:
               schema:
-                type: string
+                type: object
+                properties:
+                  prop1:
+                    type: string
+                  prop2:
+                    type: string
+                required:
+                  - prop1
+                  - prop2
diff --git a/maven/src/test/resources/oldspec.yaml b/maven/src/test/resources/oldspec.yaml
index 2f2735763..40cd4175e 100644
--- a/maven/src/test/resources/oldspec.yaml
+++ b/maven/src/test/resources/oldspec.yaml
@@ -1,6 +1,33 @@
----
-openapi: 3.0.3
+openapi: 3.0.0
 info:
-  title: Generated API
-  version: "1.0"
-paths: {}
+  description: myDesc
+  title: myTitle
+  version: 1.0.0
+paths:
+  /widgets:
+    get:
+      operationId: listWidgets
+      parameters:
+        - name: query-param-1
+          in: query
+          required: true
+          schema:
+            type: string
+        - name: query-param-2
+          in: query
+          schema:
+            type: string
+      responses:
+        '200':
+          description: successful operation
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  prop1:
+                    type: string
+                  prop2:
+                    type: string
+                required:
+                  - prop1
diff --git a/maven/src/test/resources/test-config-file.yaml b/maven/src/test/resources/test-config-file.yaml
new file mode 100644
index 000000000..633ad0be3
--- /dev/null
+++ b/maven/src/test/resources/test-config-file.yaml
@@ -0,0 +1,8 @@
+####
+## Config file for openapi-diff
+####
+
+incompatible:
+  response:
+    required:
+      decreased: false
diff --git a/pom.xml b/pom.xml
index 7db6b41a3..4b289dc33 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
 
     <groupId>org.openapitools.openapidiff</groupId>
     <artifactId>openapi-diff-parent</artifactId>
-    <version>2.1.0-SNAPSHOT</version>
+    <version>2.2.0-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <name>openapi-diff-parent</name>
@@ -59,23 +59,30 @@
 
     <distributionManagement>
         <snapshotRepository>
-            <id>sonatype-nexus-snapshots</id>
-            <name>Sonatype Nexus snapshot repository</name>
-            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <id>ossrh</id>
+            <url>https://central.sonatype.com/repository/maven-snapshots</url>
         </snapshotRepository>
+    </distributionManagement>
+    <repositories>
         <repository>
-            <id>sonatype-nexus-staging</id>
-            <name>Sonatype Nexus release repository</name>
-            <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+            <id>ossrh</id>
+            <url>https://central.sonatype.com/repository/maven-snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+                <updatePolicy>always</updatePolicy>
+            </snapshots>
         </repository>
-    </distributionManagement>
+    </repositories>
 
     <properties>
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-        <project.build.outputTimestamp>2023-07-25T21:46:40Z</project.build.outputTimestamp>
+        <project.build.outputTimestamp>2025-05-30T16:02:28Z</project.build.outputTimestamp>
         <project.scm.id>github</project.scm.id>
 
         <sonar.organization>openapitools</sonar.organization>
@@ -83,8 +90,8 @@
         <sonar.host.url>https://sonarcloud.io</sonar.host.url>
         <sonar.moduleKey>${project.artifactId}</sonar.moduleKey>
 
-        <swagger-parser.version>2.1.19</swagger-parser.version>
-        <slf4j.version>2.0.9</slf4j.version>
+        <swagger-parser.version>2.1.31</swagger-parser.version>
+        <slf4j.version>2.0.17</slf4j.version>
     </properties>
 
     <dependencyManagement>
@@ -92,12 +99,12 @@
             <dependency>
                 <groupId>org.openapitools.openapidiff</groupId>
                 <artifactId>openapi-diff-core</artifactId>
-                <version>2.1.0-SNAPSHOT</version>
+                <version>2.2.0-SNAPSHOT</version>
             </dependency>
             <dependency>
                 <groupId>org.junit</groupId>
                 <artifactId>junit-bom</artifactId>
-                <version>5.10.1</version>
+                <version>5.13.3</version>
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
@@ -124,17 +131,22 @@
             <dependency>
                 <groupId>org.apache.commons</groupId>
                 <artifactId>commons-collections4</artifactId>
-                <version>4.4</version>
+                <version>4.5.0</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-configuration2</artifactId>
+                <version>2.12.0</version>
             </dependency>
             <dependency>
                 <groupId>commons-cli</groupId>
                 <artifactId>commons-cli</artifactId>
-                <version>1.6.0</version>
+                <version>1.9.0</version>
             </dependency>
             <dependency>
                 <groupId>org.apache.commons</groupId>
                 <artifactId>commons-lang3</artifactId>
-                <version>3.14.0</version>
+                <version>3.18.0</version>
             </dependency>
             <dependency>
                 <groupId>org.slf4j</groupId>
@@ -159,7 +171,7 @@
             <dependency>
                 <groupId>org.assertj</groupId>
                 <artifactId>assertj-core</artifactId>
-                <version>3.24.2</version>
+                <version>3.27.3</version>
                 <scope>test</scope>
             </dependency>
         </dependencies>
@@ -202,22 +214,15 @@
                         </executions>
                     </plugin>
                     <plugin>
-                        <groupId>org.sonatype.plugins</groupId>
-                        <artifactId>nexus-staging-maven-plugin</artifactId>
+                        <groupId>org.sonatype.central</groupId>
+                        <artifactId>central-publishing-maven-plugin</artifactId>
+                        <version>0.7.0</version>
+                        <extensions>true</extensions>
                         <configuration>
-                            <serverId>sonatype-nexus-staging</serverId>
-                            <nexusUrl>https://oss.sonatype.org/</nexusUrl>
-                            <autoReleaseAfterClose>true</autoReleaseAfterClose>
+                            <publishingServerId>ossrh</publishingServerId>
+                            <autoPublish>true</autoPublish>
+                            <waitUntil>published</waitUntil>
                         </configuration>
-                        <executions>
-                            <execution>
-                                <id>nexus-deploy</id>
-                                <phase>deploy</phase>
-                                <goals>
-                                    <goal>deploy</goal>
-                                </goals>
-                            </execution>
-                        </executions>
                     </plugin>
                     <plugin>
                         <groupId>org.apache.maven.plugins</groupId>
@@ -273,32 +278,39 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-compiler-plugin</artifactId>
-                    <version>3.11.0</version>
+                    <version>3.14.0</version>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-source-plugin</artifactId>
-                    <version>3.3.0</version>
+                    <version>3.3.1</version>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-jar-plugin</artifactId>
-                    <version>3.3.0</version>
+                    <version>3.4.2</version>
+                    <configuration>
+                        <archive>
+                            <manifestEntries>
+                                <Implementation-Version>${project.version}</Implementation-Version>
+                            </manifestEntries>
+                        </archive>
+                    </configuration>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-release-plugin</artifactId>
-                    <version>3.0.1</version>
+                    <version>3.1.1</version>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-javadoc-plugin</artifactId>
-                    <version>3.6.3</version>
+                    <version>3.11.2</version>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-surefire-plugin</artifactId>
-                    <version>3.2.2</version>
+                    <version>3.5.3</version>
                 </plugin>
                 <plugin>
                     <groupId>com.coveo</groupId>
@@ -313,38 +325,37 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-gpg-plugin</artifactId>
-                    <version>3.1.0</version>
+                    <version>3.2.8</version>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-deploy-plugin</artifactId>
-                    <version>3.1.1</version>
+                    <version>3.1.4</version>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-shade-plugin</artifactId>
-                    <version>3.5.1</version>
+                    <version>3.6.0</version>
                 </plugin>
                 <plugin>
-                    <groupId>org.sonatype.plugins</groupId>
-                    <artifactId>nexus-staging-maven-plugin</artifactId>
-                    <version>1.6.13</version>
-                    <extensions>true</extensions>
+                    <groupId>org.sonatype.central</groupId>
+                    <artifactId>central-publishing-maven-plugin</artifactId>
+                    <version>0.7.0</version>
                 </plugin>
                 <plugin>
                     <groupId>org.jacoco</groupId>
                     <artifactId>jacoco-maven-plugin</artifactId>
-                    <version>0.8.11</version>
+                    <version>0.8.13</version>
                 </plugin>
                 <plugin>
                     <groupId>org.sonarsource.scanner.maven</groupId>
                     <artifactId>sonar-maven-plugin</artifactId>
-                    <version>3.10.0.2594</version>
+                    <version>5.1.0.4751</version>
                 </plugin>
                 <plugin>
                     <groupId>org.cyclonedx</groupId>
                     <artifactId>cyclonedx-maven-plugin</artifactId>
-                    <version>2.7.10</version>
+                    <version>2.9.1</version>
                 </plugin>
             </plugins>
         </pluginManagement>
