From 9aa7e845d98b32d5c2cde2b85e0d84ca0374a852 Mon Sep 17 00:00:00 2001 From: Melsy Huamani Date: Thu, 10 Sep 2026 18:15:55 -0500 Subject: [PATCH 1/3] fix: oar005, oar007, oar010 rules --- CHANGELOG.md | 8 + pom.xml | 2 +- .../apim/wso2/AbstractWso2ScopesCheck.java | 17 +- .../apim/wso2/OAR002ValidWso2ScopesCheck.java | 12 +- .../OAR005UndefinedWso2ScopeUseCheck.java | 27 +- .../format/AbstractDefaultMediaTypeCheck.java | 13 +- .../sonar/openapi/utils/JsonNodeUtils.java | 34 +++ .../rules/openapi/apim/wso2/OAR005.html | 28 +- .../rules/openapi/apim/wso2/OAR005.html | 1 + .../openapi/rules/openapi/format/OAR007.html | 4 +- .../OAR005UndefinedWso2ScopeUseCheckTest.java | 248 ++++++++++++++++++ ...07UndefinedResponseMediaTypeCheckTest.java | 109 ++++++++ ...R010DefaultResponseMediaTypeCheckTest.java | 49 ++++ .../v2/apim/wso2/OAR005/extensive-api.json | 241 +++++++++++++++++ .../v2/apim/wso2/OAR005/extensive-api.yaml | 167 ++++++++++++ .../v2/apim/wso2/OAR005/with-all-verbs.json | 77 ++++++ .../v2/apim/wso2/OAR005/with-all-verbs.yaml | 49 ++++ .../OAR005/with-chained-ref-security.json | 50 ++++ .../OAR005/with-chained-ref-security.yaml | 33 +++ .../v2/apim/wso2/OAR005/with-ref-scope.json | 55 ++++ .../v2/apim/wso2/OAR005/with-ref-scope.yaml | 36 +++ .../apim/wso2/OAR005/with-ref-security.json | 47 ++++ .../apim/wso2/OAR005/with-ref-security.yaml | 31 +++ .../wso2/OAR005/with-scope-key-not-name.json | 37 +++ .../wso2/OAR005/with-scope-key-not-name.yaml | 24 ++ .../apim/wso2/OAR005/with-scopes-as-map.json | 66 +++++ .../apim/wso2/OAR005/with-scopes-as-map.yaml | 43 +++ .../v2/apim/wso2/OAR005/without-security.json | 26 ++ .../v2/apim/wso2/OAR005/without-security.yaml | 15 ++ .../v2/format/OAR007/with-specific-put.json | 21 ++ .../v2/format/OAR007/with-specific-put.yaml | 13 + .../OAR010/with-default-mixed-case.json | 21 ++ .../OAR010/with-default-mixed-case.yaml | 13 + .../v3/apim/wso2/OAR005/extensive-api.json | 241 +++++++++++++++++ .../v3/apim/wso2/OAR005/extensive-api.yaml | 167 ++++++++++++ .../v3/apim/wso2/OAR005/with-all-verbs.json | 85 ++++++ .../v3/apim/wso2/OAR005/with-all-verbs.yaml | 54 ++++ .../apim/wso2/OAR005/with-array-security.yaml | 18 ++ .../wso2/OAR005/with-callback-operations.json | 72 +++++ .../wso2/OAR005/with-callback-operations.yaml | 43 +++ .../OAR005/with-chained-ref-security.json | 50 ++++ .../OAR005/with-chained-ref-security.yaml | 33 +++ .../wso2/OAR005/with-cyclic-ref-security.yaml | 24 ++ .../OAR005/with-dangling-ref-security.yaml | 26 ++ .../wso2/OAR005/with-empty-array-scopes.yaml | 20 ++ .../wso2/OAR005/with-empty-object-scopes.yaml | 20 ++ .../wso2/OAR005/with-malformed-scopes.yaml | 57 ++++ .../v3/apim/wso2/OAR005/with-null-apim.yaml | 19 ++ .../v3/apim/wso2/OAR005/with-null-scopes.yaml | 20 ++ .../apim/wso2/OAR005/with-null-security.yaml | 18 ++ .../v3/apim/wso2/OAR005/with-ref-scope.json | 55 ++++ .../v3/apim/wso2/OAR005/with-ref-scope.yaml | 36 +++ .../apim/wso2/OAR005/with-ref-security.json | 47 ++++ .../apim/wso2/OAR005/with-ref-security.yaml | 31 +++ .../apim/wso2/OAR005/with-scalar-scopes.yaml | 20 ++ .../wso2/OAR005/with-scalar-security.yaml | 18 ++ .../wso2/OAR005/with-scope-key-not-name.json | 37 +++ .../wso2/OAR005/with-scope-key-not-name.yaml | 24 ++ .../apim/wso2/OAR005/with-scopes-as-map.json | 66 +++++ .../apim/wso2/OAR005/with-scopes-as-map.yaml | 43 +++ .../with-x-scope-block-collections.yaml | 25 ++ .../wso2/OAR005/with-x-scope-collections.yaml | 33 +++ .../OAR005/with-x-scope-null-spellings.yaml | 49 ++++ .../OAR005/with-x-scope-scalar-types.yaml | 54 ++++ .../v3/apim/wso2/OAR005/without-apim.yaml | 20 ++ .../v3/apim/wso2/OAR005/without-scopes.yaml | 19 ++ .../v3/apim/wso2/OAR005/without-security.json | 26 ++ .../v3/apim/wso2/OAR005/without-security.yaml | 15 ++ .../v3/format/OAR007/with-204-response.json | 18 ++ .../v3/format/OAR007/with-204-response.yaml | 10 + .../v3/format/OAR007/with-chained-ref.json | 28 ++ .../v3/format/OAR007/with-chained-ref.yaml | 16 ++ .../format/OAR007/with-default-and-ref.json | 28 ++ .../format/OAR007/with-default-and-ref.yaml | 16 ++ .../OAR007/with-default-response-key.json | 19 ++ .../OAR007/with-default-response-key.yaml | 11 + .../v3/format/OAR007/with-external-ref.json | 18 ++ .../v3/format/OAR007/with-external-ref.yaml | 11 + .../OAR007/with-multiple-operations.json | 53 ++++ .../OAR007/with-multiple-operations.yaml | 31 +++ .../v3/format/OAR007/with-specific.json | 21 ++ .../v3/format/OAR007/with-specific.yaml | 12 + .../v3/format/OAR007/with-wrong-ref.json | 25 ++ .../v3/format/OAR007/with-wrong-ref.yaml | 14 + .../v3/format/OAR010/with-204-response.json | 27 ++ .../v3/format/OAR010/with-204-response.yaml | 16 ++ .../OAR010/with-default-mixed-case.json | 21 ++ .../OAR010/with-default-mixed-case.yaml | 12 + .../v3/format/OAR010/with-external-ref.json | 18 ++ .../v3/format/OAR010/with-external-ref.yaml | 11 + .../OAR010/with-wrong-default-and-ref.json | 28 ++ .../OAR010/with-wrong-default-and-ref.yaml | 16 ++ .../checks/v31/apim/OAR005/extensive-api.json | 241 +++++++++++++++++ .../checks/v31/apim/OAR005/extensive-api.yaml | 167 ++++++++++++ .../v31/apim/OAR005/with-all-verbs.json | 85 ++++++ .../v31/apim/OAR005/with-all-verbs.yaml | 54 ++++ .../apim/OAR005/with-callback-operations.json | 72 +++++ .../apim/OAR005/with-callback-operations.yaml | 43 +++ .../OAR005/with-chained-ref-security.json | 50 ++++ .../OAR005/with-chained-ref-security.yaml | 33 +++ .../v31/apim/OAR005/with-ref-scope.json | 55 ++++ .../v31/apim/OAR005/with-ref-scope.yaml | 36 +++ .../v31/apim/OAR005/with-ref-security.json | 47 ++++ .../v31/apim/OAR005/with-ref-security.yaml | 31 +++ .../apim/OAR005/with-scope-key-not-name.json | 37 +++ .../apim/OAR005/with-scope-key-not-name.yaml | 24 ++ .../v31/apim/OAR005/with-scopes-as-map.json | 66 +++++ .../v31/apim/OAR005/with-scopes-as-map.yaml | 43 +++ .../apim/OAR005/with-webhook-operations.json | 60 +++++ .../apim/OAR005/with-webhook-operations.yaml | 38 +++ .../v31/apim/OAR005/without-security.json | 26 ++ .../v31/apim/OAR005/without-security.yaml | 15 ++ .../v31/format/OAR007/with-204-response.json | 18 ++ .../v31/format/OAR007/with-204-response.yaml | 10 + .../v31/format/OAR007/with-chained-ref.json | 28 ++ .../v31/format/OAR007/with-chained-ref.yaml | 16 ++ .../format/OAR007/with-default-and-ref.json | 28 ++ .../format/OAR007/with-default-and-ref.yaml | 16 ++ .../OAR007/with-default-response-key.json | 19 ++ .../OAR007/with-default-response-key.yaml | 11 + .../v31/format/OAR007/with-external-ref.json | 18 ++ .../v31/format/OAR007/with-external-ref.yaml | 11 + .../OAR007/with-multiple-operations.json | 53 ++++ .../OAR007/with-multiple-operations.yaml | 31 +++ .../v31/format/OAR007/with-specific.json | 21 ++ .../v31/format/OAR007/with-specific.yaml | 12 + .../v31/format/OAR007/with-wrong-ref.json | 25 ++ .../v31/format/OAR007/with-wrong-ref.yaml | 14 + .../v31/format/OAR010/with-204-response.json | 27 ++ .../v31/format/OAR010/with-204-response.yaml | 16 ++ .../OAR010/with-default-mixed-case.json | 21 ++ .../OAR010/with-default-mixed-case.yaml | 12 + .../OAR010/with-wrong-default-and-ref.json | 28 ++ .../OAR010/with-wrong-default-and-ref.yaml | 16 ++ .../checks/v32/apim/OAR005/extensive-api.json | 241 +++++++++++++++++ .../checks/v32/apim/OAR005/extensive-api.yaml | 167 ++++++++++++ .../OAR005/with-additional-operations.json | 60 +++++ .../OAR005/with-additional-operations.yaml | 37 +++ .../v32/apim/OAR005/with-all-verbs.json | 93 +++++++ .../v32/apim/OAR005/with-all-verbs.yaml | 59 +++++ .../apim/OAR005/with-callback-operations.json | 72 +++++ .../apim/OAR005/with-callback-operations.yaml | 43 +++ .../OAR005/with-chained-ref-security.json | 50 ++++ .../OAR005/with-chained-ref-security.yaml | 33 +++ .../v32/apim/OAR005/with-ref-scope.json | 55 ++++ .../v32/apim/OAR005/with-ref-scope.yaml | 36 +++ .../v32/apim/OAR005/with-ref-security.json | 47 ++++ .../v32/apim/OAR005/with-ref-security.yaml | 31 +++ .../apim/OAR005/with-scope-key-not-name.json | 37 +++ .../apim/OAR005/with-scope-key-not-name.yaml | 24 ++ .../v32/apim/OAR005/with-scopes-as-map.json | 66 +++++ .../v32/apim/OAR005/with-scopes-as-map.yaml | 43 +++ .../apim/OAR005/with-webhook-operations.json | 60 +++++ .../apim/OAR005/with-webhook-operations.yaml | 38 +++ .../v32/apim/OAR005/without-security.json | 26 ++ .../v32/apim/OAR005/without-security.yaml | 15 ++ .../v32/format/OAR007/with-204-response.json | 18 ++ .../v32/format/OAR007/with-204-response.yaml | 10 + .../v32/format/OAR007/with-chained-ref.json | 28 ++ .../v32/format/OAR007/with-chained-ref.yaml | 16 ++ .../format/OAR007/with-default-and-ref.json | 28 ++ .../format/OAR007/with-default-and-ref.yaml | 16 ++ .../OAR007/with-default-response-key.json | 19 ++ .../OAR007/with-default-response-key.yaml | 11 + .../v32/format/OAR007/with-external-ref.json | 18 ++ .../v32/format/OAR007/with-external-ref.yaml | 11 + .../OAR007/with-multiple-operations.json | 53 ++++ .../OAR007/with-multiple-operations.yaml | 31 +++ .../v32/format/OAR007/with-specific.json | 21 ++ .../v32/format/OAR007/with-specific.yaml | 12 + .../v32/format/OAR007/with-wrong-ref.json | 25 ++ .../v32/format/OAR007/with-wrong-ref.yaml | 14 + .../v32/format/OAR010/with-204-response.json | 27 ++ .../v32/format/OAR010/with-204-response.yaml | 16 ++ .../OAR010/with-default-mixed-case.json | 21 ++ .../OAR010/with-default-mixed-case.yaml | 12 + .../OAR010/with-wrong-default-and-ref.json | 28 ++ .../OAR010/with-wrong-default-and-ref.yaml | 16 ++ 178 files changed, 7064 insertions(+), 76 deletions(-) create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/extensive-api.json create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/extensive-api.yaml create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/with-all-verbs.json create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/with-all-verbs.yaml create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/with-chained-ref-security.json create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/with-chained-ref-security.yaml create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-scope.json create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-scope.yaml create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-security.json create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-security.yaml create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/with-scope-key-not-name.json create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/with-scope-key-not-name.yaml create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/with-scopes-as-map.json create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/with-scopes-as-map.yaml create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/without-security.json create mode 100644 src/test/resources/checks/v2/apim/wso2/OAR005/without-security.yaml create mode 100644 src/test/resources/checks/v2/format/OAR007/with-specific-put.json create mode 100644 src/test/resources/checks/v2/format/OAR007/with-specific-put.yaml create mode 100644 src/test/resources/checks/v2/format/OAR010/with-default-mixed-case.json create mode 100644 src/test/resources/checks/v2/format/OAR010/with-default-mixed-case.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/extensive-api.json create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/extensive-api.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-all-verbs.json create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-all-verbs.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-array-security.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-callback-operations.json create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-callback-operations.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-chained-ref-security.json create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-chained-ref-security.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-cyclic-ref-security.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-dangling-ref-security.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-empty-array-scopes.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-empty-object-scopes.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-malformed-scopes.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-null-apim.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-null-scopes.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-null-security.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-scope.json create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-scope.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-security.json create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-security.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-scalar-scopes.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-scalar-security.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-scope-key-not-name.json create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-scope-key-not-name.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-scopes-as-map.json create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-scopes-as-map.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-block-collections.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-collections.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-null-spellings.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-scalar-types.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/without-apim.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/without-scopes.yaml create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/without-security.json create mode 100644 src/test/resources/checks/v3/apim/wso2/OAR005/without-security.yaml create mode 100644 src/test/resources/checks/v3/format/OAR007/with-204-response.json create mode 100644 src/test/resources/checks/v3/format/OAR007/with-204-response.yaml create mode 100644 src/test/resources/checks/v3/format/OAR007/with-chained-ref.json create mode 100644 src/test/resources/checks/v3/format/OAR007/with-chained-ref.yaml create mode 100644 src/test/resources/checks/v3/format/OAR007/with-default-and-ref.json create mode 100644 src/test/resources/checks/v3/format/OAR007/with-default-and-ref.yaml create mode 100644 src/test/resources/checks/v3/format/OAR007/with-default-response-key.json create mode 100644 src/test/resources/checks/v3/format/OAR007/with-default-response-key.yaml create mode 100644 src/test/resources/checks/v3/format/OAR007/with-external-ref.json create mode 100644 src/test/resources/checks/v3/format/OAR007/with-external-ref.yaml create mode 100644 src/test/resources/checks/v3/format/OAR007/with-multiple-operations.json create mode 100644 src/test/resources/checks/v3/format/OAR007/with-multiple-operations.yaml create mode 100644 src/test/resources/checks/v3/format/OAR007/with-specific.json create mode 100644 src/test/resources/checks/v3/format/OAR007/with-specific.yaml create mode 100644 src/test/resources/checks/v3/format/OAR007/with-wrong-ref.json create mode 100644 src/test/resources/checks/v3/format/OAR007/with-wrong-ref.yaml create mode 100644 src/test/resources/checks/v3/format/OAR010/with-204-response.json create mode 100644 src/test/resources/checks/v3/format/OAR010/with-204-response.yaml create mode 100644 src/test/resources/checks/v3/format/OAR010/with-default-mixed-case.json create mode 100644 src/test/resources/checks/v3/format/OAR010/with-default-mixed-case.yaml create mode 100644 src/test/resources/checks/v3/format/OAR010/with-external-ref.json create mode 100644 src/test/resources/checks/v3/format/OAR010/with-external-ref.yaml create mode 100644 src/test/resources/checks/v3/format/OAR010/with-wrong-default-and-ref.json create mode 100644 src/test/resources/checks/v3/format/OAR010/with-wrong-default-and-ref.yaml create mode 100644 src/test/resources/checks/v31/apim/OAR005/extensive-api.json create mode 100644 src/test/resources/checks/v31/apim/OAR005/extensive-api.yaml create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-all-verbs.json create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-all-verbs.yaml create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-callback-operations.json create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-callback-operations.yaml create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-chained-ref-security.json create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-chained-ref-security.yaml create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-ref-scope.json create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-ref-scope.yaml create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-ref-security.json create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-ref-security.yaml create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-scope-key-not-name.json create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-scope-key-not-name.yaml create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-scopes-as-map.json create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-scopes-as-map.yaml create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-webhook-operations.json create mode 100644 src/test/resources/checks/v31/apim/OAR005/with-webhook-operations.yaml create mode 100644 src/test/resources/checks/v31/apim/OAR005/without-security.json create mode 100644 src/test/resources/checks/v31/apim/OAR005/without-security.yaml create mode 100644 src/test/resources/checks/v31/format/OAR007/with-204-response.json create mode 100644 src/test/resources/checks/v31/format/OAR007/with-204-response.yaml create mode 100644 src/test/resources/checks/v31/format/OAR007/with-chained-ref.json create mode 100644 src/test/resources/checks/v31/format/OAR007/with-chained-ref.yaml create mode 100644 src/test/resources/checks/v31/format/OAR007/with-default-and-ref.json create mode 100644 src/test/resources/checks/v31/format/OAR007/with-default-and-ref.yaml create mode 100644 src/test/resources/checks/v31/format/OAR007/with-default-response-key.json create mode 100644 src/test/resources/checks/v31/format/OAR007/with-default-response-key.yaml create mode 100644 src/test/resources/checks/v31/format/OAR007/with-external-ref.json create mode 100644 src/test/resources/checks/v31/format/OAR007/with-external-ref.yaml create mode 100644 src/test/resources/checks/v31/format/OAR007/with-multiple-operations.json create mode 100644 src/test/resources/checks/v31/format/OAR007/with-multiple-operations.yaml create mode 100644 src/test/resources/checks/v31/format/OAR007/with-specific.json create mode 100644 src/test/resources/checks/v31/format/OAR007/with-specific.yaml create mode 100644 src/test/resources/checks/v31/format/OAR007/with-wrong-ref.json create mode 100644 src/test/resources/checks/v31/format/OAR007/with-wrong-ref.yaml create mode 100644 src/test/resources/checks/v31/format/OAR010/with-204-response.json create mode 100644 src/test/resources/checks/v31/format/OAR010/with-204-response.yaml create mode 100644 src/test/resources/checks/v31/format/OAR010/with-default-mixed-case.json create mode 100644 src/test/resources/checks/v31/format/OAR010/with-default-mixed-case.yaml create mode 100644 src/test/resources/checks/v31/format/OAR010/with-wrong-default-and-ref.json create mode 100644 src/test/resources/checks/v31/format/OAR010/with-wrong-default-and-ref.yaml create mode 100644 src/test/resources/checks/v32/apim/OAR005/extensive-api.json create mode 100644 src/test/resources/checks/v32/apim/OAR005/extensive-api.yaml create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-additional-operations.json create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-additional-operations.yaml create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-all-verbs.json create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-all-verbs.yaml create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-callback-operations.json create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-callback-operations.yaml create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-chained-ref-security.json create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-chained-ref-security.yaml create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-ref-scope.json create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-ref-scope.yaml create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-ref-security.json create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-ref-security.yaml create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-scope-key-not-name.json create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-scope-key-not-name.yaml create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-scopes-as-map.json create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-scopes-as-map.yaml create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-webhook-operations.json create mode 100644 src/test/resources/checks/v32/apim/OAR005/with-webhook-operations.yaml create mode 100644 src/test/resources/checks/v32/apim/OAR005/without-security.json create mode 100644 src/test/resources/checks/v32/apim/OAR005/without-security.yaml create mode 100644 src/test/resources/checks/v32/format/OAR007/with-204-response.json create mode 100644 src/test/resources/checks/v32/format/OAR007/with-204-response.yaml create mode 100644 src/test/resources/checks/v32/format/OAR007/with-chained-ref.json create mode 100644 src/test/resources/checks/v32/format/OAR007/with-chained-ref.yaml create mode 100644 src/test/resources/checks/v32/format/OAR007/with-default-and-ref.json create mode 100644 src/test/resources/checks/v32/format/OAR007/with-default-and-ref.yaml create mode 100644 src/test/resources/checks/v32/format/OAR007/with-default-response-key.json create mode 100644 src/test/resources/checks/v32/format/OAR007/with-default-response-key.yaml create mode 100644 src/test/resources/checks/v32/format/OAR007/with-external-ref.json create mode 100644 src/test/resources/checks/v32/format/OAR007/with-external-ref.yaml create mode 100644 src/test/resources/checks/v32/format/OAR007/with-multiple-operations.json create mode 100644 src/test/resources/checks/v32/format/OAR007/with-multiple-operations.yaml create mode 100644 src/test/resources/checks/v32/format/OAR007/with-specific.json create mode 100644 src/test/resources/checks/v32/format/OAR007/with-specific.yaml create mode 100644 src/test/resources/checks/v32/format/OAR007/with-wrong-ref.json create mode 100644 src/test/resources/checks/v32/format/OAR007/with-wrong-ref.yaml create mode 100644 src/test/resources/checks/v32/format/OAR010/with-204-response.json create mode 100644 src/test/resources/checks/v32/format/OAR010/with-204-response.yaml create mode 100644 src/test/resources/checks/v32/format/OAR010/with-default-mixed-case.json create mode 100644 src/test/resources/checks/v32/format/OAR010/with-default-mixed-case.yaml create mode 100644 src/test/resources/checks/v32/format/OAR010/with-wrong-default-and-ref.json create mode 100644 src/test/resources/checks/v32/format/OAR010/with-wrong-default-and-ref.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 2814ab30..cb0cb08c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.6.0-beta-6] - 2026-09-10 + +### Fixed + +- OAR005 - UndefinedWso2ScopeUse - Resolve a `$ref` on `x-wso2-security` and on each individual scope, and iterate map-form `x-wso2-scopes` in addition to the array form (shared with `AbstractWso2ScopesCheck` through new `JsonNodeUtils` helpers), so an operation whose `x-scope` names a scope declared behind a reference or under a mapping key is no longer reported. Also accept the `~`/`Null`/`NULL` null spellings for the operation's `x-scope` (previously only the lowercase `null` scalar was treated as null). Matching remains on the scope `name` only, never on `key`. +- OAR009 / OAR010 - DefaultRequestMediaType / DefaultResponseMediaType - `AbstractDefaultMediaTypeCheck` now compares `default-media-type` and the document's actual media types case-insensitively (matching Spectral's `apq-response-media-type`), so a spec written with mixed-case media types (e.g. `Application/JSON`) or a `default-media-type` property configured with different casing no longer diverges from Spectral. +- OAR007 - UndefinedResponseMediaType - Fixed the rule description: paragraph 1 wrongly stated "the request data formats must be defined" and referenced the `"consumes"` keyword (copy-pasted from OAR006); corrected to describe response media types and the `"produces"` keyword, matching the already-correct Spanish translation and the rest of the description. + ## [1.6.0-beta-5] - 2026-09-09 ### Added diff --git a/pom.xml b/pom.xml index a1d135d2..91b706c0 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.apiaddicts.apitools.dosonarapi sonaropenapi-rules-community - 1.6.0-beta-4 + 1.6.0-beta-6 sonar-plugin SonarQube OpenAPI Community Rules diff --git a/src/main/java/apiaddicts/sonar/openapi/checks/apim/wso2/AbstractWso2ScopesCheck.java b/src/main/java/apiaddicts/sonar/openapi/checks/apim/wso2/AbstractWso2ScopesCheck.java index 7a0d5899..fa31620b 100644 --- a/src/main/java/apiaddicts/sonar/openapi/checks/apim/wso2/AbstractWso2ScopesCheck.java +++ b/src/main/java/apiaddicts/sonar/openapi/checks/apim/wso2/AbstractWso2ScopesCheck.java @@ -10,7 +10,6 @@ import apiaddicts.sonar.openapi.utils.JsonNodeUtils; import org.apiaddicts.apitools.dosonarapi.sslr.yaml.grammar.JsonNode; -import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -33,20 +32,12 @@ protected JsonNode scopesKeyNode() { } private void visitV2NV3Node(JsonNode node) { - JsonNode securityNode = node.get("x-wso2-security"); - if (!securityNode.isMissing()) securityNode = JsonNodeUtils.resolve(securityNode); - JsonNode apimNode = securityNode.get("apim"); - JsonNode scopesNode = apimNode.get("x-wso2-scopes"); - scopesKeyNode = JsonNodeUtils.propertyKey(apimNode, "x-wso2-scopes"); + JsonNode apimNode = JsonNodeUtils.getWso2ApimNode(node); + JsonNode scopesNode = apimNode.get(JsonNodeUtils.WSO2_SCOPES); + scopesKeyNode = JsonNodeUtils.propertyKey(apimNode, JsonNodeUtils.WSO2_SCOPES); visitScopesNode(scopesNode); if (scopesNode.isMissing() || scopesNode.isNull()) return; - List rawScopes = scopesNode.isObject() - ? new ArrayList<>(scopesNode.propertyMap().values()) - : scopesNode.elements(); - List scopes = new ArrayList<>(rawScopes.size()); - for (JsonNode scope : rawScopes) { - scopes.add(JsonNodeUtils.resolve(scope)); - } + List scopes = JsonNodeUtils.getWso2Scopes(scopesNode); visitScopes(scopes); scopes.forEach(this::visitScope); } diff --git a/src/main/java/apiaddicts/sonar/openapi/checks/apim/wso2/OAR002ValidWso2ScopesCheck.java b/src/main/java/apiaddicts/sonar/openapi/checks/apim/wso2/OAR002ValidWso2ScopesCheck.java index e588b1e0..37fcc3a7 100644 --- a/src/main/java/apiaddicts/sonar/openapi/checks/apim/wso2/OAR002ValidWso2ScopesCheck.java +++ b/src/main/java/apiaddicts/sonar/openapi/checks/apim/wso2/OAR002ValidWso2ScopesCheck.java @@ -1,14 +1,11 @@ package apiaddicts.sonar.openapi.checks.apim.wso2; -import com.google.common.collect.ImmutableSet; -import com.sonar.sslr.api.Token; import org.sonar.check.Rule; import apiaddicts.sonar.openapi.utils.JsonNodeUtils; import org.apiaddicts.apitools.dosonarapi.sslr.yaml.grammar.JsonNode; import java.util.List; import java.util.Map; -import java.util.Set; @Rule(key = OAR002ValidWso2ScopesCheck.KEY) public class OAR002ValidWso2ScopesCheck extends AbstractWso2ScopesCheck { @@ -16,7 +13,6 @@ public class OAR002ValidWso2ScopesCheck extends AbstractWso2ScopesCheck { public static final String KEY = "OAR002"; private static final String MESSAGE = "OAR002.error"; private static final String MESSAGE_PROP = "OAR002.error-property"; - private static final Set NULL_SPELLINGS = ImmutableSet.of("~", "Null", "NULL"); private JsonNode scopesNode; @@ -63,15 +59,9 @@ private JsonNode scopeLocation(JsonNode scope) { } private boolean isEmpty(JsonNode property) { - if (isNullScalar(property)) return true; + if (JsonNodeUtils.isNullScalar(property)) return true; if (property.isArray()) return property.elements().isEmpty(); if (property.isObject()) return property.propertyMap().isEmpty(); return property.getTokenValue().trim().equals(""); } - - private boolean isNullScalar(JsonNode property) { - if (property.isNull()) return true; - Token token = property.getToken(); - return token != null && NULL_SPELLINGS.contains(token.getOriginalValue()); - } } diff --git a/src/main/java/apiaddicts/sonar/openapi/checks/apim/wso2/OAR005UndefinedWso2ScopeUseCheck.java b/src/main/java/apiaddicts/sonar/openapi/checks/apim/wso2/OAR005UndefinedWso2ScopeUseCheck.java index 22dc33d3..ad7de94d 100644 --- a/src/main/java/apiaddicts/sonar/openapi/checks/apim/wso2/OAR005UndefinedWso2ScopeUseCheck.java +++ b/src/main/java/apiaddicts/sonar/openapi/checks/apim/wso2/OAR005UndefinedWso2ScopeUseCheck.java @@ -2,14 +2,12 @@ import com.sonar.sslr.api.AstNode; import org.sonar.check.Rule; +import apiaddicts.sonar.openapi.utils.JsonNodeUtils; import org.apiaddicts.apitools.dosonarapi.sslr.yaml.grammar.JsonNode; -import java.util.Collections; import java.util.Set; import java.util.stream.Collectors; -import static java.util.Objects.isNull; - @Rule(key = OAR005UndefinedWso2ScopeUseCheck.KEY) public class OAR005UndefinedWso2ScopeUseCheck extends AbstractWso2OperationCheck { @@ -26,18 +24,13 @@ protected void visitFile(JsonNode root) { private Set getScopes(JsonNode root) { - JsonNode scopes = root - .get("x-wso2-security") - .get("apim") - .get("x-wso2-scopes"); - - if (scopes.isMissing() || scopes.isNull()) { - return Collections.emptySet(); - } + JsonNode scopes = JsonNodeUtils + .getWso2ApimNode(root) + .get(JsonNodeUtils.WSO2_SCOPES); - return scopes.elements().stream() + return JsonNodeUtils.getWso2Scopes(scopes).stream() .map(node -> node.get("name")) - .filter(node -> !node.isMissing() && !node.isNull()) + .filter(node -> !node.isMissing() && !JsonNodeUtils.isNullScalar(node)) .map(AstNode::getTokenValue) .collect(Collectors.toSet()); } @@ -49,12 +42,8 @@ protected void visitOperationNode(JsonNode node) { if (scopeNode.isMissing()) return; - String scope = scopeNode.isNull() - ? null - : scopeNode.getTokenValue(); - - if (isNull(scope) || !definedScopes.contains(scope)) { + if (JsonNodeUtils.isNullScalar(scopeNode) || !definedScopes.contains(scopeNode.getTokenValue())) { addIssue(KEY, translate(MESSAGE), scopeNode); } } -} \ No newline at end of file +} diff --git a/src/main/java/apiaddicts/sonar/openapi/checks/format/AbstractDefaultMediaTypeCheck.java b/src/main/java/apiaddicts/sonar/openapi/checks/format/AbstractDefaultMediaTypeCheck.java index 1da0417d..019a29d1 100644 --- a/src/main/java/apiaddicts/sonar/openapi/checks/format/AbstractDefaultMediaTypeCheck.java +++ b/src/main/java/apiaddicts/sonar/openapi/checks/format/AbstractDefaultMediaTypeCheck.java @@ -41,6 +41,7 @@ public abstract class AbstractDefaultMediaTypeCheck extends BaseCheck { defaultValue = DEFAULT_MEDIA_TYPE_VALUE) public String defaultMediaType = DEFAULT_MEDIA_TYPE_VALUE; + private String defaultMediaTypeLower; private boolean globalSupportsDefaultMimeType = false; protected AbstractDefaultMediaTypeCheck(String key, String section, String message) { @@ -60,6 +61,7 @@ protected void visitFile(JsonNode root) { .map(String::trim) .map(String::toLowerCase) .collect(Collectors.toSet()); + defaultMediaTypeLower = defaultMediaType.toLowerCase(); globalSupportsDefaultMimeType = (root.getType() instanceof OpenApi2Grammar) && supportsDefaultMimeTypeV2(root); } @@ -141,18 +143,21 @@ private boolean supportsDefaultMimeTypeV2(JsonNode node) { List mimeTypes = consumes.elements().stream() .map(AstNode::getTokenValue) + .map(String::toLowerCase) .collect(Collectors.toList()); - return mimeTypes.stream().anyMatch(mediaTypeExceptions::contains) || - mimeTypes.stream().anyMatch(defaultMediaType::equals); + return mimeTypes.stream().anyMatch(mediaTypeExceptions::contains) || + mimeTypes.stream().anyMatch(defaultMediaTypeLower::equals); } private boolean supportsDefaultMimeTypeV3(JsonNode content) { if (content.isMissing() || content.isNull()) return false; - Set keys = content.propertyMap().keySet(); + Set keys = content.propertyMap().keySet().stream() + .map(String::toLowerCase) + .collect(Collectors.toSet()); return keys.stream().anyMatch(mediaTypeExceptions::contains) || - keys.stream().anyMatch(defaultMediaType::equals); + keys.stream().anyMatch(defaultMediaTypeLower::equals); } } diff --git a/src/main/java/apiaddicts/sonar/openapi/utils/JsonNodeUtils.java b/src/main/java/apiaddicts/sonar/openapi/utils/JsonNodeUtils.java index 4380a62e..77c657c9 100644 --- a/src/main/java/apiaddicts/sonar/openapi/utils/JsonNodeUtils.java +++ b/src/main/java/apiaddicts/sonar/openapi/utils/JsonNodeUtils.java @@ -18,10 +18,15 @@ import java.io.InputStreamReader; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; +import com.google.common.collect.ImmutableSet; import com.sonar.sslr.api.AstNodeType; +import com.sonar.sslr.api.Token; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; @@ -44,6 +49,10 @@ private JsonNodeUtils() { public static final String TYPE_INTEGER = "integer"; public static final String TYPE_BOOLEAN = "boolean"; public static final String TYPE_ANY = "*"; + public static final String WSO2_SECURITY = "x-wso2-security"; + public static final String WSO2_APIM = "apim"; + public static final String WSO2_SCOPES = "x-wso2-scopes"; + private static final Set NULL_SPELLINGS = ImmutableSet.of("~", "Null", "NULL"); private static String lastFetchedContent = ""; public static JsonNode resolve(JsonNode original) { @@ -64,6 +73,31 @@ public static JsonNode resolve(JsonNode original) { return current; } + public static JsonNode getWso2ApimNode(JsonNode root) { + JsonNode securityNode = root.get(WSO2_SECURITY); + if (!securityNode.isMissing()) securityNode = resolve(securityNode); + return securityNode.get(WSO2_APIM); + } + + public static List getWso2Scopes(JsonNode scopesNode) { + if (scopesNode == null || scopesNode.isMissing() || scopesNode.isNull()) return Collections.emptyList(); + List rawScopes = scopesNode.isObject() + ? new ArrayList<>(scopesNode.propertyMap().values()) + : scopesNode.elements(); + List scopes = new ArrayList<>(rawScopes.size()); + for (JsonNode scope : rawScopes) { + scopes.add(resolve(scope)); + } + return scopes; + } + + public static boolean isNullScalar(JsonNode node) { + if (node == null) return true; + if (node.isNull()) return true; + Token token = node.getToken(); + return token != null && NULL_SPELLINGS.contains(token.getOriginalValue()); + } + public static boolean isExternalRef (JsonNode original){ if (original.isRef()) { diff --git a/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/apim/wso2/OAR005.html b/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/apim/wso2/OAR005.html index df268cc0..1cb5f3fc 100644 --- a/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/apim/wso2/OAR005.html +++ b/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/apim/wso2/OAR005.html @@ -1,33 +1,9 @@

- Los scopes disponibles se definen al final del documento de definición, a nivel raíz. Se definen mediante la siguiente estructura: + Un scope incorrecto puede causar problemas al importar la definición de la API en WSO2 o permitir que cualquier usuario invoque el endpoint.

-
-x-wso2-security:
-  apim:
-  x-wso2-scopes:
-    - name: Nombre_scope_1
-      description: ""
-      key: Etiqueta_scope_1
-      roles: "Role_1, Role_2, …, Role_n"
-    - name: Nombre_scope_2>
-      description: ""
-      key: Etiqueta_scope_2
-      roles: "Role_1,Role_2,…,Role_n"
-

- Cada elemento del array x-wso2-scopes contiene los siguientes elementos: + El x-scope de la operación debe coincidir con el name de un scope declarado. El key del scope nunca se tiene en cuenta.

-
    -
  • name: El nombre que recibirá el scope. -
      -
    • La nomenclatura es {Código POAP del API}_sc_{nombre-descriptivo}
    • -
    • Por ejemplo: USUG-API_sc_user-scope
    • -
    -
  • -
  • description: Breve descripción del scope. Opcional.
  • -
  • key: Etiqueta del scope. Se recomienda que coincida con el nombre para evitar confusiones.
  • -
  • roles: Cadena con todos los roles asociados al scope separados por coma (se corresponde con los perfiles de cada Aplicación obtenidos de USUG).
  • -

Ejemplo de código no compatible (OpenAPI 2)

 swagger: "2.0"
diff --git a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/apim/wso2/OAR005.html b/src/main/resources/org/sonar/l10n/openapi/rules/openapi/apim/wso2/OAR005.html
index 97c4df10..a3176ec1 100644
--- a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/apim/wso2/OAR005.html
+++ b/src/main/resources/org/sonar/l10n/openapi/rules/openapi/apim/wso2/OAR005.html
@@ -1,4 +1,5 @@
 

A wrong scope may cause problems to import the API definition into WSO2 or allow all users to call the endpoint.

+

The operation x-scope must match the name of a declared scope. The scope key is never taken into account.

Noncompliant Code Example (OpenAPI 2)

 swagger: "2.0"
diff --git a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/format/OAR007.html b/src/main/resources/org/sonar/l10n/openapi/rules/openapi/format/OAR007.html
index 09f6c98c..5a748ea2 100644
--- a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/format/OAR007.html
+++ b/src/main/resources/org/sonar/l10n/openapi/rules/openapi/format/OAR007.html
@@ -1,5 +1,5 @@
-

When defining an API, the request data formats must be defined.

-

For OpenAPI 2 specify at least a MIME Type understood by the API in the "consumes" keyword is mandatory.

+

When defining an API, the response data formats must be defined.

+

For OpenAPI 2 specify at least a MIME Type understood by the API in the "produces" keyword is mandatory.

For OpenAPI 3 specify at least a Media Type in the content of the response body is mandatory.

Noncompliant Code Example (OpenAPI 2)

diff --git a/src/test/java/apiaddicts/sonar/openapi/checks/apim/wso2/OAR005UndefinedWso2ScopeUseCheckTest.java b/src/test/java/apiaddicts/sonar/openapi/checks/apim/wso2/OAR005UndefinedWso2ScopeUseCheckTest.java
index d569214d..493e6652 100644
--- a/src/test/java/apiaddicts/sonar/openapi/checks/apim/wso2/OAR005UndefinedWso2ScopeUseCheckTest.java
+++ b/src/test/java/apiaddicts/sonar/openapi/checks/apim/wso2/OAR005UndefinedWso2ScopeUseCheckTest.java
@@ -72,6 +72,254 @@ public void verifyInV32WithCorrectOperationScope() {
         verifyV32("with-correct-operation-scope");
     }
 
+    @Test
+    public void verifyInV2WithRefSecurity() {
+        verifyV2("with-ref-security");
+    }
+    @Test
+    public void verifyInV3WithRefSecurity() {
+        verifyV3("with-ref-security");
+    }
+    @Test
+    public void verifyInV31WithRefSecurity() {
+        verifyV31("with-ref-security");
+    }
+    @Test
+    public void verifyInV32WithRefSecurity() {
+        verifyV32("with-ref-security");
+    }
+
+    @Test
+    public void verifyInV2WithChainedRefSecurity() {
+        verifyV2("with-chained-ref-security");
+    }
+    @Test
+    public void verifyInV3WithChainedRefSecurity() {
+        verifyV3("with-chained-ref-security");
+    }
+    @Test
+    public void verifyInV31WithChainedRefSecurity() {
+        verifyV31("with-chained-ref-security");
+    }
+    @Test
+    public void verifyInV32WithChainedRefSecurity() {
+        verifyV32("with-chained-ref-security");
+    }
+
+    @Test
+    public void verifyInV2WithScopesAsMap() {
+        verifyV2("with-scopes-as-map");
+    }
+    @Test
+    public void verifyInV3WithScopesAsMap() {
+        verifyV3("with-scopes-as-map");
+    }
+    @Test
+    public void verifyInV31WithScopesAsMap() {
+        verifyV31("with-scopes-as-map");
+    }
+    @Test
+    public void verifyInV32WithScopesAsMap() {
+        verifyV32("with-scopes-as-map");
+    }
+
+    @Test
+    public void verifyInV2WithRefScope() {
+        verifyV2("with-ref-scope");
+    }
+    @Test
+    public void verifyInV3WithRefScope() {
+        verifyV3("with-ref-scope");
+    }
+    @Test
+    public void verifyInV31WithRefScope() {
+        verifyV31("with-ref-scope");
+    }
+    @Test
+    public void verifyInV32WithRefScope() {
+        verifyV32("with-ref-scope");
+    }
+
+    @Test
+    public void verifyInV2WithScopeKeyNotName() {
+        verifyV2("with-scope-key-not-name");
+    }
+    @Test
+    public void verifyInV3WithScopeKeyNotName() {
+        verifyV3("with-scope-key-not-name");
+    }
+    @Test
+    public void verifyInV31WithScopeKeyNotName() {
+        verifyV31("with-scope-key-not-name");
+    }
+    @Test
+    public void verifyInV32WithScopeKeyNotName() {
+        verifyV32("with-scope-key-not-name");
+    }
+
+    @Test
+    public void verifyInV2WithoutSecurity() {
+        verifyV2("without-security");
+    }
+    @Test
+    public void verifyInV3WithoutSecurity() {
+        verifyV3("without-security");
+    }
+    @Test
+    public void verifyInV31WithoutSecurity() {
+        verifyV31("without-security");
+    }
+    @Test
+    public void verifyInV32WithoutSecurity() {
+        verifyV32("without-security");
+    }
+
+    @Test
+    public void verifyInV3WithNullSecurity() {
+        verifyV3("with-null-security.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithScalarSecurity() {
+        verifyV3("with-scalar-security.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithArraySecurity() {
+        verifyV3("with-array-security.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithoutApim() {
+        verifyV3("without-apim.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithNullApim() {
+        verifyV3("with-null-apim.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithoutScopes() {
+        verifyV3("without-scopes.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithNullScopes() {
+        verifyV3("with-null-scopes.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithEmptyArrayScopes() {
+        verifyV3("with-empty-array-scopes.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithEmptyObjectScopes() {
+        verifyV3("with-empty-object-scopes.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithScalarScopes() {
+        verifyV3("with-scalar-scopes.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithCyclicRefSecurity() {
+        verifyV3("with-cyclic-ref-security.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithDanglingRefSecurity() {
+        verifyV3("with-dangling-ref-security.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithMalformedScopes() {
+        verifyV3("with-malformed-scopes.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithXScopeNullSpellings() {
+        verifyV3("with-x-scope-null-spellings.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithXScopeScalarTypes() {
+        verifyV3("with-x-scope-scalar-types.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithXScopeCollections() {
+        verifyV3("with-x-scope-collections.yaml");
+    }
+
+    @Test
+    public void verifyInV3WithXScopeBlockCollections() {
+        verifyV3("with-x-scope-block-collections.yaml");
+    }
+
+    @Test
+    public void verifyInV2WithAllVerbs() {
+        verifyV2("with-all-verbs");
+    }
+    @Test
+    public void verifyInV3WithAllVerbs() {
+        verifyV3("with-all-verbs");
+    }
+    @Test
+    public void verifyInV31WithAllVerbs() {
+        verifyV31("with-all-verbs");
+    }
+    @Test
+    public void verifyInV32WithAllVerbs() {
+        verifyV32("with-all-verbs");
+    }
+
+    @Test
+    public void verifyInV3WithCallbackOperations() {
+        verifyV3("with-callback-operations");
+    }
+    @Test
+    public void verifyInV31WithCallbackOperations() {
+        verifyV31("with-callback-operations");
+    }
+    @Test
+    public void verifyInV32WithCallbackOperations() {
+        verifyV32("with-callback-operations");
+    }
+
+    @Test
+    public void verifyInV31WithWebhookOperations() {
+        verifyV31("with-webhook-operations");
+    }
+    @Test
+    public void verifyInV32WithWebhookOperations() {
+        verifyV32("with-webhook-operations");
+    }
+
+    @Test
+    public void verifyInV32WithAdditionalOperations() {
+        verifyV32("with-additional-operations");
+    }
+
+    @Test
+    public void verifyInV2Extensive() {
+        verifyV2("extensive-api");
+    }
+    @Test
+    public void verifyInV3Extensive() {
+        verifyV3("extensive-api");
+    }
+    @Test
+    public void verifyInV31Extensive() {
+        verifyV31("extensive-api");
+    }
+    @Test
+    public void verifyInV32Extensive() {
+        verifyV32("extensive-api");
+    }
+
     @Override
     public void verifyRule() {
         assertRuleProperties("OAR005 - UndefinedWso2ScopeUse - WSO2 scope definition does not exists", RuleType.VULNERABILITY, Severity.BLOCKER, tags("api-manager", "vulnerability", "wso2"));
diff --git a/src/test/java/apiaddicts/sonar/openapi/checks/format/OAR007UndefinedResponseMediaTypeCheckTest.java b/src/test/java/apiaddicts/sonar/openapi/checks/format/OAR007UndefinedResponseMediaTypeCheckTest.java
index 2b4eb51c..559a31a4 100644
--- a/src/test/java/apiaddicts/sonar/openapi/checks/format/OAR007UndefinedResponseMediaTypeCheckTest.java
+++ b/src/test/java/apiaddicts/sonar/openapi/checks/format/OAR007UndefinedResponseMediaTypeCheckTest.java
@@ -38,6 +38,11 @@ public void verifyInV2WithoutAnything() {
         verifyV2("without-anything");
     }
 
+    @Test
+    public void verifyInV2WithSpecificPut() {
+        verifyV2("with-specific-put");
+    }
+
     @Test
     public void verifyInV3WithoutAnything() {
         verifyV3("without-anything");
@@ -51,6 +56,110 @@ public void verifyInV32WithoutAnything() {
         verifyV32("without-anything");
     }
 
+    @Test
+    public void verifyInV3WithSpecific() {
+        verifyV3("with-specific");
+    }
+    @Test
+    public void verifyInV31WithSpecific() {
+        verifyV31("with-specific");
+    }
+    @Test
+    public void verifyInV32WithSpecific() {
+        verifyV32("with-specific");
+    }
+
+    @Test
+    public void verifyInV3WithMultipleOperations() {
+        verifyV3("with-multiple-operations");
+    }
+    @Test
+    public void verifyInV31WithMultipleOperations() {
+        verifyV31("with-multiple-operations");
+    }
+    @Test
+    public void verifyInV32WithMultipleOperations() {
+        verifyV32("with-multiple-operations");
+    }
+
+    @Test
+    public void verifyInV3WithDefaultAndRef() {
+        verifyV3("with-default-and-ref");
+    }
+    @Test
+    public void verifyInV31WithDefaultAndRef() {
+        verifyV31("with-default-and-ref");
+    }
+    @Test
+    public void verifyInV32WithDefaultAndRef() {
+        verifyV32("with-default-and-ref");
+    }
+
+    @Test
+    public void verifyInV3WithWrongRef() {
+        verifyV3("with-wrong-ref");
+    }
+    @Test
+    public void verifyInV31WithWrongRef() {
+        verifyV31("with-wrong-ref");
+    }
+    @Test
+    public void verifyInV32WithWrongRef() {
+        verifyV32("with-wrong-ref");
+    }
+
+    @Test
+    public void verifyInV3WithChainedRef() {
+        verifyV3("with-chained-ref");
+    }
+    @Test
+    public void verifyInV31WithChainedRef() {
+        verifyV31("with-chained-ref");
+    }
+    @Test
+    public void verifyInV32WithChainedRef() {
+        verifyV32("with-chained-ref");
+    }
+
+    @Test
+    public void verifyInV3WithExternalRef() {
+        verifyV3("with-external-ref");
+    }
+    @Test
+    public void verifyInV31WithExternalRef() {
+        verifyV31("with-external-ref");
+    }
+    @Test
+    public void verifyInV32WithExternalRef() {
+        verifyV32("with-external-ref");
+    }
+
+    @Test
+    public void verifyInV3With204Response() {
+        verifyV3("with-204-response");
+    }
+    @Test
+    public void verifyInV31With204Response() {
+        verifyV31("with-204-response");
+    }
+    @Test
+    public void verifyInV32With204Response() {
+        verifyV32("with-204-response");
+    }
+
+    @Test
+    public void verifyInV3WithDefaultResponseKey() {
+        verifyV3("with-default-response-key");
+    }
+    @Test
+    public void verifyInV31WithDefaultResponseKey() {
+        verifyV31("with-default-response-key");
+    }
+    @Test
+    public void verifyInV32WithDefaultResponseKey() {
+        verifyV32("with-default-response-key");
+    }
+
     @Override
     public void verifyRule() {
         assertRuleProperties("OAR007 - UndefinedResponseMediaType - APIs must define response media types supported by the API", RuleType.BUG, Severity.BLOCKER, tags("format"));
diff --git a/src/test/java/apiaddicts/sonar/openapi/checks/format/OAR010DefaultResponseMediaTypeCheckTest.java b/src/test/java/apiaddicts/sonar/openapi/checks/format/OAR010DefaultResponseMediaTypeCheckTest.java
index f18c65a5..8cea8c98 100644
--- a/src/test/java/apiaddicts/sonar/openapi/checks/format/OAR010DefaultResponseMediaTypeCheckTest.java
+++ b/src/test/java/apiaddicts/sonar/openapi/checks/format/OAR010DefaultResponseMediaTypeCheckTest.java
@@ -49,6 +49,11 @@ public void verifyInV2WithoutAnything() {
         verifyV2("without-anything");
     }
 
+    @Test
+    public void verifyInV2WithDefaultMixedCase() {
+        verifyV2("with-default-mixed-case");
+    }
+
     @Test
     public void verifyInV3WithDefault() {
         verifyV3("with-default-and-$ref");
@@ -127,6 +132,50 @@ public void verifyInV32WithoutAnything() {
         verifyV32("without-anything");
     }
 
+    @Test
+    public void verifyInV3WithDefaultMixedCase() {
+        verifyV3("with-default-mixed-case");
+    }
+    @Test
+    public void verifyInV31WithDefaultMixedCase() {
+        verifyV31("with-default-mixed-case");
+    }
+    @Test
+    public void verifyInV32WithDefaultMixedCase() {
+        verifyV32("with-default-mixed-case");
+    }
+
+    @Test
+    public void verifyInV3WithWrongDefaultAndRef() {
+        verifyV3("with-wrong-default-and-ref");
+    }
+    @Test
+    public void verifyInV31WithWrongDefaultAndRef() {
+        verifyV31("with-wrong-default-and-ref");
+    }
+    @Test
+    public void verifyInV32WithWrongDefaultAndRef() {
+        verifyV32("with-wrong-default-and-ref");
+    }
+
+    @Test
+    public void verifyInV3With204Response() {
+        verifyV3("with-204-response");
+    }
+    @Test
+    public void verifyInV31With204Response() {
+        verifyV31("with-204-response");
+    }
+    @Test
+    public void verifyInV32With204Response() {
+        verifyV32("with-204-response");
+    }
+
+    @Test
+    public void verifyInV3WithExternalRef() {
+        verifyV3("with-external-ref");
+    }
+
     @Override
     public void verifyRule() {
         assertRuleProperties("OAR010 - DefaultResponseMediaType - Should indicate the default response media type", RuleType.BUG, Severity.MINOR, tags("format"));
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/extensive-api.json b/src/test/resources/checks/v2/apim/wso2/OAR005/extensive-api.json
new file mode 100644
index 00000000..ea7a8928
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/extensive-api.json
@@ -0,0 +1,241 @@
+{
+  "swagger" : "2.0",
+  "info" : {
+    "version" : "2.1.0",
+    "title" : "Retail Storefront API",
+    "description" : "Public-facing REST API for the retail storefront covering product catalog browsing, order placement, account management, and platform administration."
+  },
+  "paths" : {
+    "/catalog/products" : {
+      "get" : {
+        "operationId" : "get_catalog_products",
+        "summary" : "List products",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_READ"
+      },
+      "post" : {
+        "operationId" : "post_catalog_products",
+        "summary" : "Create a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_WRITE"
+      }
+    },
+    "/catalog/products/{productId}" : {
+      "get" : {
+        "operationId" : "get_catalog_products_productId",
+        "summary" : "Get a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_READ"
+      },
+      "put" : {
+        "operationId" : "put_catalog_products_productId",
+        "summary" : "Replace a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_WRITE"
+      },
+      "delete" : {
+        "operationId" : "delete_catalog_products_productId",
+        "summary" : "Delete a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_WRITE"
+      }
+    },
+    "/orders" : {
+      "get" : {
+        "operationId" : "get_orders",
+        "summary" : "List orders",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_READ"
+      },
+      "post" : {
+        "operationId" : "post_orders",
+        "summary" : "Place an order",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_WRITE"
+      }
+    },
+    "/orders/{orderId}" : {
+      "get" : {
+        "operationId" : "get_orders_orderId",
+        "summary" : "Get an order",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_READ"
+      },
+      "delete" : {
+        "operationId" : "delete_orders_orderId",
+        "summary" : "Cancel an order",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_WRITE"
+      }
+    },
+    "/account/profile" : {
+      "get" : {
+        "operationId" : "get_account_profile",
+        "summary" : "Get the caller's profile",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ACCOUNT_SC_READ"
+      },
+      "put" : {
+        "operationId" : "put_account_profile",
+        "summary" : "Update the caller's profile - undeclared scope",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ACCOUNT_SC_WRITE" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    },
+    "/admin/users" : {
+      "get" : {
+        "operationId" : "get_admin_users",
+        "summary" : "List platform users - matches key not name",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "admin_all" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "post" : {
+        "operationId" : "post_admin_users",
+        "summary" : "Create a platform user",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ADMIN_SC_ALL"
+      }
+    },
+    "/admin/audit-log" : {
+      "get" : {
+        "operationId" : "get_admin_audit-log",
+        "summary" : "Read the audit log",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ADMIN_SC_ALL"
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "CATALOG_SC_READ",
+        "key" : "catalog_read",
+        "roles" : "ROLE_CATALOG_READ",
+        "description" : "Allows users to browse the product catalog"
+      }, {
+        "name" : "CATALOG_SC_WRITE",
+        "key" : "catalog_write",
+        "roles" : "ROLE_CATALOG_WRITE",
+        "description" : "Allows users to create or update products"
+      }, {
+        "name" : "ORDERS_SC_READ",
+        "key" : "orders_read",
+        "roles" : "ROLE_ORDERS_READ",
+        "description" : "Allows users to view orders"
+      }, {
+        "name" : "ORDERS_SC_WRITE",
+        "key" : "orders_write",
+        "roles" : "ROLE_ORDERS_WRITE",
+        "description" : "Allows users to place or cancel orders"
+      }, {
+        "name" : "ACCOUNT_SC_READ",
+        "key" : "account_read",
+        "roles" : "ROLE_ACCOUNT_READ",
+        "description" : "Allows users to view their own account"
+      }, {
+        "name" : "ADMIN_SC_ALL",
+        "key" : "admin_all",
+        "roles" : "ROLE_ADMIN",
+        "description" : "Full administrative access"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/extensive-api.yaml b/src/test/resources/checks/v2/apim/wso2/OAR005/extensive-api.yaml
new file mode 100644
index 00000000..1477fc6a
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/extensive-api.yaml
@@ -0,0 +1,167 @@
+swagger: "2.0"
+info:
+  version: 2.1.0
+  title: Retail Storefront API
+  description: Public-facing REST API for the retail storefront covering product catalog browsing, order placement, account management, and platform administration.
+paths:
+  /catalog/products:
+    get:
+      operationId: get_catalog_products
+      summary: List products
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_READ
+    post:
+      operationId: post_catalog_products
+      summary: Create a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_WRITE
+  /catalog/products/{productId}:
+    get:
+      operationId: get_catalog_products_productId
+      summary: Get a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_READ
+    put:
+      operationId: put_catalog_products_productId
+      summary: Replace a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_WRITE
+    delete:
+      operationId: delete_catalog_products_productId
+      summary: Delete a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_WRITE
+  /orders:
+    get:
+      operationId: get_orders
+      summary: List orders
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_READ
+    post:
+      operationId: post_orders
+      summary: Place an order
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_WRITE
+  /orders/{orderId}:
+    get:
+      operationId: get_orders_orderId
+      summary: Get an order
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_READ
+    delete:
+      operationId: delete_orders_orderId
+      summary: Cancel an order
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_WRITE
+  /account/profile:
+    get:
+      operationId: get_account_profile
+      summary: Get the caller's profile
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ACCOUNT_SC_READ
+    put:
+      operationId: put_account_profile
+      summary: Update the caller's profile - undeclared scope
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ACCOUNT_SC_WRITE # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /admin/users:
+    get:
+      operationId: get_admin_users
+      summary: List platform users - matches key not name
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: admin_all # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    post:
+      operationId: post_admin_users
+      summary: Create a platform user
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ADMIN_SC_ALL
+  /admin/audit-log:
+    get:
+      operationId: get_admin_audit-log
+      summary: Read the audit log
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ADMIN_SC_ALL
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: CATALOG_SC_READ
+        key: catalog_read
+        roles: ROLE_CATALOG_READ
+        description: Allows users to browse the product catalog
+      - name: CATALOG_SC_WRITE
+        key: catalog_write
+        roles: ROLE_CATALOG_WRITE
+        description: Allows users to create or update products
+      - name: ORDERS_SC_READ
+        key: orders_read
+        roles: ROLE_ORDERS_READ
+        description: Allows users to view orders
+      - name: ORDERS_SC_WRITE
+        key: orders_write
+        roles: ROLE_ORDERS_WRITE
+        description: Allows users to place or cancel orders
+      - name: ACCOUNT_SC_READ
+        key: account_read
+        roles: ROLE_ACCOUNT_READ
+        description: Allows users to view their own account
+      - name: ADMIN_SC_ALL
+        key: admin_all
+        roles: ROLE_ADMIN
+        description: Full administrative access
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/with-all-verbs.json b/src/test/resources/checks/v2/apim/wso2/OAR005/with-all-verbs.json
new file mode 100644
index 00000000..9f34cfee
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/with-all-verbs.json
@@ -0,0 +1,77 @@
+{
+  "swagger" : "2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/a" : {
+      "x-scope" : "scope_one",
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "put" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "delete" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "options" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "head" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "patch" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "scope_one",
+        "key" : "scope_one",
+        "roles" : "role_one"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/with-all-verbs.yaml b/src/test/resources/checks/v2/apim/wso2/OAR005/with-all-verbs.yaml
new file mode 100644
index 00000000..358bc36f
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/with-all-verbs.yaml
@@ -0,0 +1,49 @@
+swagger: "2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    x-scope: scope_one
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    delete:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    options:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    head:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    patch:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        key: scope_one
+        roles: role_one
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/with-chained-ref-security.json b/src/test/resources/checks/v2/apim/wso2/OAR005/with-chained-ref-security.json
new file mode 100644
index 00000000..c4866112
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/with-chained-ref-security.json
@@ -0,0 +1,50 @@
+{
+  "swagger" : "2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_two"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "$ref" : "#/x-wso2-definitions/alias"
+  },
+  "x-wso2-definitions" : {
+    "alias" : {
+      "$ref" : "#/x-wso2-definitions/security"
+    },
+    "security" : {
+      "apim" : {
+        "x-wso2-scopes" : [ {
+          "name" : "scope_one",
+          "description" : "scope_one",
+          "key" : "scope_one",
+          "roles" : "role_one"
+        }, {
+          "name" : "scope_two",
+          "description" : "scope_two",
+          "key" : "scope_two",
+          "roles" : "role_two"
+        } ]
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/with-chained-ref-security.yaml b/src/test/resources/checks/v2/apim/wso2/OAR005/with-chained-ref-security.yaml
new file mode 100644
index 00000000..c80432d1
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/with-chained-ref-security.yaml
@@ -0,0 +1,33 @@
+swagger: "2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_two
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  $ref: "#/x-wso2-definitions/alias"
+x-wso2-definitions:
+  alias:
+    $ref: "#/x-wso2-definitions/security"
+  security:
+    apim:
+      x-wso2-scopes:
+        - name: scope_one
+          description: scope_one
+          key: scope_one
+          roles: role_one
+        - name: scope_two
+          description: scope_two
+          key: scope_two
+          roles: role_two
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-scope.json b/src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-scope.json
new file mode 100644
index 00000000..2038f1e4
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-scope.json
@@ -0,0 +1,55 @@
+{
+  "swagger" : "2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_one"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_two"
+      },
+      "put" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "scope_one",
+        "description" : "scope_one",
+        "key" : "scope_one",
+        "roles" : "role_one"
+      }, {
+        "$ref" : "#/x-wso2-definitions/scopeTwo"
+      } ]
+    }
+  },
+  "x-wso2-definitions" : {
+    "scopeTwo" : {
+      "name" : "scope_two",
+      "description" : "scope_two",
+      "key" : "scope_two",
+      "roles" : "role_two"
+    }
+  }
+}
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-scope.yaml b/src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-scope.yaml
new file mode 100644
index 00000000..6e21fea4
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-scope.yaml
@@ -0,0 +1,36 @@
+swagger: "2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_two
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        description: scope_one
+        key: scope_one
+        roles: role_one
+      - $ref: "#/x-wso2-definitions/scopeTwo"
+x-wso2-definitions:
+  scopeTwo:
+    name: scope_two
+    description: scope_two
+    key: scope_two
+    roles: role_two
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-security.json b/src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-security.json
new file mode 100644
index 00000000..498b2903
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-security.json
@@ -0,0 +1,47 @@
+{
+  "swagger" : "2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_two"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "$ref" : "#/x-wso2-definitions/security"
+  },
+  "x-wso2-definitions" : {
+    "security" : {
+      "apim" : {
+        "x-wso2-scopes" : [ {
+          "name" : "scope_one",
+          "description" : "scope_one",
+          "key" : "scope_one",
+          "roles" : "role_one"
+        }, {
+          "name" : "scope_two",
+          "description" : "scope_two",
+          "key" : "scope_two",
+          "roles" : "role_two"
+        } ]
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-security.yaml b/src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-security.yaml
new file mode 100644
index 00000000..1f5d9318
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/with-ref-security.yaml
@@ -0,0 +1,31 @@
+swagger: "2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_two
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  $ref: "#/x-wso2-definitions/security"
+x-wso2-definitions:
+  security:
+    apim:
+      x-wso2-scopes:
+        - name: scope_one
+          description: scope_one
+          key: scope_one
+          roles: role_one
+        - name: scope_two
+          description: scope_two
+          key: scope_two
+          roles: role_two
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/with-scope-key-not-name.json b/src/test/resources/checks/v2/apim/wso2/OAR005/with-scope-key-not-name.json
new file mode 100644
index 00000000..82040f6b
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/with-scope-key-not-name.json
@@ -0,0 +1,37 @@
+{
+  "swagger" : "2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "catalogue_read"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "read" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "catalogue_read",
+        "description" : "catalogue_read",
+        "key" : "read",
+        "roles" : "role_one"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/with-scope-key-not-name.yaml b/src/test/resources/checks/v2/apim/wso2/OAR005/with-scope-key-not-name.yaml
new file mode 100644
index 00000000..aa81780b
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/with-scope-key-not-name.yaml
@@ -0,0 +1,24 @@
+swagger: "2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: catalogue_read
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: read # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: catalogue_read
+        description: catalogue_read
+        key: read
+        roles: role_one
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/with-scopes-as-map.json b/src/test/resources/checks/v2/apim/wso2/OAR005/with-scopes-as-map.json
new file mode 100644
index 00000000..ffb790f6
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/with-scopes-as-map.json
@@ -0,0 +1,66 @@
+{
+  "swagger" : "2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "read_scope"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "read" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "put" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "write_scope"
+      },
+      "delete" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : {
+        "read" : {
+          "name" : "read_scope",
+          "key" : "read",
+          "roles" : "ROLE_READ",
+          "description" : "Allows users to read the catalogue"
+        },
+        "write" : {
+          "$ref" : "#/x-wso2-definitions/writeScope"
+        }
+      }
+    }
+  },
+  "x-wso2-definitions" : {
+    "writeScope" : {
+      "name" : "write_scope",
+      "key" : "write",
+      "roles" : "ROLE_WRITE",
+      "description" : "Allows users to write the catalogue"
+    }
+  }
+}
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/with-scopes-as-map.yaml b/src/test/resources/checks/v2/apim/wso2/OAR005/with-scopes-as-map.yaml
new file mode 100644
index 00000000..4fce63a7
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/with-scopes-as-map.yaml
@@ -0,0 +1,43 @@
+swagger: "2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: read_scope
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: read # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: write_scope
+    delete:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      read:
+        name: read_scope
+        key: read
+        roles: ROLE_READ
+        description: Allows users to read the catalogue
+      write:
+        $ref: "#/x-wso2-definitions/writeScope"
+x-wso2-definitions:
+  writeScope:
+    name: write_scope
+    key: write
+    roles: ROLE_WRITE
+    description: Allows users to write the catalogue
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/without-security.json b/src/test/resources/checks/v2/apim/wso2/OAR005/without-security.json
new file mode 100644
index 00000000..ed4974f3
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/without-security.json
@@ -0,0 +1,26 @@
+{
+  "swagger" : "2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_one" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v2/apim/wso2/OAR005/without-security.yaml b/src/test/resources/checks/v2/apim/wso2/OAR005/without-security.yaml
new file mode 100644
index 00000000..9eaae866
--- /dev/null
+++ b/src/test/resources/checks/v2/apim/wso2/OAR005/without-security.yaml
@@ -0,0 +1,15 @@
+swagger: "2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    post:
+      responses:
+        200:
+          description: Ok
diff --git a/src/test/resources/checks/v2/format/OAR007/with-specific-put.json b/src/test/resources/checks/v2/format/OAR007/with-specific-put.json
new file mode 100644
index 00000000..8b798cb3
--- /dev/null
+++ b/src/test/resources/checks/v2/format/OAR007/with-specific-put.json
@@ -0,0 +1,21 @@
+{
+  "swagger": "2.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "produces": [
+          "application/json"
+        ],
+        "responses": {
+          "200": {
+            "description": "Ok"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v2/format/OAR007/with-specific-put.yaml b/src/test/resources/checks/v2/format/OAR007/with-specific-put.yaml
new file mode 100644
index 00000000..21362e15
--- /dev/null
+++ b/src/test/resources/checks/v2/format/OAR007/with-specific-put.yaml
@@ -0,0 +1,13 @@
+swagger: "2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+
+paths:
+  /pets:
+    put:
+      produces:
+        - application/json
+      responses:
+        200:
+          description: Ok
diff --git a/src/test/resources/checks/v2/format/OAR010/with-default-mixed-case.json b/src/test/resources/checks/v2/format/OAR010/with-default-mixed-case.json
new file mode 100644
index 00000000..30267930
--- /dev/null
+++ b/src/test/resources/checks/v2/format/OAR010/with-default-mixed-case.json
@@ -0,0 +1,21 @@
+{
+  "swagger": "2.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "post": {
+        "produces": [
+          "Application/JSON"
+        ],
+        "responses": {
+          "200": {
+            "description": "Ok"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v2/format/OAR010/with-default-mixed-case.yaml b/src/test/resources/checks/v2/format/OAR010/with-default-mixed-case.yaml
new file mode 100644
index 00000000..c954d326
--- /dev/null
+++ b/src/test/resources/checks/v2/format/OAR010/with-default-mixed-case.yaml
@@ -0,0 +1,13 @@
+swagger: "2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+
+paths:
+  /pets:
+    post:
+      produces:
+        - Application/JSON
+      responses:
+        200:
+          description: Ok
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/extensive-api.json b/src/test/resources/checks/v3/apim/wso2/OAR005/extensive-api.json
new file mode 100644
index 00000000..62484806
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/extensive-api.json
@@ -0,0 +1,241 @@
+{
+  "openapi" : "3.0.0",
+  "info" : {
+    "version" : "2.1.0",
+    "title" : "Retail Storefront API",
+    "description" : "Public-facing REST API for the retail storefront covering product catalog browsing, order placement, account management, and platform administration."
+  },
+  "paths" : {
+    "/catalog/products" : {
+      "get" : {
+        "operationId" : "get_catalog_products",
+        "summary" : "List products",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_READ"
+      },
+      "post" : {
+        "operationId" : "post_catalog_products",
+        "summary" : "Create a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_WRITE"
+      }
+    },
+    "/catalog/products/{productId}" : {
+      "get" : {
+        "operationId" : "get_catalog_products_productId",
+        "summary" : "Get a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_READ"
+      },
+      "put" : {
+        "operationId" : "put_catalog_products_productId",
+        "summary" : "Replace a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_WRITE"
+      },
+      "delete" : {
+        "operationId" : "delete_catalog_products_productId",
+        "summary" : "Delete a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_WRITE"
+      }
+    },
+    "/orders" : {
+      "get" : {
+        "operationId" : "get_orders",
+        "summary" : "List orders",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_READ"
+      },
+      "post" : {
+        "operationId" : "post_orders",
+        "summary" : "Place an order",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_WRITE"
+      }
+    },
+    "/orders/{orderId}" : {
+      "get" : {
+        "operationId" : "get_orders_orderId",
+        "summary" : "Get an order",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_READ"
+      },
+      "delete" : {
+        "operationId" : "delete_orders_orderId",
+        "summary" : "Cancel an order",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_WRITE"
+      }
+    },
+    "/account/profile" : {
+      "get" : {
+        "operationId" : "get_account_profile",
+        "summary" : "Get the caller's profile",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ACCOUNT_SC_READ"
+      },
+      "put" : {
+        "operationId" : "put_account_profile",
+        "summary" : "Update the caller's profile - undeclared scope",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ACCOUNT_SC_WRITE" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    },
+    "/admin/users" : {
+      "get" : {
+        "operationId" : "get_admin_users",
+        "summary" : "List platform users - matches key not name",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "admin_all" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "post" : {
+        "operationId" : "post_admin_users",
+        "summary" : "Create a platform user",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ADMIN_SC_ALL"
+      }
+    },
+    "/admin/audit-log" : {
+      "get" : {
+        "operationId" : "get_admin_audit-log",
+        "summary" : "Read the audit log",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ADMIN_SC_ALL"
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "CATALOG_SC_READ",
+        "key" : "catalog_read",
+        "roles" : "ROLE_CATALOG_READ",
+        "description" : "Allows users to browse the product catalog"
+      }, {
+        "name" : "CATALOG_SC_WRITE",
+        "key" : "catalog_write",
+        "roles" : "ROLE_CATALOG_WRITE",
+        "description" : "Allows users to create or update products"
+      }, {
+        "name" : "ORDERS_SC_READ",
+        "key" : "orders_read",
+        "roles" : "ROLE_ORDERS_READ",
+        "description" : "Allows users to view orders"
+      }, {
+        "name" : "ORDERS_SC_WRITE",
+        "key" : "orders_write",
+        "roles" : "ROLE_ORDERS_WRITE",
+        "description" : "Allows users to place or cancel orders"
+      }, {
+        "name" : "ACCOUNT_SC_READ",
+        "key" : "account_read",
+        "roles" : "ROLE_ACCOUNT_READ",
+        "description" : "Allows users to view their own account"
+      }, {
+        "name" : "ADMIN_SC_ALL",
+        "key" : "admin_all",
+        "roles" : "ROLE_ADMIN",
+        "description" : "Full administrative access"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/extensive-api.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/extensive-api.yaml
new file mode 100644
index 00000000..669fc5ad
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/extensive-api.yaml
@@ -0,0 +1,167 @@
+openapi: "3.0.0"
+info:
+  version: 2.1.0
+  title: Retail Storefront API
+  description: Public-facing REST API for the retail storefront covering product catalog browsing, order placement, account management, and platform administration.
+paths:
+  /catalog/products:
+    get:
+      operationId: get_catalog_products
+      summary: List products
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_READ
+    post:
+      operationId: post_catalog_products
+      summary: Create a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_WRITE
+  /catalog/products/{productId}:
+    get:
+      operationId: get_catalog_products_productId
+      summary: Get a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_READ
+    put:
+      operationId: put_catalog_products_productId
+      summary: Replace a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_WRITE
+    delete:
+      operationId: delete_catalog_products_productId
+      summary: Delete a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_WRITE
+  /orders:
+    get:
+      operationId: get_orders
+      summary: List orders
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_READ
+    post:
+      operationId: post_orders
+      summary: Place an order
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_WRITE
+  /orders/{orderId}:
+    get:
+      operationId: get_orders_orderId
+      summary: Get an order
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_READ
+    delete:
+      operationId: delete_orders_orderId
+      summary: Cancel an order
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_WRITE
+  /account/profile:
+    get:
+      operationId: get_account_profile
+      summary: Get the caller's profile
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ACCOUNT_SC_READ
+    put:
+      operationId: put_account_profile
+      summary: Update the caller's profile - undeclared scope
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ACCOUNT_SC_WRITE # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /admin/users:
+    get:
+      operationId: get_admin_users
+      summary: List platform users - matches key not name
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: admin_all # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    post:
+      operationId: post_admin_users
+      summary: Create a platform user
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ADMIN_SC_ALL
+  /admin/audit-log:
+    get:
+      operationId: get_admin_audit-log
+      summary: Read the audit log
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ADMIN_SC_ALL
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: CATALOG_SC_READ
+        key: catalog_read
+        roles: ROLE_CATALOG_READ
+        description: Allows users to browse the product catalog
+      - name: CATALOG_SC_WRITE
+        key: catalog_write
+        roles: ROLE_CATALOG_WRITE
+        description: Allows users to create or update products
+      - name: ORDERS_SC_READ
+        key: orders_read
+        roles: ROLE_ORDERS_READ
+        description: Allows users to view orders
+      - name: ORDERS_SC_WRITE
+        key: orders_write
+        roles: ROLE_ORDERS_WRITE
+        description: Allows users to place or cancel orders
+      - name: ACCOUNT_SC_READ
+        key: account_read
+        roles: ROLE_ACCOUNT_READ
+        description: Allows users to view their own account
+      - name: ADMIN_SC_ALL
+        key: admin_all
+        roles: ROLE_ADMIN
+        description: Full administrative access
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-all-verbs.json b/src/test/resources/checks/v3/apim/wso2/OAR005/with-all-verbs.json
new file mode 100644
index 00000000..f5588a67
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-all-verbs.json
@@ -0,0 +1,85 @@
+{
+  "openapi" : "3.0.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/a" : {
+      "x-scope" : "scope_one",
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "put" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "delete" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "options" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "head" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "patch" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "trace" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "scope_one",
+        "key" : "scope_one",
+        "roles" : "role_one"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-all-verbs.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-all-verbs.yaml
new file mode 100644
index 00000000..50261884
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-all-verbs.yaml
@@ -0,0 +1,54 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    x-scope: scope_one
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    delete:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    options:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    head:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    patch:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    trace:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        key: scope_one
+        roles: role_one
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-array-security.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-array-security.yaml
new file mode 100644
index 00000000..64e6a744
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-array-security.yaml
@@ -0,0 +1,18 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /b:
+    get:
+      responses:
+        200:
+          description: Ok
+x-wso2-security: []
+
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-callback-operations.json b/src/test/resources/checks/v3/apim/wso2/OAR005/with-callback-operations.json
new file mode 100644
index 00000000..e3da2608
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-callback-operations.json
@@ -0,0 +1,72 @@
+{
+  "openapi" : "3.0.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/a" : {
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_one",
+        "callbacks" : {
+          "onEvent" : {
+            "'{$request.body#/callbackUrl}'" : {
+              "post" : {
+                "responses" : {
+                  "200" : {
+                    "description" : "Ok"
+                  }
+                },
+                "x-scope" : "scope_five", # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+                "callbacks" : {
+                  "onNested" : {
+                    "'{$request.body#/nestedUrl}'" : {
+                      "post" : {
+                        "responses" : {
+                          "200" : {
+                            "description" : "Ok"
+                          }
+                        },
+                        "x-scope" : "scope_six" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  },
+  "components" : {
+    "callbacks" : {
+      "sharedCallback" : {
+        "'{$request.body#/callbackUrl}'" : {
+          "post" : {
+            "responses" : {
+              "200" : {
+                "description" : "Ok"
+              }
+            },
+            "x-scope" : "scope_seven" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+          }
+        }
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "scope_one",
+        "key" : "scope_one",
+        "roles" : "role_one"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-callback-operations.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-callback-operations.yaml
new file mode 100644
index 00000000..6077bdbd
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-callback-operations.yaml
@@ -0,0 +1,43 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one
+      callbacks:
+        onEvent:
+          '{$request.body#/callbackUrl}':
+            post:
+              responses:
+                200:
+                  description: Ok
+              x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+              callbacks:
+                onNested:
+                  '{$request.body#/nestedUrl}':
+                    post:
+                      responses:
+                        200:
+                          description: Ok
+                      x-scope: scope_six # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+components:
+  callbacks:
+    sharedCallback:
+      '{$request.body#/callbackUrl}':
+        post:
+          responses:
+            200:
+              description: Ok
+          x-scope: scope_seven # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        key: scope_one
+        roles: role_one
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-chained-ref-security.json b/src/test/resources/checks/v3/apim/wso2/OAR005/with-chained-ref-security.json
new file mode 100644
index 00000000..260b93ae
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-chained-ref-security.json
@@ -0,0 +1,50 @@
+{
+  "openapi" : "3.0.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_two"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "$ref" : "#/x-wso2-definitions/alias"
+  },
+  "x-wso2-definitions" : {
+    "alias" : {
+      "$ref" : "#/x-wso2-definitions/security"
+    },
+    "security" : {
+      "apim" : {
+        "x-wso2-scopes" : [ {
+          "name" : "scope_one",
+          "description" : "scope_one",
+          "key" : "scope_one",
+          "roles" : "role_one"
+        }, {
+          "name" : "scope_two",
+          "description" : "scope_two",
+          "key" : "scope_two",
+          "roles" : "role_two"
+        } ]
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-chained-ref-security.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-chained-ref-security.yaml
new file mode 100644
index 00000000..d1c9cff1
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-chained-ref-security.yaml
@@ -0,0 +1,33 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_two
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  $ref: "#/x-wso2-definitions/alias"
+x-wso2-definitions:
+  alias:
+    $ref: "#/x-wso2-definitions/security"
+  security:
+    apim:
+      x-wso2-scopes:
+        - name: scope_one
+          description: scope_one
+          key: scope_one
+          roles: role_one
+        - name: scope_two
+          description: scope_two
+          key: scope_two
+          roles: role_two
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-cyclic-ref-security.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-cyclic-ref-security.yaml
new file mode 100644
index 00000000..92925adc
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-cyclic-ref-security.yaml
@@ -0,0 +1,24 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /b:
+    get:
+      responses:
+        200:
+          description: Ok
+x-wso2-security:
+  $ref: "#/x-wso2-definitions/securityA"
+x-wso2-definitions:
+  securityA:
+    $ref: "#/x-wso2-definitions/securityB"
+  securityB:
+    $ref: "#/x-wso2-definitions/securityA"
+
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-dangling-ref-security.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-dangling-ref-security.yaml
new file mode 100644
index 00000000..01fd7d47
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-dangling-ref-security.yaml
@@ -0,0 +1,26 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /b:
+    get:
+      responses:
+        200:
+          description: Ok
+x-wso2-security:
+  $ref: "#/x-wso2-definitions/missing"
+x-wso2-definitions:
+  present:
+    apim:
+      x-wso2-scopes:
+        - name: scope_other
+          key: scope_other
+          roles: role_other
+
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-empty-array-scopes.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-empty-array-scopes.yaml
new file mode 100644
index 00000000..8d2f3826
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-empty-array-scopes.yaml
@@ -0,0 +1,20 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /b:
+    get:
+      responses:
+        200:
+          description: Ok
+x-wso2-security:
+  apim:
+    x-wso2-scopes: []
+
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-empty-object-scopes.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-empty-object-scopes.yaml
new file mode 100644
index 00000000..e815be8b
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-empty-object-scopes.yaml
@@ -0,0 +1,20 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /b:
+    get:
+      responses:
+        200:
+          description: Ok
+x-wso2-security:
+  apim:
+    x-wso2-scopes: {}
+
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-malformed-scopes.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-malformed-scopes.yaml
new file mode 100644
index 00000000..6e03e645
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-malformed-scopes.yaml
@@ -0,0 +1,57 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: no_name # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: null_name # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    delete:
+      responses:
+        200:
+          description: Ok
+      x-scope: empty_name # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    options:
+      responses:
+        200:
+          description: Ok
+      x-scope: plain_scalar_element # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    head:
+      responses:
+        200:
+          description: Ok
+      x-scope: array_element # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        key: scope_one
+        roles: role_one
+        description: A well formed scope
+      - key: no_name
+        roles: role_two
+        description: No name property at all
+      - name: null
+        key: null_name
+        roles: role_three
+        description: Null name
+      - name:
+        key: empty_name
+        roles: role_four
+        description: Name with no value
+      - plain_scalar_element
+      - [array_element]
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-null-apim.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-null-apim.yaml
new file mode 100644
index 00000000..ff80f556
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-null-apim.yaml
@@ -0,0 +1,19 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /b:
+    get:
+      responses:
+        200:
+          description: Ok
+x-wso2-security:
+  apim: null
+
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-null-scopes.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-null-scopes.yaml
new file mode 100644
index 00000000..50a7649a
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-null-scopes.yaml
@@ -0,0 +1,20 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /b:
+    get:
+      responses:
+        200:
+          description: Ok
+x-wso2-security:
+  apim:
+    x-wso2-scopes: null
+
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-null-security.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-null-security.yaml
new file mode 100644
index 00000000..56297463
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-null-security.yaml
@@ -0,0 +1,18 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /b:
+    get:
+      responses:
+        200:
+          description: Ok
+x-wso2-security: null
+
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-scope.json b/src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-scope.json
new file mode 100644
index 00000000..93e31a8d
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-scope.json
@@ -0,0 +1,55 @@
+{
+  "openapi" : "3.0.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_one"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_two"
+      },
+      "put" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "scope_one",
+        "description" : "scope_one",
+        "key" : "scope_one",
+        "roles" : "role_one"
+      }, {
+        "$ref" : "#/x-wso2-definitions/scopeTwo"
+      } ]
+    }
+  },
+  "x-wso2-definitions" : {
+    "scopeTwo" : {
+      "name" : "scope_two",
+      "description" : "scope_two",
+      "key" : "scope_two",
+      "roles" : "role_two"
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-scope.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-scope.yaml
new file mode 100644
index 00000000..e9272308
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-scope.yaml
@@ -0,0 +1,36 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_two
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        description: scope_one
+        key: scope_one
+        roles: role_one
+      - $ref: "#/x-wso2-definitions/scopeTwo"
+x-wso2-definitions:
+  scopeTwo:
+    name: scope_two
+    description: scope_two
+    key: scope_two
+    roles: role_two
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-security.json b/src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-security.json
new file mode 100644
index 00000000..8d4b2f83
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-security.json
@@ -0,0 +1,47 @@
+{
+  "openapi" : "3.0.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_two"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "$ref" : "#/x-wso2-definitions/security"
+  },
+  "x-wso2-definitions" : {
+    "security" : {
+      "apim" : {
+        "x-wso2-scopes" : [ {
+          "name" : "scope_one",
+          "description" : "scope_one",
+          "key" : "scope_one",
+          "roles" : "role_one"
+        }, {
+          "name" : "scope_two",
+          "description" : "scope_two",
+          "key" : "scope_two",
+          "roles" : "role_two"
+        } ]
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-security.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-security.yaml
new file mode 100644
index 00000000..58cec9c0
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-ref-security.yaml
@@ -0,0 +1,31 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_two
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  $ref: "#/x-wso2-definitions/security"
+x-wso2-definitions:
+  security:
+    apim:
+      x-wso2-scopes:
+        - name: scope_one
+          description: scope_one
+          key: scope_one
+          roles: role_one
+        - name: scope_two
+          description: scope_two
+          key: scope_two
+          roles: role_two
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-scalar-scopes.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-scalar-scopes.yaml
new file mode 100644
index 00000000..73621af2
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-scalar-scopes.yaml
@@ -0,0 +1,20 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /b:
+    get:
+      responses:
+        200:
+          description: Ok
+x-wso2-security:
+  apim:
+    x-wso2-scopes: read
+
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-scalar-security.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-scalar-security.yaml
new file mode 100644
index 00000000..b6380e7f
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-scalar-security.yaml
@@ -0,0 +1,18 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /b:
+    get:
+      responses:
+        200:
+          description: Ok
+x-wso2-security: none
+
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-scope-key-not-name.json b/src/test/resources/checks/v3/apim/wso2/OAR005/with-scope-key-not-name.json
new file mode 100644
index 00000000..38dafeb3
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-scope-key-not-name.json
@@ -0,0 +1,37 @@
+{
+  "openapi" : "3.0.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "catalogue_read"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "read" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "catalogue_read",
+        "description" : "catalogue_read",
+        "key" : "read",
+        "roles" : "role_one"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-scope-key-not-name.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-scope-key-not-name.yaml
new file mode 100644
index 00000000..dfe73644
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-scope-key-not-name.yaml
@@ -0,0 +1,24 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: catalogue_read
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: read # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: catalogue_read
+        description: catalogue_read
+        key: read
+        roles: role_one
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-scopes-as-map.json b/src/test/resources/checks/v3/apim/wso2/OAR005/with-scopes-as-map.json
new file mode 100644
index 00000000..612864ed
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-scopes-as-map.json
@@ -0,0 +1,66 @@
+{
+  "openapi" : "3.0.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "read_scope"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "read" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "put" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "write_scope"
+      },
+      "delete" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : {
+        "read" : {
+          "name" : "read_scope",
+          "key" : "read",
+          "roles" : "ROLE_READ",
+          "description" : "Allows users to read the catalogue"
+        },
+        "write" : {
+          "$ref" : "#/x-wso2-definitions/writeScope"
+        }
+      }
+    }
+  },
+  "x-wso2-definitions" : {
+    "writeScope" : {
+      "name" : "write_scope",
+      "key" : "write",
+      "roles" : "ROLE_WRITE",
+      "description" : "Allows users to write the catalogue"
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-scopes-as-map.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-scopes-as-map.yaml
new file mode 100644
index 00000000..ed635286
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-scopes-as-map.yaml
@@ -0,0 +1,43 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: read_scope
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: read # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: write_scope
+    delete:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      read:
+        name: read_scope
+        key: read
+        roles: ROLE_READ
+        description: Allows users to read the catalogue
+      write:
+        $ref: "#/x-wso2-definitions/writeScope"
+x-wso2-definitions:
+  writeScope:
+    name: write_scope
+    key: write
+    roles: ROLE_WRITE
+    description: Allows users to write the catalogue
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-block-collections.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-block-collections.yaml
new file mode 100644
index 00000000..6267f884
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-block-collections.yaml
@@ -0,0 +1,25 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope:
+        - scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope:
+        name: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        key: scope_one
+        roles: role_one
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-collections.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-collections.yaml
new file mode 100644
index 00000000..b39e467b
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-collections.yaml
@@ -0,0 +1,33 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: [] # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: {} # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: [scope_one] # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    delete:
+      responses:
+        200:
+          description: Ok
+      x-scope: {name: scope_one} # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        key: scope_one
+        roles: role_one
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-null-spellings.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-null-spellings.yaml
new file mode 100644
index 00000000..2b0f5e99
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-null-spellings.yaml
@@ -0,0 +1,49 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: null # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: ~ # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: Null # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    delete:
+      responses:
+        200:
+          description: Ok
+      x-scope: NULL # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    options:
+      responses:
+        200:
+          description: Ok
+      x-scope: "null"
+    head:
+      responses:
+        200:
+          description: Ok
+      x-scope:
+    trace:
+      responses:
+        200:
+          description: Ok
+      x-scope: "" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: "null"
+        key: quoted_null
+        roles: role_null
+        description: A scope whose name is the literal text null
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-scalar-types.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-scalar-types.yaml
new file mode 100644
index 00000000..015fa8b7
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/with-x-scope-scalar-types.yaml
@@ -0,0 +1,54 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: "scope_one"
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: "" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    delete:
+      responses:
+        200:
+          description: Ok
+      x-scope: 42
+    options:
+      responses:
+        200:
+          description: Ok
+      x-scope: 7 # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    head:
+      responses:
+        200:
+          description: Ok
+      x-scope: true
+    trace:
+      responses:
+        200:
+          description: Ok
+      x-scope: false # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        key: scope_one
+        roles: role_one
+      - name: 42
+        key: num_scope
+        roles: role_num
+      - name: true
+        key: bool_scope
+        roles: role_bool
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/without-apim.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/without-apim.yaml
new file mode 100644
index 00000000..8f7a667f
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/without-apim.yaml
@@ -0,0 +1,20 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /b:
+    get:
+      responses:
+        200:
+          description: Ok
+x-wso2-security:
+  other:
+    x-wso2-scopes: []
+
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/without-scopes.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/without-scopes.yaml
new file mode 100644
index 00000000..5421c457
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/without-scopes.yaml
@@ -0,0 +1,19 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /b:
+    get:
+      responses:
+        200:
+          description: Ok
+x-wso2-security:
+  apim: {}
+
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/without-security.json b/src/test/resources/checks/v3/apim/wso2/OAR005/without-security.json
new file mode 100644
index 00000000..33930da4
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/without-security.json
@@ -0,0 +1,26 @@
+{
+  "openapi" : "3.0.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_one" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/apim/wso2/OAR005/without-security.yaml b/src/test/resources/checks/v3/apim/wso2/OAR005/without-security.yaml
new file mode 100644
index 00000000..469e5f38
--- /dev/null
+++ b/src/test/resources/checks/v3/apim/wso2/OAR005/without-security.yaml
@@ -0,0 +1,15 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    post:
+      responses:
+        200:
+          description: Ok
diff --git a/src/test/resources/checks/v3/format/OAR007/with-204-response.json b/src/test/resources/checks/v3/format/OAR007/with-204-response.json
new file mode 100644
index 00000000..619f4f86
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-204-response.json
@@ -0,0 +1,18 @@
+{
+  "openapi": "3.0.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "delete": {
+        "responses": {
+          "204": {
+            "description": "No Content"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/format/OAR007/with-204-response.yaml b/src/test/resources/checks/v3/format/OAR007/with-204-response.yaml
new file mode 100644
index 00000000..e323bc65
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-204-response.yaml
@@ -0,0 +1,10 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    delete:
+      responses:
+        '204':
+          description: No Content
diff --git a/src/test/resources/checks/v3/format/OAR007/with-chained-ref.json b/src/test/resources/checks/v3/format/OAR007/with-chained-ref.json
new file mode 100644
index 00000000..9f44591c
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-chained-ref.json
@@ -0,0 +1,28 @@
+{
+  "openapi": "3.0.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "components": {
+    "responses": {
+      "A": {
+        "$ref": "#/components/responses/B"
+      },
+      "B": { # Noncompliant {{OAR007: Section content is mandatory}}
+        "description": "No content defined"
+      }
+    }
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/A"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/format/OAR007/with-chained-ref.yaml b/src/test/resources/checks/v3/format/OAR007/with-chained-ref.yaml
new file mode 100644
index 00000000..b507aa65
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-chained-ref.yaml
@@ -0,0 +1,16 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+components:
+  responses:
+    A:
+      $ref: '#/components/responses/B'
+    B: # Noncompliant {{OAR007: Section content is mandatory}}
+      description: No content defined
+paths:
+  /pets:
+    put:
+      responses:
+        '200':
+          $ref: '#/components/responses/A'
diff --git a/src/test/resources/checks/v3/format/OAR007/with-default-and-ref.json b/src/test/resources/checks/v3/format/OAR007/with-default-and-ref.json
new file mode 100644
index 00000000..d962e59d
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-default-and-ref.json
@@ -0,0 +1,28 @@
+{
+  "openapi": "3.0.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "components": {
+    "responses": {
+      "PetsResponse": {
+        "description": "OK",
+        "content": {
+          "application/json": {}
+        }
+      }
+    }
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/PetsResponse"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/format/OAR007/with-default-and-ref.yaml b/src/test/resources/checks/v3/format/OAR007/with-default-and-ref.yaml
new file mode 100644
index 00000000..c0fa3518
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-default-and-ref.yaml
@@ -0,0 +1,16 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+components:
+  responses:
+    PetsResponse:
+      description: OK
+      content:
+        application/json: {}
+paths:
+  /pets:
+    put:
+      responses:
+        '200':
+          $ref: '#/components/responses/PetsResponse'
diff --git a/src/test/resources/checks/v3/format/OAR007/with-default-response-key.json b/src/test/resources/checks/v3/format/OAR007/with-default-response-key.json
new file mode 100644
index 00000000..c350e397
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-default-response-key.json
@@ -0,0 +1,19 @@
+{
+  "openapi": "3.0.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "post": {
+        "responses": {
+          "default": { # Noncompliant {{OAR007: Section content is mandatory}}
+            "description": "Unexpected error",
+            "content": {}
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/format/OAR007/with-default-response-key.yaml b/src/test/resources/checks/v3/format/OAR007/with-default-response-key.yaml
new file mode 100644
index 00000000..b20f7779
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-default-response-key.yaml
@@ -0,0 +1,11 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    post:
+      responses:
+        default: # Noncompliant {{OAR007: Section content is mandatory}}
+          description: Unexpected error
+          content: {}
diff --git a/src/test/resources/checks/v3/format/OAR007/with-external-ref.json b/src/test/resources/checks/v3/format/OAR007/with-external-ref.json
new file mode 100644
index 00000000..f683b50d
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-external-ref.json
@@ -0,0 +1,18 @@
+{
+  "openapi": "3.0.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "responses": {
+          "200": {
+            "$ref": "http://localhost:18089/OAR007.yaml#/components/responses/SuccessResponse"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/format/OAR007/with-external-ref.yaml b/src/test/resources/checks/v3/format/OAR007/with-external-ref.yaml
new file mode 100644
index 00000000..84ec98f9
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-external-ref.yaml
@@ -0,0 +1,11 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    put:
+      responses:
+        '200':
+          $ref: >-
+            http://localhost:18089/OAR007.yaml#/components/responses/SuccessResponse
diff --git a/src/test/resources/checks/v3/format/OAR007/with-multiple-operations.json b/src/test/resources/checks/v3/format/OAR007/with-multiple-operations.json
new file mode 100644
index 00000000..682a2222
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-multiple-operations.json
@@ -0,0 +1,53 @@
+{
+  "openapi": "3.0.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "get": {
+        "responses": {
+          "200": {
+            "description": "Ok",
+            "content": {
+              "application/json": {}
+            }
+          },
+          "204": {
+            "description": "No Content"
+          }
+        }
+      },
+      "post": {
+        "responses": {
+          "201": { # Noncompliant {{OAR007: Section content is mandatory}}
+            "description": "Created"
+          }
+        }
+      }
+    },
+    "/owners": {
+      "put": {
+        "responses": {
+          "200": {
+            "description": "Ok",
+            "content": {
+              "application/xml": {}
+            }
+          },
+          "400": { # Noncompliant {{OAR007: Section content is mandatory}}
+            "description": "Bad Request"
+          }
+        }
+      },
+      "delete": {
+        "responses": {
+          "204": {
+            "description": "No Content"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/format/OAR007/with-multiple-operations.yaml b/src/test/resources/checks/v3/format/OAR007/with-multiple-operations.yaml
new file mode 100644
index 00000000..d6f3fb5f
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-multiple-operations.yaml
@@ -0,0 +1,31 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        '200':
+          description: Ok
+          content:
+            application/json: {}
+        '204':
+          description: No Content
+    post:
+      responses:
+        '201': # Noncompliant {{OAR007: Section content is mandatory}}
+          description: Created
+  /owners:
+    put:
+      responses:
+        '200':
+          description: Ok
+          content:
+            application/xml: {}
+        '400': # Noncompliant {{OAR007: Section content is mandatory}}
+          description: Bad Request
+    delete:
+      responses:
+        '204':
+          description: No Content
diff --git a/src/test/resources/checks/v3/format/OAR007/with-specific.json b/src/test/resources/checks/v3/format/OAR007/with-specific.json
new file mode 100644
index 00000000..f32afc92
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-specific.json
@@ -0,0 +1,21 @@
+{
+  "openapi": "3.0.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "responses": {
+          "200": {
+            "description": "Ok",
+            "content": {
+              "application/json": {}
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/format/OAR007/with-specific.yaml b/src/test/resources/checks/v3/format/OAR007/with-specific.yaml
new file mode 100644
index 00000000..ff100bb5
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-specific.yaml
@@ -0,0 +1,12 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    put:
+      responses:
+        '200':
+          description: Ok
+          content:
+            application/json: {}
diff --git a/src/test/resources/checks/v3/format/OAR007/with-wrong-ref.json b/src/test/resources/checks/v3/format/OAR007/with-wrong-ref.json
new file mode 100644
index 00000000..7d523b2e
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-wrong-ref.json
@@ -0,0 +1,25 @@
+{
+  "openapi": "3.0.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "components": {
+    "responses": {
+      "PetsResponse": { # Noncompliant {{OAR007: Section content is mandatory}}
+        "description": "No content defined"
+      }
+    }
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/PetsResponse"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/format/OAR007/with-wrong-ref.yaml b/src/test/resources/checks/v3/format/OAR007/with-wrong-ref.yaml
new file mode 100644
index 00000000..6ff09a2e
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR007/with-wrong-ref.yaml
@@ -0,0 +1,14 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+components:
+  responses:
+    PetsResponse: # Noncompliant {{OAR007: Section content is mandatory}}
+      description: No content defined
+paths:
+  /pets:
+    put:
+      responses:
+        '200':
+          $ref: '#/components/responses/PetsResponse'
diff --git a/src/test/resources/checks/v3/format/OAR010/with-204-response.json b/src/test/resources/checks/v3/format/OAR010/with-204-response.json
new file mode 100644
index 00000000..b6328902
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR010/with-204-response.json
@@ -0,0 +1,27 @@
+{
+  "openapi": "3.0.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "post": {
+        "responses": {
+          "200": {
+            "description": "Ok",
+            "content": {
+              "application/json": {}
+            }
+          },
+          "204": {
+            "description": "No Content",
+            "content": {
+              "application/xml": {}
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/format/OAR010/with-204-response.yaml b/src/test/resources/checks/v3/format/OAR010/with-204-response.yaml
new file mode 100644
index 00000000..257dd57b
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR010/with-204-response.yaml
@@ -0,0 +1,16 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    post:
+      responses:
+        '200':
+          description: Ok
+          content:
+            application/json: {}
+        '204':
+          description: No Content
+          content:
+            application/xml: {}
diff --git a/src/test/resources/checks/v3/format/OAR010/with-default-mixed-case.json b/src/test/resources/checks/v3/format/OAR010/with-default-mixed-case.json
new file mode 100644
index 00000000..8ced2d72
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR010/with-default-mixed-case.json
@@ -0,0 +1,21 @@
+{
+  "openapi": "3.0.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "post": {
+        "responses": {
+          "200": {
+            "description": "Ok",
+            "content": {
+              "Application/JSON": {}
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/format/OAR010/with-default-mixed-case.yaml b/src/test/resources/checks/v3/format/OAR010/with-default-mixed-case.yaml
new file mode 100644
index 00000000..5758d03b
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR010/with-default-mixed-case.yaml
@@ -0,0 +1,12 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    post:
+      responses:
+        '200':
+          description: Ok
+          content:
+            Application/JSON: {}
diff --git a/src/test/resources/checks/v3/format/OAR010/with-external-ref.json b/src/test/resources/checks/v3/format/OAR010/with-external-ref.json
new file mode 100644
index 00000000..c5603828
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR010/with-external-ref.json
@@ -0,0 +1,18 @@
+{
+  "openapi": "3.0.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "post": {
+        "responses": {
+          "200": {
+            "$ref": "http://localhost:18089/OAR010.yaml#/components/responses/SuccessResponse"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/format/OAR010/with-external-ref.yaml b/src/test/resources/checks/v3/format/OAR010/with-external-ref.yaml
new file mode 100644
index 00000000..fa887704
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR010/with-external-ref.yaml
@@ -0,0 +1,11 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    post:
+      responses:
+        '200':
+          $ref: >-
+            http://localhost:18089/OAR010.yaml#/components/responses/SuccessResponse
diff --git a/src/test/resources/checks/v3/format/OAR010/with-wrong-default-and-ref.json b/src/test/resources/checks/v3/format/OAR010/with-wrong-default-and-ref.json
new file mode 100644
index 00000000..0d842352
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR010/with-wrong-default-and-ref.json
@@ -0,0 +1,28 @@
+{
+  "openapi": "3.0.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "components": {
+    "responses": {
+      "XmlOnlyResponse": {
+        "description": "OK",
+        "content": { # Noncompliant {{OAR010: Should indicate the default response media type}}
+          "application/xml": {}
+        }
+      }
+    }
+  },
+  "paths": {
+    "/pets": {
+      "post": {
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/XmlOnlyResponse"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v3/format/OAR010/with-wrong-default-and-ref.yaml b/src/test/resources/checks/v3/format/OAR010/with-wrong-default-and-ref.yaml
new file mode 100644
index 00000000..53a3b8e4
--- /dev/null
+++ b/src/test/resources/checks/v3/format/OAR010/with-wrong-default-and-ref.yaml
@@ -0,0 +1,16 @@
+openapi: "3.0.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+components:
+  responses:
+    XmlOnlyResponse:
+      description: OK
+      content: # Noncompliant {{OAR010: Should indicate the default response media type}}
+        application/xml: {}
+paths:
+  /pets:
+    post:
+      responses:
+        '200':
+          $ref: '#/components/responses/XmlOnlyResponse'
diff --git a/src/test/resources/checks/v31/apim/OAR005/extensive-api.json b/src/test/resources/checks/v31/apim/OAR005/extensive-api.json
new file mode 100644
index 00000000..1f4512a9
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/extensive-api.json
@@ -0,0 +1,241 @@
+{
+  "openapi" : "3.1.0",
+  "info" : {
+    "version" : "2.1.0",
+    "title" : "Retail Storefront API",
+    "description" : "Public-facing REST API for the retail storefront covering product catalog browsing, order placement, account management, and platform administration."
+  },
+  "paths" : {
+    "/catalog/products" : {
+      "get" : {
+        "operationId" : "get_catalog_products",
+        "summary" : "List products",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_READ"
+      },
+      "post" : {
+        "operationId" : "post_catalog_products",
+        "summary" : "Create a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_WRITE"
+      }
+    },
+    "/catalog/products/{productId}" : {
+      "get" : {
+        "operationId" : "get_catalog_products_productId",
+        "summary" : "Get a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_READ"
+      },
+      "put" : {
+        "operationId" : "put_catalog_products_productId",
+        "summary" : "Replace a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_WRITE"
+      },
+      "delete" : {
+        "operationId" : "delete_catalog_products_productId",
+        "summary" : "Delete a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_WRITE"
+      }
+    },
+    "/orders" : {
+      "get" : {
+        "operationId" : "get_orders",
+        "summary" : "List orders",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_READ"
+      },
+      "post" : {
+        "operationId" : "post_orders",
+        "summary" : "Place an order",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_WRITE"
+      }
+    },
+    "/orders/{orderId}" : {
+      "get" : {
+        "operationId" : "get_orders_orderId",
+        "summary" : "Get an order",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_READ"
+      },
+      "delete" : {
+        "operationId" : "delete_orders_orderId",
+        "summary" : "Cancel an order",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_WRITE"
+      }
+    },
+    "/account/profile" : {
+      "get" : {
+        "operationId" : "get_account_profile",
+        "summary" : "Get the caller's profile",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ACCOUNT_SC_READ"
+      },
+      "put" : {
+        "operationId" : "put_account_profile",
+        "summary" : "Update the caller's profile - undeclared scope",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ACCOUNT_SC_WRITE" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    },
+    "/admin/users" : {
+      "get" : {
+        "operationId" : "get_admin_users",
+        "summary" : "List platform users - matches key not name",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "admin_all" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "post" : {
+        "operationId" : "post_admin_users",
+        "summary" : "Create a platform user",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ADMIN_SC_ALL"
+      }
+    },
+    "/admin/audit-log" : {
+      "get" : {
+        "operationId" : "get_admin_audit-log",
+        "summary" : "Read the audit log",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ADMIN_SC_ALL"
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "CATALOG_SC_READ",
+        "key" : "catalog_read",
+        "roles" : "ROLE_CATALOG_READ",
+        "description" : "Allows users to browse the product catalog"
+      }, {
+        "name" : "CATALOG_SC_WRITE",
+        "key" : "catalog_write",
+        "roles" : "ROLE_CATALOG_WRITE",
+        "description" : "Allows users to create or update products"
+      }, {
+        "name" : "ORDERS_SC_READ",
+        "key" : "orders_read",
+        "roles" : "ROLE_ORDERS_READ",
+        "description" : "Allows users to view orders"
+      }, {
+        "name" : "ORDERS_SC_WRITE",
+        "key" : "orders_write",
+        "roles" : "ROLE_ORDERS_WRITE",
+        "description" : "Allows users to place or cancel orders"
+      }, {
+        "name" : "ACCOUNT_SC_READ",
+        "key" : "account_read",
+        "roles" : "ROLE_ACCOUNT_READ",
+        "description" : "Allows users to view their own account"
+      }, {
+        "name" : "ADMIN_SC_ALL",
+        "key" : "admin_all",
+        "roles" : "ROLE_ADMIN",
+        "description" : "Full administrative access"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/apim/OAR005/extensive-api.yaml b/src/test/resources/checks/v31/apim/OAR005/extensive-api.yaml
new file mode 100644
index 00000000..b788d01f
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/extensive-api.yaml
@@ -0,0 +1,167 @@
+openapi: "3.1.0"
+info:
+  version: 2.1.0
+  title: Retail Storefront API
+  description: Public-facing REST API for the retail storefront covering product catalog browsing, order placement, account management, and platform administration.
+paths:
+  /catalog/products:
+    get:
+      operationId: get_catalog_products
+      summary: List products
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_READ
+    post:
+      operationId: post_catalog_products
+      summary: Create a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_WRITE
+  /catalog/products/{productId}:
+    get:
+      operationId: get_catalog_products_productId
+      summary: Get a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_READ
+    put:
+      operationId: put_catalog_products_productId
+      summary: Replace a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_WRITE
+    delete:
+      operationId: delete_catalog_products_productId
+      summary: Delete a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_WRITE
+  /orders:
+    get:
+      operationId: get_orders
+      summary: List orders
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_READ
+    post:
+      operationId: post_orders
+      summary: Place an order
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_WRITE
+  /orders/{orderId}:
+    get:
+      operationId: get_orders_orderId
+      summary: Get an order
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_READ
+    delete:
+      operationId: delete_orders_orderId
+      summary: Cancel an order
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_WRITE
+  /account/profile:
+    get:
+      operationId: get_account_profile
+      summary: Get the caller's profile
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ACCOUNT_SC_READ
+    put:
+      operationId: put_account_profile
+      summary: Update the caller's profile - undeclared scope
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ACCOUNT_SC_WRITE # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /admin/users:
+    get:
+      operationId: get_admin_users
+      summary: List platform users - matches key not name
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: admin_all # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    post:
+      operationId: post_admin_users
+      summary: Create a platform user
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ADMIN_SC_ALL
+  /admin/audit-log:
+    get:
+      operationId: get_admin_audit-log
+      summary: Read the audit log
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ADMIN_SC_ALL
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: CATALOG_SC_READ
+        key: catalog_read
+        roles: ROLE_CATALOG_READ
+        description: Allows users to browse the product catalog
+      - name: CATALOG_SC_WRITE
+        key: catalog_write
+        roles: ROLE_CATALOG_WRITE
+        description: Allows users to create or update products
+      - name: ORDERS_SC_READ
+        key: orders_read
+        roles: ROLE_ORDERS_READ
+        description: Allows users to view orders
+      - name: ORDERS_SC_WRITE
+        key: orders_write
+        roles: ROLE_ORDERS_WRITE
+        description: Allows users to place or cancel orders
+      - name: ACCOUNT_SC_READ
+        key: account_read
+        roles: ROLE_ACCOUNT_READ
+        description: Allows users to view their own account
+      - name: ADMIN_SC_ALL
+        key: admin_all
+        roles: ROLE_ADMIN
+        description: Full administrative access
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-all-verbs.json b/src/test/resources/checks/v31/apim/OAR005/with-all-verbs.json
new file mode 100644
index 00000000..219d8f44
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-all-verbs.json
@@ -0,0 +1,85 @@
+{
+  "openapi" : "3.1.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/a" : {
+      "x-scope" : "scope_one",
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "put" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "delete" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "options" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "head" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "patch" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "trace" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "scope_one",
+        "key" : "scope_one",
+        "roles" : "role_one"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-all-verbs.yaml b/src/test/resources/checks/v31/apim/OAR005/with-all-verbs.yaml
new file mode 100644
index 00000000..d74abfcd
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-all-verbs.yaml
@@ -0,0 +1,54 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    x-scope: scope_one
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    delete:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    options:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    head:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    patch:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    trace:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        key: scope_one
+        roles: role_one
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-callback-operations.json b/src/test/resources/checks/v31/apim/OAR005/with-callback-operations.json
new file mode 100644
index 00000000..29fab7f4
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-callback-operations.json
@@ -0,0 +1,72 @@
+{
+  "openapi" : "3.1.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/a" : {
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_one",
+        "callbacks" : {
+          "onEvent" : {
+            "'{$request.body#/callbackUrl}'" : {
+              "post" : {
+                "responses" : {
+                  "200" : {
+                    "description" : "Ok"
+                  }
+                },
+                "x-scope" : "scope_five", # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+                "callbacks" : {
+                  "onNested" : {
+                    "'{$request.body#/nestedUrl}'" : {
+                      "post" : {
+                        "responses" : {
+                          "200" : {
+                            "description" : "Ok"
+                          }
+                        },
+                        "x-scope" : "scope_six" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  },
+  "components" : {
+    "callbacks" : {
+      "sharedCallback" : {
+        "'{$request.body#/callbackUrl}'" : {
+          "post" : {
+            "responses" : {
+              "200" : {
+                "description" : "Ok"
+              }
+            },
+            "x-scope" : "scope_seven" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+          }
+        }
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "scope_one",
+        "key" : "scope_one",
+        "roles" : "role_one"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-callback-operations.yaml b/src/test/resources/checks/v31/apim/OAR005/with-callback-operations.yaml
new file mode 100644
index 00000000..b40822e3
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-callback-operations.yaml
@@ -0,0 +1,43 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one
+      callbacks:
+        onEvent:
+          '{$request.body#/callbackUrl}':
+            post:
+              responses:
+                200:
+                  description: Ok
+              x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+              callbacks:
+                onNested:
+                  '{$request.body#/nestedUrl}':
+                    post:
+                      responses:
+                        200:
+                          description: Ok
+                      x-scope: scope_six # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+components:
+  callbacks:
+    sharedCallback:
+      '{$request.body#/callbackUrl}':
+        post:
+          responses:
+            200:
+              description: Ok
+          x-scope: scope_seven # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        key: scope_one
+        roles: role_one
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-chained-ref-security.json b/src/test/resources/checks/v31/apim/OAR005/with-chained-ref-security.json
new file mode 100644
index 00000000..6e69412f
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-chained-ref-security.json
@@ -0,0 +1,50 @@
+{
+  "openapi" : "3.1.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_two"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "$ref" : "#/x-wso2-definitions/alias"
+  },
+  "x-wso2-definitions" : {
+    "alias" : {
+      "$ref" : "#/x-wso2-definitions/security"
+    },
+    "security" : {
+      "apim" : {
+        "x-wso2-scopes" : [ {
+          "name" : "scope_one",
+          "description" : "scope_one",
+          "key" : "scope_one",
+          "roles" : "role_one"
+        }, {
+          "name" : "scope_two",
+          "description" : "scope_two",
+          "key" : "scope_two",
+          "roles" : "role_two"
+        } ]
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-chained-ref-security.yaml b/src/test/resources/checks/v31/apim/OAR005/with-chained-ref-security.yaml
new file mode 100644
index 00000000..c6ebb0f1
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-chained-ref-security.yaml
@@ -0,0 +1,33 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_two
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  $ref: "#/x-wso2-definitions/alias"
+x-wso2-definitions:
+  alias:
+    $ref: "#/x-wso2-definitions/security"
+  security:
+    apim:
+      x-wso2-scopes:
+        - name: scope_one
+          description: scope_one
+          key: scope_one
+          roles: role_one
+        - name: scope_two
+          description: scope_two
+          key: scope_two
+          roles: role_two
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-ref-scope.json b/src/test/resources/checks/v31/apim/OAR005/with-ref-scope.json
new file mode 100644
index 00000000..62234c28
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-ref-scope.json
@@ -0,0 +1,55 @@
+{
+  "openapi" : "3.1.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_one"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_two"
+      },
+      "put" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "scope_one",
+        "description" : "scope_one",
+        "key" : "scope_one",
+        "roles" : "role_one"
+      }, {
+        "$ref" : "#/x-wso2-definitions/scopeTwo"
+      } ]
+    }
+  },
+  "x-wso2-definitions" : {
+    "scopeTwo" : {
+      "name" : "scope_two",
+      "description" : "scope_two",
+      "key" : "scope_two",
+      "roles" : "role_two"
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-ref-scope.yaml b/src/test/resources/checks/v31/apim/OAR005/with-ref-scope.yaml
new file mode 100644
index 00000000..017514ad
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-ref-scope.yaml
@@ -0,0 +1,36 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_two
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        description: scope_one
+        key: scope_one
+        roles: role_one
+      - $ref: "#/x-wso2-definitions/scopeTwo"
+x-wso2-definitions:
+  scopeTwo:
+    name: scope_two
+    description: scope_two
+    key: scope_two
+    roles: role_two
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-ref-security.json b/src/test/resources/checks/v31/apim/OAR005/with-ref-security.json
new file mode 100644
index 00000000..e21f46b8
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-ref-security.json
@@ -0,0 +1,47 @@
+{
+  "openapi" : "3.1.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_two"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "$ref" : "#/x-wso2-definitions/security"
+  },
+  "x-wso2-definitions" : {
+    "security" : {
+      "apim" : {
+        "x-wso2-scopes" : [ {
+          "name" : "scope_one",
+          "description" : "scope_one",
+          "key" : "scope_one",
+          "roles" : "role_one"
+        }, {
+          "name" : "scope_two",
+          "description" : "scope_two",
+          "key" : "scope_two",
+          "roles" : "role_two"
+        } ]
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-ref-security.yaml b/src/test/resources/checks/v31/apim/OAR005/with-ref-security.yaml
new file mode 100644
index 00000000..6391da4e
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-ref-security.yaml
@@ -0,0 +1,31 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_two
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  $ref: "#/x-wso2-definitions/security"
+x-wso2-definitions:
+  security:
+    apim:
+      x-wso2-scopes:
+        - name: scope_one
+          description: scope_one
+          key: scope_one
+          roles: role_one
+        - name: scope_two
+          description: scope_two
+          key: scope_two
+          roles: role_two
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-scope-key-not-name.json b/src/test/resources/checks/v31/apim/OAR005/with-scope-key-not-name.json
new file mode 100644
index 00000000..ce2403ae
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-scope-key-not-name.json
@@ -0,0 +1,37 @@
+{
+  "openapi" : "3.1.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "catalogue_read"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "read" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "catalogue_read",
+        "description" : "catalogue_read",
+        "key" : "read",
+        "roles" : "role_one"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-scope-key-not-name.yaml b/src/test/resources/checks/v31/apim/OAR005/with-scope-key-not-name.yaml
new file mode 100644
index 00000000..7bd94393
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-scope-key-not-name.yaml
@@ -0,0 +1,24 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: catalogue_read
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: read # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: catalogue_read
+        description: catalogue_read
+        key: read
+        roles: role_one
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-scopes-as-map.json b/src/test/resources/checks/v31/apim/OAR005/with-scopes-as-map.json
new file mode 100644
index 00000000..c00db5f5
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-scopes-as-map.json
@@ -0,0 +1,66 @@
+{
+  "openapi" : "3.1.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "read_scope"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "read" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "put" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "write_scope"
+      },
+      "delete" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : {
+        "read" : {
+          "name" : "read_scope",
+          "key" : "read",
+          "roles" : "ROLE_READ",
+          "description" : "Allows users to read the catalogue"
+        },
+        "write" : {
+          "$ref" : "#/x-wso2-definitions/writeScope"
+        }
+      }
+    }
+  },
+  "x-wso2-definitions" : {
+    "writeScope" : {
+      "name" : "write_scope",
+      "key" : "write",
+      "roles" : "ROLE_WRITE",
+      "description" : "Allows users to write the catalogue"
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-scopes-as-map.yaml b/src/test/resources/checks/v31/apim/OAR005/with-scopes-as-map.yaml
new file mode 100644
index 00000000..e9d0a792
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-scopes-as-map.yaml
@@ -0,0 +1,43 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: read_scope
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: read # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: write_scope
+    delete:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      read:
+        name: read_scope
+        key: read
+        roles: ROLE_READ
+        description: Allows users to read the catalogue
+      write:
+        $ref: "#/x-wso2-definitions/writeScope"
+x-wso2-definitions:
+  writeScope:
+    name: write_scope
+    key: write
+    roles: ROLE_WRITE
+    description: Allows users to write the catalogue
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-webhook-operations.json b/src/test/resources/checks/v31/apim/OAR005/with-webhook-operations.json
new file mode 100644
index 00000000..386fd1c4
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-webhook-operations.json
@@ -0,0 +1,60 @@
+{
+  "openapi" : "3.1.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "$ref" : "#/components/pathItems/PetsPath"
+    }
+  },
+  "webhooks" : {
+    "newPet" : {
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "components" : {
+    "pathItems" : {
+      "PetsPath" : {
+        "x-scope" : "scope_one",
+        "get" : {
+          "responses" : {
+            "200" : {
+              "description" : "Ok"
+            }
+          },
+          "x-scope" : "scope_six" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+        }
+      }
+    },
+    "webhooks" : {
+      "reusableWebhook" : {
+        "post" : {
+          "responses" : {
+            "200" : {
+              "description" : "Ok"
+            }
+          },
+          "x-scope" : "scope_seven" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+        }
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "scope_one",
+        "key" : "scope_one",
+        "roles" : "role_one"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/apim/OAR005/with-webhook-operations.yaml b/src/test/resources/checks/v31/apim/OAR005/with-webhook-operations.yaml
new file mode 100644
index 00000000..6b1fa4b7
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/with-webhook-operations.yaml
@@ -0,0 +1,38 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    $ref: "#/components/pathItems/PetsPath"
+webhooks:
+  newPet:
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+components:
+  pathItems:
+    PetsPath:
+      x-scope: scope_one
+      get:
+        responses:
+          200:
+            description: Ok
+        x-scope: scope_six # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  webhooks:
+    reusableWebhook:
+      post:
+        responses:
+          200:
+            description: Ok
+        x-scope: scope_seven # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        key: scope_one
+        roles: role_one
diff --git a/src/test/resources/checks/v31/apim/OAR005/without-security.json b/src/test/resources/checks/v31/apim/OAR005/without-security.json
new file mode 100644
index 00000000..eff68435
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/without-security.json
@@ -0,0 +1,26 @@
+{
+  "openapi" : "3.1.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_one" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/apim/OAR005/without-security.yaml b/src/test/resources/checks/v31/apim/OAR005/without-security.yaml
new file mode 100644
index 00000000..e2b8f1aa
--- /dev/null
+++ b/src/test/resources/checks/v31/apim/OAR005/without-security.yaml
@@ -0,0 +1,15 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    post:
+      responses:
+        200:
+          description: Ok
diff --git a/src/test/resources/checks/v31/format/OAR007/with-204-response.json b/src/test/resources/checks/v31/format/OAR007/with-204-response.json
new file mode 100644
index 00000000..1ccf567f
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-204-response.json
@@ -0,0 +1,18 @@
+{
+  "openapi": "3.1.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "delete": {
+        "responses": {
+          "204": {
+            "description": "No Content"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/format/OAR007/with-204-response.yaml b/src/test/resources/checks/v31/format/OAR007/with-204-response.yaml
new file mode 100644
index 00000000..bb080d5e
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-204-response.yaml
@@ -0,0 +1,10 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    delete:
+      responses:
+        '204':
+          description: No Content
diff --git a/src/test/resources/checks/v31/format/OAR007/with-chained-ref.json b/src/test/resources/checks/v31/format/OAR007/with-chained-ref.json
new file mode 100644
index 00000000..3260aa1c
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-chained-ref.json
@@ -0,0 +1,28 @@
+{
+  "openapi": "3.1.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "components": {
+    "responses": {
+      "A": {
+        "$ref": "#/components/responses/B"
+      },
+      "B": { # Noncompliant {{OAR007: Section content is mandatory}}
+        "description": "No content defined"
+      }
+    }
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/A"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/format/OAR007/with-chained-ref.yaml b/src/test/resources/checks/v31/format/OAR007/with-chained-ref.yaml
new file mode 100644
index 00000000..0ea40fa0
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-chained-ref.yaml
@@ -0,0 +1,16 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+components:
+  responses:
+    A:
+      $ref: '#/components/responses/B'
+    B: # Noncompliant {{OAR007: Section content is mandatory}}
+      description: No content defined
+paths:
+  /pets:
+    put:
+      responses:
+        '200':
+          $ref: '#/components/responses/A'
diff --git a/src/test/resources/checks/v31/format/OAR007/with-default-and-ref.json b/src/test/resources/checks/v31/format/OAR007/with-default-and-ref.json
new file mode 100644
index 00000000..f3d84a94
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-default-and-ref.json
@@ -0,0 +1,28 @@
+{
+  "openapi": "3.1.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "components": {
+    "responses": {
+      "PetsResponse": {
+        "description": "OK",
+        "content": {
+          "application/json": {}
+        }
+      }
+    }
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/PetsResponse"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/format/OAR007/with-default-and-ref.yaml b/src/test/resources/checks/v31/format/OAR007/with-default-and-ref.yaml
new file mode 100644
index 00000000..a20959a4
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-default-and-ref.yaml
@@ -0,0 +1,16 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+components:
+  responses:
+    PetsResponse:
+      description: OK
+      content:
+        application/json: {}
+paths:
+  /pets:
+    put:
+      responses:
+        '200':
+          $ref: '#/components/responses/PetsResponse'
diff --git a/src/test/resources/checks/v31/format/OAR007/with-default-response-key.json b/src/test/resources/checks/v31/format/OAR007/with-default-response-key.json
new file mode 100644
index 00000000..ceaf057f
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-default-response-key.json
@@ -0,0 +1,19 @@
+{
+  "openapi": "3.1.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "post": {
+        "responses": {
+          "default": { # Noncompliant {{OAR007: Section content is mandatory}}
+            "description": "Unexpected error",
+            "content": {}
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/format/OAR007/with-default-response-key.yaml b/src/test/resources/checks/v31/format/OAR007/with-default-response-key.yaml
new file mode 100644
index 00000000..9ad855e3
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-default-response-key.yaml
@@ -0,0 +1,11 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    post:
+      responses:
+        default: # Noncompliant {{OAR007: Section content is mandatory}}
+          description: Unexpected error
+          content: {}
diff --git a/src/test/resources/checks/v31/format/OAR007/with-external-ref.json b/src/test/resources/checks/v31/format/OAR007/with-external-ref.json
new file mode 100644
index 00000000..f6567e42
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-external-ref.json
@@ -0,0 +1,18 @@
+{
+  "openapi": "3.1.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "responses": {
+          "200": {
+            "$ref": "http://localhost:18089/OAR007.yaml#/components/responses/SuccessResponse"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/format/OAR007/with-external-ref.yaml b/src/test/resources/checks/v31/format/OAR007/with-external-ref.yaml
new file mode 100644
index 00000000..3b7d240d
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-external-ref.yaml
@@ -0,0 +1,11 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    put:
+      responses:
+        '200':
+          $ref: >-
+            http://localhost:18089/OAR007.yaml#/components/responses/SuccessResponse
diff --git a/src/test/resources/checks/v31/format/OAR007/with-multiple-operations.json b/src/test/resources/checks/v31/format/OAR007/with-multiple-operations.json
new file mode 100644
index 00000000..a9c4e4dc
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-multiple-operations.json
@@ -0,0 +1,53 @@
+{
+  "openapi": "3.1.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "get": {
+        "responses": {
+          "200": {
+            "description": "Ok",
+            "content": {
+              "application/json": {}
+            }
+          },
+          "204": {
+            "description": "No Content"
+          }
+        }
+      },
+      "post": {
+        "responses": {
+          "201": { # Noncompliant {{OAR007: Section content is mandatory}}
+            "description": "Created"
+          }
+        }
+      }
+    },
+    "/owners": {
+      "put": {
+        "responses": {
+          "200": {
+            "description": "Ok",
+            "content": {
+              "application/xml": {}
+            }
+          },
+          "400": { # Noncompliant {{OAR007: Section content is mandatory}}
+            "description": "Bad Request"
+          }
+        }
+      },
+      "delete": {
+        "responses": {
+          "204": {
+            "description": "No Content"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/format/OAR007/with-multiple-operations.yaml b/src/test/resources/checks/v31/format/OAR007/with-multiple-operations.yaml
new file mode 100644
index 00000000..bb48e6b3
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-multiple-operations.yaml
@@ -0,0 +1,31 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        '200':
+          description: Ok
+          content:
+            application/json: {}
+        '204':
+          description: No Content
+    post:
+      responses:
+        '201': # Noncompliant {{OAR007: Section content is mandatory}}
+          description: Created
+  /owners:
+    put:
+      responses:
+        '200':
+          description: Ok
+          content:
+            application/xml: {}
+        '400': # Noncompliant {{OAR007: Section content is mandatory}}
+          description: Bad Request
+    delete:
+      responses:
+        '204':
+          description: No Content
diff --git a/src/test/resources/checks/v31/format/OAR007/with-specific.json b/src/test/resources/checks/v31/format/OAR007/with-specific.json
new file mode 100644
index 00000000..9afb31e4
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-specific.json
@@ -0,0 +1,21 @@
+{
+  "openapi": "3.1.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "responses": {
+          "200": {
+            "description": "Ok",
+            "content": {
+              "application/json": {}
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/format/OAR007/with-specific.yaml b/src/test/resources/checks/v31/format/OAR007/with-specific.yaml
new file mode 100644
index 00000000..fa9f955c
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-specific.yaml
@@ -0,0 +1,12 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    put:
+      responses:
+        '200':
+          description: Ok
+          content:
+            application/json: {}
diff --git a/src/test/resources/checks/v31/format/OAR007/with-wrong-ref.json b/src/test/resources/checks/v31/format/OAR007/with-wrong-ref.json
new file mode 100644
index 00000000..7a86ba86
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-wrong-ref.json
@@ -0,0 +1,25 @@
+{
+  "openapi": "3.1.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "components": {
+    "responses": {
+      "PetsResponse": { # Noncompliant {{OAR007: Section content is mandatory}}
+        "description": "No content defined"
+      }
+    }
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/PetsResponse"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/format/OAR007/with-wrong-ref.yaml b/src/test/resources/checks/v31/format/OAR007/with-wrong-ref.yaml
new file mode 100644
index 00000000..dfafb717
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR007/with-wrong-ref.yaml
@@ -0,0 +1,14 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+components:
+  responses:
+    PetsResponse: # Noncompliant {{OAR007: Section content is mandatory}}
+      description: No content defined
+paths:
+  /pets:
+    put:
+      responses:
+        '200':
+          $ref: '#/components/responses/PetsResponse'
diff --git a/src/test/resources/checks/v31/format/OAR010/with-204-response.json b/src/test/resources/checks/v31/format/OAR010/with-204-response.json
new file mode 100644
index 00000000..6f132667
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR010/with-204-response.json
@@ -0,0 +1,27 @@
+{
+  "openapi": "3.1.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "post": {
+        "responses": {
+          "200": {
+            "description": "Ok",
+            "content": {
+              "application/json": {}
+            }
+          },
+          "204": {
+            "description": "No Content",
+            "content": {
+              "application/xml": {}
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/format/OAR010/with-204-response.yaml b/src/test/resources/checks/v31/format/OAR010/with-204-response.yaml
new file mode 100644
index 00000000..1b8999ec
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR010/with-204-response.yaml
@@ -0,0 +1,16 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    post:
+      responses:
+        '200':
+          description: Ok
+          content:
+            application/json: {}
+        '204':
+          description: No Content
+          content:
+            application/xml: {}
diff --git a/src/test/resources/checks/v31/format/OAR010/with-default-mixed-case.json b/src/test/resources/checks/v31/format/OAR010/with-default-mixed-case.json
new file mode 100644
index 00000000..79e3af7a
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR010/with-default-mixed-case.json
@@ -0,0 +1,21 @@
+{
+  "openapi": "3.1.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "post": {
+        "responses": {
+          "200": {
+            "description": "Ok",
+            "content": {
+              "Application/JSON": {}
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/format/OAR010/with-default-mixed-case.yaml b/src/test/resources/checks/v31/format/OAR010/with-default-mixed-case.yaml
new file mode 100644
index 00000000..cca3f65f
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR010/with-default-mixed-case.yaml
@@ -0,0 +1,12 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    post:
+      responses:
+        '200':
+          description: Ok
+          content:
+            Application/JSON: {}
diff --git a/src/test/resources/checks/v31/format/OAR010/with-wrong-default-and-ref.json b/src/test/resources/checks/v31/format/OAR010/with-wrong-default-and-ref.json
new file mode 100644
index 00000000..005c8be1
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR010/with-wrong-default-and-ref.json
@@ -0,0 +1,28 @@
+{
+  "openapi": "3.1.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "components": {
+    "responses": {
+      "XmlOnlyResponse": {
+        "description": "OK",
+        "content": { # Noncompliant {{OAR010: Should indicate the default response media type}}
+          "application/xml": {}
+        }
+      }
+    }
+  },
+  "paths": {
+    "/pets": {
+      "post": {
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/XmlOnlyResponse"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v31/format/OAR010/with-wrong-default-and-ref.yaml b/src/test/resources/checks/v31/format/OAR010/with-wrong-default-and-ref.yaml
new file mode 100644
index 00000000..76fbf25d
--- /dev/null
+++ b/src/test/resources/checks/v31/format/OAR010/with-wrong-default-and-ref.yaml
@@ -0,0 +1,16 @@
+openapi: "3.1.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+components:
+  responses:
+    XmlOnlyResponse:
+      description: OK
+      content: # Noncompliant {{OAR010: Should indicate the default response media type}}
+        application/xml: {}
+paths:
+  /pets:
+    post:
+      responses:
+        '200':
+          $ref: '#/components/responses/XmlOnlyResponse'
diff --git a/src/test/resources/checks/v32/apim/OAR005/extensive-api.json b/src/test/resources/checks/v32/apim/OAR005/extensive-api.json
new file mode 100644
index 00000000..80e2569e
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/extensive-api.json
@@ -0,0 +1,241 @@
+{
+  "openapi" : "3.2.0",
+  "info" : {
+    "version" : "2.1.0",
+    "title" : "Retail Storefront API",
+    "description" : "Public-facing REST API for the retail storefront covering product catalog browsing, order placement, account management, and platform administration."
+  },
+  "paths" : {
+    "/catalog/products" : {
+      "get" : {
+        "operationId" : "get_catalog_products",
+        "summary" : "List products",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_READ"
+      },
+      "post" : {
+        "operationId" : "post_catalog_products",
+        "summary" : "Create a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_WRITE"
+      }
+    },
+    "/catalog/products/{productId}" : {
+      "get" : {
+        "operationId" : "get_catalog_products_productId",
+        "summary" : "Get a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_READ"
+      },
+      "put" : {
+        "operationId" : "put_catalog_products_productId",
+        "summary" : "Replace a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_WRITE"
+      },
+      "delete" : {
+        "operationId" : "delete_catalog_products_productId",
+        "summary" : "Delete a product",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "CATALOG_SC_WRITE"
+      }
+    },
+    "/orders" : {
+      "get" : {
+        "operationId" : "get_orders",
+        "summary" : "List orders",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_READ"
+      },
+      "post" : {
+        "operationId" : "post_orders",
+        "summary" : "Place an order",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_WRITE"
+      }
+    },
+    "/orders/{orderId}" : {
+      "get" : {
+        "operationId" : "get_orders_orderId",
+        "summary" : "Get an order",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_READ"
+      },
+      "delete" : {
+        "operationId" : "delete_orders_orderId",
+        "summary" : "Cancel an order",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ORDERS_SC_WRITE"
+      }
+    },
+    "/account/profile" : {
+      "get" : {
+        "operationId" : "get_account_profile",
+        "summary" : "Get the caller's profile",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ACCOUNT_SC_READ"
+      },
+      "put" : {
+        "operationId" : "put_account_profile",
+        "summary" : "Update the caller's profile - undeclared scope",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ACCOUNT_SC_WRITE" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    },
+    "/admin/users" : {
+      "get" : {
+        "operationId" : "get_admin_users",
+        "summary" : "List platform users - matches key not name",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "admin_all" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "post" : {
+        "operationId" : "post_admin_users",
+        "summary" : "Create a platform user",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ADMIN_SC_ALL"
+      }
+    },
+    "/admin/audit-log" : {
+      "get" : {
+        "operationId" : "get_admin_audit-log",
+        "summary" : "Read the audit log",
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          },
+          "400" : {
+            "description" : "Bad request"
+          }
+        },
+        "x-scope" : "ADMIN_SC_ALL"
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "CATALOG_SC_READ",
+        "key" : "catalog_read",
+        "roles" : "ROLE_CATALOG_READ",
+        "description" : "Allows users to browse the product catalog"
+      }, {
+        "name" : "CATALOG_SC_WRITE",
+        "key" : "catalog_write",
+        "roles" : "ROLE_CATALOG_WRITE",
+        "description" : "Allows users to create or update products"
+      }, {
+        "name" : "ORDERS_SC_READ",
+        "key" : "orders_read",
+        "roles" : "ROLE_ORDERS_READ",
+        "description" : "Allows users to view orders"
+      }, {
+        "name" : "ORDERS_SC_WRITE",
+        "key" : "orders_write",
+        "roles" : "ROLE_ORDERS_WRITE",
+        "description" : "Allows users to place or cancel orders"
+      }, {
+        "name" : "ACCOUNT_SC_READ",
+        "key" : "account_read",
+        "roles" : "ROLE_ACCOUNT_READ",
+        "description" : "Allows users to view their own account"
+      }, {
+        "name" : "ADMIN_SC_ALL",
+        "key" : "admin_all",
+        "roles" : "ROLE_ADMIN",
+        "description" : "Full administrative access"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/apim/OAR005/extensive-api.yaml b/src/test/resources/checks/v32/apim/OAR005/extensive-api.yaml
new file mode 100644
index 00000000..651b1ae9
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/extensive-api.yaml
@@ -0,0 +1,167 @@
+openapi: "3.2.0"
+info:
+  version: 2.1.0
+  title: Retail Storefront API
+  description: Public-facing REST API for the retail storefront covering product catalog browsing, order placement, account management, and platform administration.
+paths:
+  /catalog/products:
+    get:
+      operationId: get_catalog_products
+      summary: List products
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_READ
+    post:
+      operationId: post_catalog_products
+      summary: Create a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_WRITE
+  /catalog/products/{productId}:
+    get:
+      operationId: get_catalog_products_productId
+      summary: Get a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_READ
+    put:
+      operationId: put_catalog_products_productId
+      summary: Replace a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_WRITE
+    delete:
+      operationId: delete_catalog_products_productId
+      summary: Delete a product
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: CATALOG_SC_WRITE
+  /orders:
+    get:
+      operationId: get_orders
+      summary: List orders
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_READ
+    post:
+      operationId: post_orders
+      summary: Place an order
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_WRITE
+  /orders/{orderId}:
+    get:
+      operationId: get_orders_orderId
+      summary: Get an order
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_READ
+    delete:
+      operationId: delete_orders_orderId
+      summary: Cancel an order
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ORDERS_SC_WRITE
+  /account/profile:
+    get:
+      operationId: get_account_profile
+      summary: Get the caller's profile
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ACCOUNT_SC_READ
+    put:
+      operationId: put_account_profile
+      summary: Update the caller's profile - undeclared scope
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ACCOUNT_SC_WRITE # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  /admin/users:
+    get:
+      operationId: get_admin_users
+      summary: List platform users - matches key not name
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: admin_all # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    post:
+      operationId: post_admin_users
+      summary: Create a platform user
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ADMIN_SC_ALL
+  /admin/audit-log:
+    get:
+      operationId: get_admin_audit-log
+      summary: Read the audit log
+      responses:
+        200:
+          description: Ok
+        400:
+          description: Bad request
+      x-scope: ADMIN_SC_ALL
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: CATALOG_SC_READ
+        key: catalog_read
+        roles: ROLE_CATALOG_READ
+        description: Allows users to browse the product catalog
+      - name: CATALOG_SC_WRITE
+        key: catalog_write
+        roles: ROLE_CATALOG_WRITE
+        description: Allows users to create or update products
+      - name: ORDERS_SC_READ
+        key: orders_read
+        roles: ROLE_ORDERS_READ
+        description: Allows users to view orders
+      - name: ORDERS_SC_WRITE
+        key: orders_write
+        roles: ROLE_ORDERS_WRITE
+        description: Allows users to place or cancel orders
+      - name: ACCOUNT_SC_READ
+        key: account_read
+        roles: ROLE_ACCOUNT_READ
+        description: Allows users to view their own account
+      - name: ADMIN_SC_ALL
+        key: admin_all
+        roles: ROLE_ADMIN
+        description: Full administrative access
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-additional-operations.json b/src/test/resources/checks/v32/apim/OAR005/with-additional-operations.json
new file mode 100644
index 00000000..8e4e8bb3
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-additional-operations.json
@@ -0,0 +1,60 @@
+{
+  "openapi" : "3.2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/a" : {
+      "query" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "additionalOperations" : {
+        "PURGE" : {
+          "responses" : {
+            "200" : {
+              "description" : "Ok"
+            }
+          },
+          "x-scope" : "scope_six" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+        }
+      }
+    }
+  },
+  "webhooks" : {
+    "newPet" : {
+      "query" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_seven" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "additionalOperations" : {
+        "LINK" : {
+          "responses" : {
+            "200" : {
+              "description" : "Ok"
+            }
+          },
+          "x-scope" : "scope_eight" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+        }
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "scope_one",
+        "key" : "scope_one",
+        "roles" : "role_one"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-additional-operations.yaml b/src/test/resources/checks/v32/apim/OAR005/with-additional-operations.yaml
new file mode 100644
index 00000000..d5ec9127
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-additional-operations.yaml
@@ -0,0 +1,37 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    query:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    additionalOperations:
+      PURGE:
+        responses:
+          200:
+            description: Ok
+        x-scope: scope_six # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+webhooks:
+  newPet:
+    query:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_seven # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    additionalOperations:
+      LINK:
+        responses:
+          200:
+            description: Ok
+        x-scope: scope_eight # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        key: scope_one
+        roles: role_one
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-all-verbs.json b/src/test/resources/checks/v32/apim/OAR005/with-all-verbs.json
new file mode 100644
index 00000000..87f4f4dc
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-all-verbs.json
@@ -0,0 +1,93 @@
+{
+  "openapi" : "3.2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/a" : {
+      "x-scope" : "scope_one",
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "put" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "delete" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "options" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "head" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "patch" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "trace" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "query" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "scope_one",
+        "key" : "scope_one",
+        "roles" : "role_one"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-all-verbs.yaml b/src/test/resources/checks/v32/apim/OAR005/with-all-verbs.yaml
new file mode 100644
index 00000000..3a51a562
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-all-verbs.yaml
@@ -0,0 +1,59 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    x-scope: scope_one
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    delete:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    options:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    head:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    patch:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    trace:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    query:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        key: scope_one
+        roles: role_one
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-callback-operations.json b/src/test/resources/checks/v32/apim/OAR005/with-callback-operations.json
new file mode 100644
index 00000000..e967307f
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-callback-operations.json
@@ -0,0 +1,72 @@
+{
+  "openapi" : "3.2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/a" : {
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_one",
+        "callbacks" : {
+          "onEvent" : {
+            "'{$request.body#/callbackUrl}'" : {
+              "post" : {
+                "responses" : {
+                  "200" : {
+                    "description" : "Ok"
+                  }
+                },
+                "x-scope" : "scope_five", # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+                "callbacks" : {
+                  "onNested" : {
+                    "'{$request.body#/nestedUrl}'" : {
+                      "post" : {
+                        "responses" : {
+                          "200" : {
+                            "description" : "Ok"
+                          }
+                        },
+                        "x-scope" : "scope_six" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  },
+  "components" : {
+    "callbacks" : {
+      "sharedCallback" : {
+        "'{$request.body#/callbackUrl}'" : {
+          "post" : {
+            "responses" : {
+              "200" : {
+                "description" : "Ok"
+              }
+            },
+            "x-scope" : "scope_seven" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+          }
+        }
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "scope_one",
+        "key" : "scope_one",
+        "roles" : "role_one"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-callback-operations.yaml b/src/test/resources/checks/v32/apim/OAR005/with-callback-operations.yaml
new file mode 100644
index 00000000..ea61929f
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-callback-operations.yaml
@@ -0,0 +1,43 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /a:
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one
+      callbacks:
+        onEvent:
+          '{$request.body#/callbackUrl}':
+            post:
+              responses:
+                200:
+                  description: Ok
+              x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+              callbacks:
+                onNested:
+                  '{$request.body#/nestedUrl}':
+                    post:
+                      responses:
+                        200:
+                          description: Ok
+                      x-scope: scope_six # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+components:
+  callbacks:
+    sharedCallback:
+      '{$request.body#/callbackUrl}':
+        post:
+          responses:
+            200:
+              description: Ok
+          x-scope: scope_seven # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        key: scope_one
+        roles: role_one
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-chained-ref-security.json b/src/test/resources/checks/v32/apim/OAR005/with-chained-ref-security.json
new file mode 100644
index 00000000..8b8fe22d
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-chained-ref-security.json
@@ -0,0 +1,50 @@
+{
+  "openapi" : "3.2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_two"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "$ref" : "#/x-wso2-definitions/alias"
+  },
+  "x-wso2-definitions" : {
+    "alias" : {
+      "$ref" : "#/x-wso2-definitions/security"
+    },
+    "security" : {
+      "apim" : {
+        "x-wso2-scopes" : [ {
+          "name" : "scope_one",
+          "description" : "scope_one",
+          "key" : "scope_one",
+          "roles" : "role_one"
+        }, {
+          "name" : "scope_two",
+          "description" : "scope_two",
+          "key" : "scope_two",
+          "roles" : "role_two"
+        } ]
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-chained-ref-security.yaml b/src/test/resources/checks/v32/apim/OAR005/with-chained-ref-security.yaml
new file mode 100644
index 00000000..ba388fec
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-chained-ref-security.yaml
@@ -0,0 +1,33 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_two
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  $ref: "#/x-wso2-definitions/alias"
+x-wso2-definitions:
+  alias:
+    $ref: "#/x-wso2-definitions/security"
+  security:
+    apim:
+      x-wso2-scopes:
+        - name: scope_one
+          description: scope_one
+          key: scope_one
+          roles: role_one
+        - name: scope_two
+          description: scope_two
+          key: scope_two
+          roles: role_two
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-ref-scope.json b/src/test/resources/checks/v32/apim/OAR005/with-ref-scope.json
new file mode 100644
index 00000000..f061e098
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-ref-scope.json
@@ -0,0 +1,55 @@
+{
+  "openapi" : "3.2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_one"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_two"
+      },
+      "put" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "scope_one",
+        "description" : "scope_one",
+        "key" : "scope_one",
+        "roles" : "role_one"
+      }, {
+        "$ref" : "#/x-wso2-definitions/scopeTwo"
+      } ]
+    }
+  },
+  "x-wso2-definitions" : {
+    "scopeTwo" : {
+      "name" : "scope_two",
+      "description" : "scope_two",
+      "key" : "scope_two",
+      "roles" : "role_two"
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-ref-scope.yaml b/src/test/resources/checks/v32/apim/OAR005/with-ref-scope.yaml
new file mode 100644
index 00000000..a4549e95
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-ref-scope.yaml
@@ -0,0 +1,36 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_two
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        description: scope_one
+        key: scope_one
+        roles: role_one
+      - $ref: "#/x-wso2-definitions/scopeTwo"
+x-wso2-definitions:
+  scopeTwo:
+    name: scope_two
+    description: scope_two
+    key: scope_two
+    roles: role_two
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-ref-security.json b/src/test/resources/checks/v32/apim/OAR005/with-ref-security.json
new file mode 100644
index 00000000..647837ec
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-ref-security.json
@@ -0,0 +1,47 @@
+{
+  "openapi" : "3.2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_two"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "$ref" : "#/x-wso2-definitions/security"
+  },
+  "x-wso2-definitions" : {
+    "security" : {
+      "apim" : {
+        "x-wso2-scopes" : [ {
+          "name" : "scope_one",
+          "description" : "scope_one",
+          "key" : "scope_one",
+          "roles" : "role_one"
+        }, {
+          "name" : "scope_two",
+          "description" : "scope_two",
+          "key" : "scope_two",
+          "roles" : "role_two"
+        } ]
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-ref-security.yaml b/src/test/resources/checks/v32/apim/OAR005/with-ref-security.yaml
new file mode 100644
index 00000000..1a88793d
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-ref-security.yaml
@@ -0,0 +1,31 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_two
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  $ref: "#/x-wso2-definitions/security"
+x-wso2-definitions:
+  security:
+    apim:
+      x-wso2-scopes:
+        - name: scope_one
+          description: scope_one
+          key: scope_one
+          roles: role_one
+        - name: scope_two
+          description: scope_two
+          key: scope_two
+          roles: role_two
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-scope-key-not-name.json b/src/test/resources/checks/v32/apim/OAR005/with-scope-key-not-name.json
new file mode 100644
index 00000000..0022eb31
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-scope-key-not-name.json
@@ -0,0 +1,37 @@
+{
+  "openapi" : "3.2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "catalogue_read"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "read" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "catalogue_read",
+        "description" : "catalogue_read",
+        "key" : "read",
+        "roles" : "role_one"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-scope-key-not-name.yaml b/src/test/resources/checks/v32/apim/OAR005/with-scope-key-not-name.yaml
new file mode 100644
index 00000000..97955637
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-scope-key-not-name.yaml
@@ -0,0 +1,24 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: catalogue_read
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: read # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: catalogue_read
+        description: catalogue_read
+        key: read
+        roles: role_one
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-scopes-as-map.json b/src/test/resources/checks/v32/apim/OAR005/with-scopes-as-map.json
new file mode 100644
index 00000000..dde82ce2
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-scopes-as-map.json
@@ -0,0 +1,66 @@
+{
+  "openapi" : "3.2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "read_scope"
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "read" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "put" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "write_scope"
+      },
+      "delete" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : {
+        "read" : {
+          "name" : "read_scope",
+          "key" : "read",
+          "roles" : "ROLE_READ",
+          "description" : "Allows users to read the catalogue"
+        },
+        "write" : {
+          "$ref" : "#/x-wso2-definitions/writeScope"
+        }
+      }
+    }
+  },
+  "x-wso2-definitions" : {
+    "writeScope" : {
+      "name" : "write_scope",
+      "key" : "write",
+      "roles" : "ROLE_WRITE",
+      "description" : "Allows users to write the catalogue"
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-scopes-as-map.yaml b/src/test/resources/checks/v32/apim/OAR005/with-scopes-as-map.yaml
new file mode 100644
index 00000000..4c837278
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-scopes-as-map.yaml
@@ -0,0 +1,43 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: read_scope
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: read # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    put:
+      responses:
+        200:
+          description: Ok
+      x-scope: write_scope
+    delete:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      read:
+        name: read_scope
+        key: read
+        roles: ROLE_READ
+        description: Allows users to read the catalogue
+      write:
+        $ref: "#/x-wso2-definitions/writeScope"
+x-wso2-definitions:
+  writeScope:
+    name: write_scope
+    key: write
+    roles: ROLE_WRITE
+    description: Allows users to write the catalogue
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-webhook-operations.json b/src/test/resources/checks/v32/apim/OAR005/with-webhook-operations.json
new file mode 100644
index 00000000..75423a0a
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-webhook-operations.json
@@ -0,0 +1,60 @@
+{
+  "openapi" : "3.2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "$ref" : "#/components/pathItems/PetsPath"
+    }
+  },
+  "webhooks" : {
+    "newPet" : {
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_five" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      }
+    }
+  },
+  "components" : {
+    "pathItems" : {
+      "PetsPath" : {
+        "x-scope" : "scope_one",
+        "get" : {
+          "responses" : {
+            "200" : {
+              "description" : "Ok"
+            }
+          },
+          "x-scope" : "scope_six" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+        }
+      }
+    },
+    "webhooks" : {
+      "reusableWebhook" : {
+        "post" : {
+          "responses" : {
+            "200" : {
+              "description" : "Ok"
+            }
+          },
+          "x-scope" : "scope_seven" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+        }
+      }
+    }
+  },
+  "x-wso2-security" : {
+    "apim" : {
+      "x-wso2-scopes" : [ {
+        "name" : "scope_one",
+        "key" : "scope_one",
+        "roles" : "role_one"
+      } ]
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/apim/OAR005/with-webhook-operations.yaml b/src/test/resources/checks/v32/apim/OAR005/with-webhook-operations.yaml
new file mode 100644
index 00000000..5524e9f4
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/with-webhook-operations.yaml
@@ -0,0 +1,38 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    $ref: "#/components/pathItems/PetsPath"
+webhooks:
+  newPet:
+    post:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_five # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+components:
+  pathItems:
+    PetsPath:
+      x-scope: scope_one
+      get:
+        responses:
+          200:
+            description: Ok
+        x-scope: scope_six # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+  webhooks:
+    reusableWebhook:
+      post:
+        responses:
+          200:
+            description: Ok
+        x-scope: scope_seven # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+      - name: scope_one
+        key: scope_one
+        roles: role_one
diff --git a/src/test/resources/checks/v32/apim/OAR005/without-security.json b/src/test/resources/checks/v32/apim/OAR005/without-security.json
new file mode 100644
index 00000000..fd2319a3
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/without-security.json
@@ -0,0 +1,26 @@
+{
+  "openapi" : "3.2.0",
+  "info" : {
+    "version" : "1.0.0",
+    "title" : "Swagger Petstore"
+  },
+  "paths" : {
+    "/pets" : {
+      "get" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        },
+        "x-scope" : "scope_one" # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+      },
+      "post" : {
+        "responses" : {
+          "200" : {
+            "description" : "Ok"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/apim/OAR005/without-security.yaml b/src/test/resources/checks/v32/apim/OAR005/without-security.yaml
new file mode 100644
index 00000000..3339db32
--- /dev/null
+++ b/src/test/resources/checks/v32/apim/OAR005/without-security.yaml
@@ -0,0 +1,15 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: Ok
+      x-scope: scope_one # Noncompliant {{OAR005: WSO2 scope definition does not exists}}
+    post:
+      responses:
+        200:
+          description: Ok
diff --git a/src/test/resources/checks/v32/format/OAR007/with-204-response.json b/src/test/resources/checks/v32/format/OAR007/with-204-response.json
new file mode 100644
index 00000000..bab1a2ca
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-204-response.json
@@ -0,0 +1,18 @@
+{
+  "openapi": "3.2.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "delete": {
+        "responses": {
+          "204": {
+            "description": "No Content"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/format/OAR007/with-204-response.yaml b/src/test/resources/checks/v32/format/OAR007/with-204-response.yaml
new file mode 100644
index 00000000..92acae09
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-204-response.yaml
@@ -0,0 +1,10 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    delete:
+      responses:
+        '204':
+          description: No Content
diff --git a/src/test/resources/checks/v32/format/OAR007/with-chained-ref.json b/src/test/resources/checks/v32/format/OAR007/with-chained-ref.json
new file mode 100644
index 00000000..969d51ca
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-chained-ref.json
@@ -0,0 +1,28 @@
+{
+  "openapi": "3.2.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "components": {
+    "responses": {
+      "A": {
+        "$ref": "#/components/responses/B"
+      },
+      "B": { # Noncompliant {{OAR007: Section content is mandatory}}
+        "description": "No content defined"
+      }
+    }
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/A"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/format/OAR007/with-chained-ref.yaml b/src/test/resources/checks/v32/format/OAR007/with-chained-ref.yaml
new file mode 100644
index 00000000..7b7d9803
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-chained-ref.yaml
@@ -0,0 +1,16 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+components:
+  responses:
+    A:
+      $ref: '#/components/responses/B'
+    B: # Noncompliant {{OAR007: Section content is mandatory}}
+      description: No content defined
+paths:
+  /pets:
+    put:
+      responses:
+        '200':
+          $ref: '#/components/responses/A'
diff --git a/src/test/resources/checks/v32/format/OAR007/with-default-and-ref.json b/src/test/resources/checks/v32/format/OAR007/with-default-and-ref.json
new file mode 100644
index 00000000..ae69aeff
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-default-and-ref.json
@@ -0,0 +1,28 @@
+{
+  "openapi": "3.2.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "components": {
+    "responses": {
+      "PetsResponse": {
+        "description": "OK",
+        "content": {
+          "application/json": {}
+        }
+      }
+    }
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/PetsResponse"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/format/OAR007/with-default-and-ref.yaml b/src/test/resources/checks/v32/format/OAR007/with-default-and-ref.yaml
new file mode 100644
index 00000000..36a3ed7d
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-default-and-ref.yaml
@@ -0,0 +1,16 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+components:
+  responses:
+    PetsResponse:
+      description: OK
+      content:
+        application/json: {}
+paths:
+  /pets:
+    put:
+      responses:
+        '200':
+          $ref: '#/components/responses/PetsResponse'
diff --git a/src/test/resources/checks/v32/format/OAR007/with-default-response-key.json b/src/test/resources/checks/v32/format/OAR007/with-default-response-key.json
new file mode 100644
index 00000000..0ca74d2d
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-default-response-key.json
@@ -0,0 +1,19 @@
+{
+  "openapi": "3.2.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "post": {
+        "responses": {
+          "default": { # Noncompliant {{OAR007: Section content is mandatory}}
+            "description": "Unexpected error",
+            "content": {}
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/format/OAR007/with-default-response-key.yaml b/src/test/resources/checks/v32/format/OAR007/with-default-response-key.yaml
new file mode 100644
index 00000000..1b5d2fae
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-default-response-key.yaml
@@ -0,0 +1,11 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    post:
+      responses:
+        default: # Noncompliant {{OAR007: Section content is mandatory}}
+          description: Unexpected error
+          content: {}
diff --git a/src/test/resources/checks/v32/format/OAR007/with-external-ref.json b/src/test/resources/checks/v32/format/OAR007/with-external-ref.json
new file mode 100644
index 00000000..3efefeac
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-external-ref.json
@@ -0,0 +1,18 @@
+{
+  "openapi": "3.2.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "responses": {
+          "200": {
+            "$ref": "http://localhost:18089/OAR007.yaml#/components/responses/SuccessResponse"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/format/OAR007/with-external-ref.yaml b/src/test/resources/checks/v32/format/OAR007/with-external-ref.yaml
new file mode 100644
index 00000000..b5813931
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-external-ref.yaml
@@ -0,0 +1,11 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    put:
+      responses:
+        '200':
+          $ref: >-
+            http://localhost:18089/OAR007.yaml#/components/responses/SuccessResponse
diff --git a/src/test/resources/checks/v32/format/OAR007/with-multiple-operations.json b/src/test/resources/checks/v32/format/OAR007/with-multiple-operations.json
new file mode 100644
index 00000000..d94df219
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-multiple-operations.json
@@ -0,0 +1,53 @@
+{
+  "openapi": "3.2.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "get": {
+        "responses": {
+          "200": {
+            "description": "Ok",
+            "content": {
+              "application/json": {}
+            }
+          },
+          "204": {
+            "description": "No Content"
+          }
+        }
+      },
+      "post": {
+        "responses": {
+          "201": { # Noncompliant {{OAR007: Section content is mandatory}}
+            "description": "Created"
+          }
+        }
+      }
+    },
+    "/owners": {
+      "put": {
+        "responses": {
+          "200": {
+            "description": "Ok",
+            "content": {
+              "application/xml": {}
+            }
+          },
+          "400": { # Noncompliant {{OAR007: Section content is mandatory}}
+            "description": "Bad Request"
+          }
+        }
+      },
+      "delete": {
+        "responses": {
+          "204": {
+            "description": "No Content"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/format/OAR007/with-multiple-operations.yaml b/src/test/resources/checks/v32/format/OAR007/with-multiple-operations.yaml
new file mode 100644
index 00000000..92260973
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-multiple-operations.yaml
@@ -0,0 +1,31 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    get:
+      responses:
+        '200':
+          description: Ok
+          content:
+            application/json: {}
+        '204':
+          description: No Content
+    post:
+      responses:
+        '201': # Noncompliant {{OAR007: Section content is mandatory}}
+          description: Created
+  /owners:
+    put:
+      responses:
+        '200':
+          description: Ok
+          content:
+            application/xml: {}
+        '400': # Noncompliant {{OAR007: Section content is mandatory}}
+          description: Bad Request
+    delete:
+      responses:
+        '204':
+          description: No Content
diff --git a/src/test/resources/checks/v32/format/OAR007/with-specific.json b/src/test/resources/checks/v32/format/OAR007/with-specific.json
new file mode 100644
index 00000000..f722e678
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-specific.json
@@ -0,0 +1,21 @@
+{
+  "openapi": "3.2.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "responses": {
+          "200": {
+            "description": "Ok",
+            "content": {
+              "application/json": {}
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/format/OAR007/with-specific.yaml b/src/test/resources/checks/v32/format/OAR007/with-specific.yaml
new file mode 100644
index 00000000..f74596be
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-specific.yaml
@@ -0,0 +1,12 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    put:
+      responses:
+        '200':
+          description: Ok
+          content:
+            application/json: {}
diff --git a/src/test/resources/checks/v32/format/OAR007/with-wrong-ref.json b/src/test/resources/checks/v32/format/OAR007/with-wrong-ref.json
new file mode 100644
index 00000000..47e7b3c7
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-wrong-ref.json
@@ -0,0 +1,25 @@
+{
+  "openapi": "3.2.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "components": {
+    "responses": {
+      "PetsResponse": { # Noncompliant {{OAR007: Section content is mandatory}}
+        "description": "No content defined"
+      }
+    }
+  },
+  "paths": {
+    "/pets": {
+      "put": {
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/PetsResponse"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/format/OAR007/with-wrong-ref.yaml b/src/test/resources/checks/v32/format/OAR007/with-wrong-ref.yaml
new file mode 100644
index 00000000..9a687bef
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR007/with-wrong-ref.yaml
@@ -0,0 +1,14 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+components:
+  responses:
+    PetsResponse: # Noncompliant {{OAR007: Section content is mandatory}}
+      description: No content defined
+paths:
+  /pets:
+    put:
+      responses:
+        '200':
+          $ref: '#/components/responses/PetsResponse'
diff --git a/src/test/resources/checks/v32/format/OAR010/with-204-response.json b/src/test/resources/checks/v32/format/OAR010/with-204-response.json
new file mode 100644
index 00000000..4c4eaec2
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR010/with-204-response.json
@@ -0,0 +1,27 @@
+{
+  "openapi": "3.2.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "post": {
+        "responses": {
+          "200": {
+            "description": "Ok",
+            "content": {
+              "application/json": {}
+            }
+          },
+          "204": {
+            "description": "No Content",
+            "content": {
+              "application/xml": {}
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/format/OAR010/with-204-response.yaml b/src/test/resources/checks/v32/format/OAR010/with-204-response.yaml
new file mode 100644
index 00000000..1882ff1f
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR010/with-204-response.yaml
@@ -0,0 +1,16 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    post:
+      responses:
+        '200':
+          description: Ok
+          content:
+            application/json: {}
+        '204':
+          description: No Content
+          content:
+            application/xml: {}
diff --git a/src/test/resources/checks/v32/format/OAR010/with-default-mixed-case.json b/src/test/resources/checks/v32/format/OAR010/with-default-mixed-case.json
new file mode 100644
index 00000000..d73a6340
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR010/with-default-mixed-case.json
@@ -0,0 +1,21 @@
+{
+  "openapi": "3.2.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "paths": {
+    "/pets": {
+      "post": {
+        "responses": {
+          "200": {
+            "description": "Ok",
+            "content": {
+              "Application/JSON": {}
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/format/OAR010/with-default-mixed-case.yaml b/src/test/resources/checks/v32/format/OAR010/with-default-mixed-case.yaml
new file mode 100644
index 00000000..10787780
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR010/with-default-mixed-case.yaml
@@ -0,0 +1,12 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+paths:
+  /pets:
+    post:
+      responses:
+        '200':
+          description: Ok
+          content:
+            Application/JSON: {}
diff --git a/src/test/resources/checks/v32/format/OAR010/with-wrong-default-and-ref.json b/src/test/resources/checks/v32/format/OAR010/with-wrong-default-and-ref.json
new file mode 100644
index 00000000..7b069a9d
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR010/with-wrong-default-and-ref.json
@@ -0,0 +1,28 @@
+{
+  "openapi": "3.2.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Swagger Petstore"
+  },
+  "components": {
+    "responses": {
+      "XmlOnlyResponse": {
+        "description": "OK",
+        "content": { # Noncompliant {{OAR010: Should indicate the default response media type}}
+          "application/xml": {}
+        }
+      }
+    }
+  },
+  "paths": {
+    "/pets": {
+      "post": {
+        "responses": {
+          "200": {
+            "$ref": "#/components/responses/XmlOnlyResponse"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/test/resources/checks/v32/format/OAR010/with-wrong-default-and-ref.yaml b/src/test/resources/checks/v32/format/OAR010/with-wrong-default-and-ref.yaml
new file mode 100644
index 00000000..69695377
--- /dev/null
+++ b/src/test/resources/checks/v32/format/OAR010/with-wrong-default-and-ref.yaml
@@ -0,0 +1,16 @@
+openapi: "3.2.0"
+info:
+  version: 1.0.0
+  title: Swagger Petstore
+components:
+  responses:
+    XmlOnlyResponse:
+      description: OK
+      content: # Noncompliant {{OAR010: Should indicate the default response media type}}
+        application/xml: {}
+paths:
+  /pets:
+    post:
+      responses:
+        '200':
+          $ref: '#/components/responses/XmlOnlyResponse'

From 41a88efb6677b2758b08e4d95556af5474d6229b Mon Sep 17 00:00:00 2001
From: Melsy Huamani 
Date: Thu, 10 Sep 2026 22:08:19 -0500
Subject: [PATCH 2/3] fix: oar026, oar031 rules

---
 CHANGELOG.md                                  |   2 +
 .../checks/examples/OAR031ExamplesCheck.java  | 165 +++++++++++++++---
 ...OAR026TotalParameterDefaultValueCheck.java |  51 ++++--
 src/main/resources/messages/errors.properties |   8 +-
 .../resources/messages/errors_es.properties   |   8 +-
 .../rules/openapi/examples/OAR031.html        |  10 +-
 .../examples/OAR031ExamplesCheckTest.java     |  36 ++++
 ...26TotalParameterDefaultValueCheckTest.java | 142 +++++++++++++++
 .../OAR031/allof-schema-missing-example.yaml  |  28 +++
 .../v2/examples/OAR031/externalref.yaml       |  10 +-
 .../OAR031/nested-properties-examples.yaml    |   4 +-
 .../v2/examples/OAR031/orphan-schema.yaml     |  28 +++
 .../checks/v2/examples/OAR031/valid.json      |   2 +-
 .../v2/examples/OAR031/without-examples.json  |  14 +-
 .../v2/examples/OAR031/without-examples.yaml  |  14 +-
 .../header-with-$total-with-defval-true.json  |  24 +++
 .../header-with-$total-with-defval-true.yaml  |  15 ++
 .../plain-with-$total-without-defval.json     |   2 +-
 .../plain-with-$total-without-defval.yaml     |   2 +-
 .../post-with-$total-with-defval-true.json    |  24 +++
 .../post-with-$total-with-defval-true.yaml    |  15 ++
 ...ferenced-with-$total-with-defval-true.json |  26 +++
 ...ferenced-with-$total-with-defval-true.yaml |  16 ++
 .../with-$ref-with-$total-without-defval.json |   2 +-
 .../with-$ref-with-$total-without-defval.yaml |   2 +-
 .../OAR031/allof-schema-missing-example.yaml  |  32 ++++
 .../v3/examples/OAR031/externalref.yaml       |   8 +-
 .../OAR031/nested-properties-examples.yaml    |   4 +-
 .../v3/examples/OAR031/orphan-schema.yaml     |  32 ++++
 .../v3/examples/OAR031/without-examples.yaml  |  20 +--
 .../header-with-$total-with-defval-true.json  |  26 +++
 .../header-with-$total-with-defval-true.yaml  |  16 ++
 .../plain-with-$total-without-defval.json     |   2 +-
 .../plain-with-$total-without-defval.yaml     |   2 +-
 .../post-with-$total-with-defval-true.json    |  26 +++
 .../post-with-$total-with-defval-true.yaml    |  16 ++
 ...ferenced-with-$total-with-defval-true.json |  30 ++++
 ...ferenced-with-$total-with-defval-true.yaml |  18 ++
 .../with-$ref-with-$total-without-defval.json |   2 +-
 .../with-$ref-with-$total-without-defval.yaml |   2 +-
 .../OAR031/allof-schema-missing-example.yaml  |  32 ++++
 .../v31/examples/OAR031/externalref.yaml      |   8 +-
 .../OAR031/nested-properties-examples.yaml    |   4 +-
 .../v31/examples/OAR031/orphan-schema.yaml    |  32 ++++
 .../v31/examples/OAR031/without-examples.yaml |  20 +--
 .../header-with-$total-with-defval-true.json  |  26 +++
 .../header-with-$total-with-defval-true.yaml  |  16 ++
 .../plain-with-$total-without-defval.json     |   2 +-
 .../plain-with-$total-without-defval.yaml     |   2 +-
 .../post-with-$total-with-defval-true.json    |  26 +++
 .../post-with-$total-with-defval-true.yaml    |  16 ++
 ...ferenced-with-$total-with-defval-true.json |  30 ++++
 ...ferenced-with-$total-with-defval-true.yaml |  18 ++
 .../with-$ref-with-$total-without-defval.json |   2 +-
 .../with-$ref-with-$total-without-defval.yaml |   2 +-
 .../OAR031/allof-schema-missing-example.yaml  |  32 ++++
 .../v32/examples/OAR031/externalref.yaml      |   8 +-
 .../OAR031/nested-properties-examples.yaml    |   4 +-
 .../v32/examples/OAR031/orphan-schema.yaml    |  32 ++++
 .../v32/examples/OAR031/without-examples.yaml |  20 +--
 .../header-with-$total-with-defval-true.json  |  26 +++
 .../header-with-$total-with-defval-true.yaml  |  16 ++
 .../plain-with-$total-without-defval.json     |   2 +-
 .../plain-with-$total-without-defval.yaml     |   2 +-
 .../post-with-$total-with-defval-true.json    |  26 +++
 .../post-with-$total-with-defval-true.yaml    |  16 ++
 ...ferenced-with-$total-with-defval-true.json |  30 ++++
 ...ferenced-with-$total-with-defval-true.yaml |  18 ++
 .../with-$ref-with-$total-without-defval.json |   2 +-
 .../with-$ref-with-$total-without-defval.yaml |   2 +-
 70 files changed, 1227 insertions(+), 131 deletions(-)
 create mode 100644 src/test/resources/checks/v2/examples/OAR031/allof-schema-missing-example.yaml
 create mode 100644 src/test/resources/checks/v2/examples/OAR031/orphan-schema.yaml
 create mode 100644 src/test/resources/checks/v2/parameters/OAR026/header-with-$total-with-defval-true.json
 create mode 100644 src/test/resources/checks/v2/parameters/OAR026/header-with-$total-with-defval-true.yaml
 create mode 100644 src/test/resources/checks/v2/parameters/OAR026/post-with-$total-with-defval-true.json
 create mode 100644 src/test/resources/checks/v2/parameters/OAR026/post-with-$total-with-defval-true.yaml
 create mode 100644 src/test/resources/checks/v2/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json
 create mode 100644 src/test/resources/checks/v2/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml
 create mode 100644 src/test/resources/checks/v3/examples/OAR031/allof-schema-missing-example.yaml
 create mode 100644 src/test/resources/checks/v3/examples/OAR031/orphan-schema.yaml
 create mode 100644 src/test/resources/checks/v3/parameters/OAR026/header-with-$total-with-defval-true.json
 create mode 100644 src/test/resources/checks/v3/parameters/OAR026/header-with-$total-with-defval-true.yaml
 create mode 100644 src/test/resources/checks/v3/parameters/OAR026/post-with-$total-with-defval-true.json
 create mode 100644 src/test/resources/checks/v3/parameters/OAR026/post-with-$total-with-defval-true.yaml
 create mode 100644 src/test/resources/checks/v3/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json
 create mode 100644 src/test/resources/checks/v3/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml
 create mode 100644 src/test/resources/checks/v31/examples/OAR031/allof-schema-missing-example.yaml
 create mode 100644 src/test/resources/checks/v31/examples/OAR031/orphan-schema.yaml
 create mode 100644 src/test/resources/checks/v31/parameters/OAR026/header-with-$total-with-defval-true.json
 create mode 100644 src/test/resources/checks/v31/parameters/OAR026/header-with-$total-with-defval-true.yaml
 create mode 100644 src/test/resources/checks/v31/parameters/OAR026/post-with-$total-with-defval-true.json
 create mode 100644 src/test/resources/checks/v31/parameters/OAR026/post-with-$total-with-defval-true.yaml
 create mode 100644 src/test/resources/checks/v31/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json
 create mode 100644 src/test/resources/checks/v31/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml
 create mode 100644 src/test/resources/checks/v32/examples/OAR031/allof-schema-missing-example.yaml
 create mode 100644 src/test/resources/checks/v32/examples/OAR031/orphan-schema.yaml
 create mode 100644 src/test/resources/checks/v32/parameters/OAR026/header-with-$total-with-defval-true.json
 create mode 100644 src/test/resources/checks/v32/parameters/OAR026/header-with-$total-with-defval-true.yaml
 create mode 100644 src/test/resources/checks/v32/parameters/OAR026/post-with-$total-with-defval-true.json
 create mode 100644 src/test/resources/checks/v32/parameters/OAR026/post-with-$total-with-defval-true.yaml
 create mode 100644 src/test/resources/checks/v32/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json
 create mode 100644 src/test/resources/checks/v32/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cb0cb08c..52cd61ef 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - OAR005 - UndefinedWso2ScopeUse - Resolve a `$ref` on `x-wso2-security` and on each individual scope, and iterate map-form `x-wso2-scopes` in addition to the array form (shared with `AbstractWso2ScopesCheck` through new `JsonNodeUtils` helpers), so an operation whose `x-scope` names a scope declared behind a reference or under a mapping key is no longer reported. Also accept the `~`/`Null`/`NULL` null spellings for the operation's `x-scope` (previously only the lowercase `null` scalar was treated as null). Matching remains on the scope `name` only, never on `key`.
 - OAR009 / OAR010 - DefaultRequestMediaType / DefaultResponseMediaType - `AbstractDefaultMediaTypeCheck` now compares `default-media-type` and the document's actual media types case-insensitively (matching Spectral's `apq-response-media-type`), so a spec written with mixed-case media types (e.g. `Application/JSON`) or a `default-media-type` property configured with different casing no longer diverges from Spectral.
 - OAR007 - UndefinedResponseMediaType - Fixed the rule description: paragraph 1 wrongly stated "the request data formats must be defined" and referenced the `"consumes"` keyword (copy-pasted from OAR006); corrected to describe response media types and the `"produces"` keyword, matching the already-correct Spanish translation and the rest of the description.
+- OAR026 - TotalParameterDefaultValue - Rewritten to match Spectral exactly: subscribes to `GET` operations (was every `PARAMETER` node in the document) and only evaluates a `$total` parameter that is `in: query`, resolving `$ref`s (internal and external) along the way; a `$total` parameter under a non-`GET` operation, with a different `in`, or declared but never referenced by any `GET` is no longer flagged. A missing `default` is no longer reported (previously it was) - only an explicitly-declared non-`false` default raises an issue, matching Spectral's `falsy` semantics.
+- OAR031 - Examples - Property-level checks (`validateProperty`) now only cover schemas actually reachable from a path's `parameters`/`requestBody`/`responses` (matching Spectral's `given` reach); an unreferenced `components.schemas`/`definitions` entry no longer produces false-positive property findings. Removed a hack that skipped every direct property of a schema with an `allOf` sibling key, and added `allOf`/`oneOf`/`anyOf` traversal to `isSchemaCovered` and the v2 response property walk, so a property declared only inside a combiner member (e.g. inherited via `allOf`) is now correctly checked (previously a false negative). Parameter- and property-level messages now interpolate the actual name (`Parameter '' must have an example defined`, `Property '' is missing an example.`), matching Spectral verbatim; response/request-body message text also corrected to match Spectral exactly (`Response must have an example defined`, `Request body must have an example defined`). Fixed the English rule doc listing the four toggle rule-property names in kebab-case (`validate-response`, ...) when the real keys are camelCase (`validateResponse`, ...). Also, found while cross-checking line numbers against Spectral: a `$ref`'d parameter's violation is now anchored at the shared definition's own key (e.g. `id:`) instead of its first content line, matching the response/request-body anchoring convention and Spectral's line; an OAS3 parameter example declared per media type under `content` is now recognized (previously always flagged as missing, regardless of a valid content-based example); the v2 response-driven property walk (`visitPathNode`) now excludes `204` responses, matching the primary walk; and Swagger 2.0 non-`body` parameters (query/path/header/formData) are now exempt from the parameter-level check in Spectral too (that field doesn't exist in the OAS2 parameter spec, only `default` does - Sonar already exempted them).
 
 ## [1.6.0-beta-5] - 2026-09-09
 
diff --git a/src/main/java/apiaddicts/sonar/openapi/checks/examples/OAR031ExamplesCheck.java b/src/main/java/apiaddicts/sonar/openapi/checks/examples/OAR031ExamplesCheck.java
index d174a7f0..3c91e621 100644
--- a/src/main/java/apiaddicts/sonar/openapi/checks/examples/OAR031ExamplesCheck.java
+++ b/src/main/java/apiaddicts/sonar/openapi/checks/examples/OAR031ExamplesCheck.java
@@ -8,6 +8,7 @@
 import static apiaddicts.sonar.openapi.utils.JsonNodeUtils.isOperation;
 import com.google.common.collect.ImmutableSet;
 import com.sonar.sslr.api.AstNodeType;
+import java.util.HashSet;
 import java.util.Set;
 import org.apiaddicts.apitools.dosonarapi.api.v2.OpenApi2Grammar;
 import org.apiaddicts.apitools.dosonarapi.api.v3.OpenApi3Grammar;
@@ -26,9 +27,12 @@ public class OAR031ExamplesCheck extends BaseCheck {
     private static final String SCHEMA = "schema";
     private static final String PROPERTIES = "properties";
     private static final String ITEMS = "items";
+    private static final String[] COMBINERS = {"allOf", "oneOf", "anyOf"};
 
     private static final String ERROR_RESPONSE = "OAR031.error-response";
     private static final String ERROR_REQUEST = "OAR031.error-request";
+    private static final String ERROR_PARAMETER = "OAR031.error-parameter";
+    private static final String ERROR_PROPERTY = "OAR031.error-property";
 
     @RuleProperty(
             key = "validateResponse",
@@ -64,6 +68,8 @@ public class OAR031ExamplesCheck extends BaseCheck {
 
     private final ExternalRefHandler handleExternalRef = new ExternalRefHandler();
 
+    private final Set reachableSchemaPointers = new HashSet<>();
+
     @Override
     public Set subscribedKinds() {
         return ImmutableSet.of(
@@ -76,6 +82,87 @@ public Set subscribedKinds() {
         );
     }
 
+    @Override
+    protected void visitFile(JsonNode root) {
+        reachableSchemaPointers.clear();
+        JsonNode pathsNode = root.get("paths");
+        if (!pathsNode.isMissing()) {
+            for (JsonNode pathItem : pathsNode.properties()) {
+                for (JsonNode operationProp : pathItem.properties()) {
+                    if (isOperation(operationProp)) {
+                        markOperationSchemasReachable(operationProp);
+                    }
+                }
+            }
+        }
+        super.visitFile(root);
+    }
+
+    private void markOperationSchemasReachable(JsonNode operation) {
+        JsonNode parameters = operation.get("parameters");
+        if (!parameters.isMissing() && parameters.isArray()) {
+            for (JsonNode parameterElement : parameters.elements()) {
+                handleExternalRef.resolve(parameterElement, resolved -> {
+                    if (OpenApi2Grammar.PARAMETER.equals(resolved.getType())) {
+                        JsonNode inNode = resolved.get("in");
+                        if (inNode.isMissing() || !"body".equals(inNode.getTokenValue())) {
+                            return;
+                        }
+                    }
+                    markReachable(resolved.get(SCHEMA));
+                });
+            }
+        }
+
+        JsonNode requestBody = operation.get("requestBody");
+        if (!requestBody.isMissing()) {
+            handleExternalRef.resolve(requestBody, this::markContentSchemas);
+        }
+
+        JsonNode responses = operation.get("responses");
+        if (!responses.isMissing()) {
+            for (JsonNode responseNode : responses.properties()) {
+                if ("204".equals(responseNode.key().getTokenValue())) continue;
+                handleExternalRef.resolve(responseNode, resolved -> {
+                    markReachable(resolved.get(SCHEMA));
+                    markContentSchemas(resolved);
+                });
+            }
+        }
+    }
+
+    private void markContentSchemas(JsonNode node) {
+        JsonNode content = node.get("content");
+        if (!content.isMissing()) {
+            content.propertyMap().values().forEach(mediaType -> markReachable(mediaType.get(SCHEMA)));
+        }
+    }
+
+    private void markReachable(JsonNode schema) {
+        if (schema == null || schema.isMissing()) return;
+        handleExternalRef.resolve(schema, resolved -> {
+            if (resolved.isMissing()) return;
+            if (!reachableSchemaPointers.add(resolved.getPointer())) return;
+
+            JsonNode props = resolved.get(PROPERTIES);
+            if (!props.isMissing() && props.isObject()) {
+                props.propertyMap().values().forEach(this::markReachable);
+            }
+
+            JsonNode items = resolved.get(ITEMS);
+            if (!items.isMissing()) {
+                markReachable(items);
+            }
+
+            for (String combiner : COMBINERS) {
+                JsonNode combinerNode = resolved.get(combiner);
+                if (!combinerNode.isMissing() && combinerNode.isArray()) {
+                    combinerNode.elements().forEach(this::markReachable);
+                }
+            }
+        });
+    }
+
     @Override
     public void visitNode(JsonNode node) {
         AstNodeType type = node.getType();
@@ -101,18 +188,35 @@ private void visitParameterNode(JsonNode node) {
 
             JsonNode schema = resolved.get(SCHEMA);
 
-            // Parameter level: the parameter itself, or its schema's ROOT, must declare an
-            // example. Examples buried inside schema properties do NOT satisfy this level.
+            // Parameter level: the parameter itself, its schema's ROOT, or (OAS3) a
+            // content media-type example, must declare an example. Examples buried inside
+            // schema properties do NOT satisfy this level.
             boolean hasExample = !resolved.get(EXAMPLE).isMissing()
                     || !resolved.get(EXAMPLES).isMissing()
-                    || schemaHasRootExample(schema);
+                    || schemaHasRootExample(schema)
+                    || hasContentExample(resolved);
 
             if (validateParameter && !hasExample) {
-                addIssue(KEY, translate("OAR031.error-parameter"), handleExternalRef.getTrueNode(node));
+                JsonNode nameNode = resolved.get("name");
+                String paramName = nameNode.isMissing() ? "" : nameNode.getTokenValue();
+                JsonNode trueNode = handleExternalRef.getTrueNode(node);
+                JsonNode anchor = trueNode.key().isMissing() ? trueNode : trueNode.key();
+                addIssue(KEY, translate(ERROR_PARAMETER, paramName), anchor);
             }
         });
     }
 
+    // OAS3 parameters may declare an example per media type under `content` instead of
+    // directly on the parameter or its schema root.
+    private boolean hasContentExample(JsonNode resolved) {
+        JsonNode content = resolved.get("content");
+        if (content.isMissing() || !content.isObject()) return false;
+        return content.propertyMap().values().stream().anyMatch(mediaType ->
+                !mediaType.get(EXAMPLE).isMissing()
+                        || !mediaType.get(EXAMPLES).isMissing()
+                        || schemaHasRootExample(mediaType.get(SCHEMA)));
+    }
+
     private void visitV2Node(JsonNode node) {
         AstNodeType type = node.getType();
         if (OpenApi2Grammar.RESPONSES.equals(type)) {
@@ -199,13 +303,22 @@ private boolean isSchemaCovered(JsonNode schemaNode) {
             }
 
             JsonNode props = resolved.get(PROPERTIES);
-            if (!props.isMissing() && props.isObject()) {
-                return props.propertyMap().values().stream().anyMatch(this::isSchemaCovered);
+            if (!props.isMissing() && props.isObject()
+                    && props.propertyMap().values().stream().anyMatch(this::isSchemaCovered)) {
+                return true;
             }
 
             JsonNode items = resolved.get(ITEMS);
-            if (!items.isMissing()) {
-                return isSchemaCovered(items);
+            if (!items.isMissing() && isSchemaCovered(items)) {
+                return true;
+            }
+
+            for (String combiner : COMBINERS) {
+                JsonNode combinerNode = resolved.get(combiner);
+                if (!combinerNode.isMissing() && combinerNode.isArray()
+                        && combinerNode.elements().stream().anyMatch(this::isSchemaCovered)) {
+                    return true;
+                }
             }
 
             return false;
@@ -215,6 +328,11 @@ private boolean isSchemaCovered(JsonNode schemaNode) {
     private void visitSchemaNode(JsonNode node) {
         if (!validateProperty) return;
 
+        JsonNode resolvedNode = handleExternalRef.resolve(node, r -> r);
+        if (!reachableSchemaPointers.contains(resolvedNode.getPointer())) {
+            return;
+        }
+
         JsonNode parentNode = (JsonNode) node.getParent().getParent();
 
         if (parentNode.getType().equals(OpenApi3Grammar.PARAMETER) || parentNode.getType().equals(OpenApi31Grammar.PARAMETER) || parentNode.getType().equals(OpenApi32Grammar.PARAMETER)) {
@@ -227,14 +345,9 @@ private void visitSchemaNode(JsonNode node) {
                 || parentNode.getType().toString().equals("BLOCK_MAPPING")
                 || parentNode.getType().toString().equals("FLOW_MAPPING")) {
 
-            JsonNode schemaParent = (JsonNode) parentNode.getParent().getParent();
-            if (schemaParent != null && !schemaParent.get("allOf").isMissing()) {
-                return;
-            }
-
             JsonNode type = getType(node);
             if (!isObjectType(type) && !type.isMissing() && !isArrayType(type) && node.get(EXAMPLE).isMissing()) {
-                addIssue(KEY, translate("OAR031.error-property"), node.key());
+                addIssue(KEY, translate(ERROR_PROPERTY, node.key().getTokenValue()), node.key());
             }
         }
     }
@@ -247,7 +360,8 @@ private void visitPathNode(JsonNode node) {
             .map(JsonNode::value)
             .map(operation -> operation.get("responses"))
             .filter(responses -> !responses.isMissing())
-            .flatMap(responses -> responses.propertyMap().values().stream())
+            .flatMap(responses -> responses.properties().stream())
+            .filter(responseNode -> !"204".equals(responseNode.key().getTokenValue()))
             .forEach(response -> handleExternalRef.resolve(response, resolved -> {
                 if (resolved.getType().equals(OpenApi2Grammar.RESPONSE)) {
                     visitSchemaNode2(resolved);
@@ -268,16 +382,27 @@ private void visitSchemaNode2(JsonNode responseNode) {
         JsonNode schemaNode = responseNode.value().get(SCHEMA);
         if (schemaNode.isMissing()) return;
 
-        handleExternalRef.resolve(schemaNode, resolvedSchema -> {
-            JsonNode props = resolvedSchema.get(PROPERTIES);
-            if (props.isMissing() || !props.isObject()) return;
+        handleExternalRef.resolve(schemaNode, this::checkSchemaProperties);
+    }
 
+    private Void checkSchemaProperties(JsonNode resolvedSchema) {
+        JsonNode props = resolvedSchema.get(PROPERTIES);
+        if (!props.isMissing() && props.isObject()) {
             props.propertyMap().forEach((key, propertyNode) -> {
                 JsonNode type = getType(propertyNode);
                 if (!type.isMissing() && !isObjectType(type) && !isArrayType(type) && !isSchemaCovered(propertyNode)) {
-                    addIssue(KEY, translate("OAR031.error-property"), handleExternalRef.getTrueNode(propertyNode.key()));
+                    addIssue(KEY, translate(ERROR_PROPERTY, key), handleExternalRef.getTrueNode(propertyNode.key()));
                 }
             });
-        });
+        }
+
+        for (String combiner : COMBINERS) {
+            JsonNode combinerNode = resolvedSchema.get(combiner);
+            if (!combinerNode.isMissing() && combinerNode.isArray()) {
+                combinerNode.elements().forEach(sub -> handleExternalRef.resolve(sub, this::checkSchemaProperties));
+            }
+        }
+
+        return null;
     }
 }
diff --git a/src/main/java/apiaddicts/sonar/openapi/checks/parameters/OAR026TotalParameterDefaultValueCheck.java b/src/main/java/apiaddicts/sonar/openapi/checks/parameters/OAR026TotalParameterDefaultValueCheck.java
index 57f41e5e..30266993 100644
--- a/src/main/java/apiaddicts/sonar/openapi/checks/parameters/OAR026TotalParameterDefaultValueCheck.java
+++ b/src/main/java/apiaddicts/sonar/openapi/checks/parameters/OAR026TotalParameterDefaultValueCheck.java
@@ -8,6 +8,7 @@
 import org.apiaddicts.apitools.dosonarapi.api.v31.OpenApi31Grammar;
 import org.apiaddicts.apitools.dosonarapi.api.v32.OpenApi32Grammar;
 import apiaddicts.sonar.openapi.checks.BaseCheck;
+import apiaddicts.sonar.openapi.utils.ExternalRefHandler;
 import org.apiaddicts.apitools.dosonarapi.sslr.yaml.grammar.JsonNode;
 
 import java.util.Set;
@@ -17,28 +18,52 @@ public class OAR026TotalParameterDefaultValueCheck extends BaseCheck {
 
     protected static final String KEY = "OAR026";
     private static final String MESSAGE = "OAR026.error";
+    private static final String TOTAL_PARAM_NAME = "$total";
+
+    private final ExternalRefHandler handleExternalRef = new ExternalRefHandler();
 
     @Override
     public Set subscribedKinds() {
-        return ImmutableSet.of(OpenApi2Grammar.PARAMETER, OpenApi3Grammar.PARAMETER, OpenApi31Grammar.PARAMETER, OpenApi32Grammar.PARAMETER);
+        return ImmutableSet.of(
+                OpenApi2Grammar.OPERATION, OpenApi3Grammar.OPERATION,
+                OpenApi31Grammar.OPERATION, OpenApi32Grammar.OPERATION);
     }
 
     @Override
     public void visitNode(JsonNode node) {
-        visitV2Node(node);
+        if (!"get".equals(node.key().getTokenValue())) {
+            return;
+        }
+
+        JsonNode parametersNode = node.get("parameters");
+        if (parametersNode.isMissing() || !parametersNode.isArray()) {
+            return;
+        }
+
+        for (JsonNode parameterElement : parametersNode.elements()) {
+            handleExternalRef.resolve(parameterElement, this::checkTotalParameter);
+        }
     }
 
-    private void visitV2Node(JsonNode node) {
-        if (!"$total".equals(node.get("name").getTokenValue())) return;
-        JsonNode defaultNode = (node.getType() == OpenApi2Grammar.PARAMETER) ? node.get("default") : node.at("/schema/default");
+    private void checkTotalParameter(JsonNode resolved) {
+        if (resolved.isMissing()) return;
+
+        JsonNode inNode = resolved.get("in");
+        if (inNode.isMissing() || !"query".equals(inNode.getTokenValue())) return;
+
+        JsonNode nameNode = resolved.get("name");
+        if (nameNode.isMissing() || !TOTAL_PARAM_NAME.equals(nameNode.getTokenValue())) return;
+
+        JsonNode defaultNode = (resolved.getType() == OpenApi2Grammar.PARAMETER)
+                ? resolved.get("default")
+                : resolved.at("/schema/default");
+
         if (defaultNode.isMissing()) {
-            if (node.key().isMissing()) {
-                addIssue(KEY, translate(MESSAGE), node);
-            } else {
-                addIssue(KEY, translate(MESSAGE), node.key());
-            }
-        } else if (!"false".equals(defaultNode.getTokenValue())) {
-            addIssue(KEY, translate(MESSAGE), defaultNode);
+            return;
+        }
+
+        if (!"false".equals(defaultNode.getTokenValue())) {
+            addIssue(KEY, translate(MESSAGE), handleExternalRef.getTrueNode(defaultNode));
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/resources/messages/errors.properties b/src/main/resources/messages/errors.properties
index c659580f..e401ed3e 100644
--- a/src/main/resources/messages/errors.properties
+++ b/src/main/resources/messages/errors.properties
@@ -32,10 +32,10 @@ OAR028.error={0} must be defined as a parameter in this operation
 OAR029.error-required-one-property=At least one property must be defined
 OAR030.error-path=The path ''{0}'' must be declared
 OAR030.error-verb=Method {0} must be declared
-OAR031.error-parameter=Parameters must have one or more examples defined
-OAR031.error-response=Responses must have one or more examples defined
-OAR031.error-request=Request body must have one or more examples defined
-OAR031.error-property=Properties must have an example defined
+OAR031.error-parameter=Parameter ''{0}'' must have an example defined
+OAR031.error-response=Response must have an example defined
+OAR031.error-request=Request body must have an example defined
+OAR031.error-property=Property ''{0}'' is missing an example.
 OAR032.error=Ambiguous path parts not encouraged: {0}
 OAR033.error-header-required=''{0}'' header must be required
 OAR035.error=Response code {0} must be defined for operations with security schemes defined
diff --git a/src/main/resources/messages/errors_es.properties b/src/main/resources/messages/errors_es.properties
index 51ce126b..2dc0ac29 100644
--- a/src/main/resources/messages/errors_es.properties
+++ b/src/main/resources/messages/errors_es.properties
@@ -32,10 +32,10 @@ OAR028.error={0} debe ser definido como un parámetro en esta operación
 OAR029.error-required-one-property=Se debe de definir al menos una propiedad
 OAR030.error-path=El path ''{0}'' debería estar declarado
 OAR030.error-verb=El método {0} debería estar declarado
-OAR031.error-parameter=Los parámetros deben tener uno o más ejemplos definidos
-OAR031.error-response=Las respuestas deben tener uno o más ejemplos definidos
-OAR031.error-request=El cuerpo de solicitud debe tener uno o más ejemplos definidos
-OAR031.error-property=Las propiedades deben definir un ejemplo definido
+OAR031.error-parameter=El parámetro ''{0}'' debe tener un ejemplo definido
+OAR031.error-response=La respuesta debe tener un ejemplo definido
+OAR031.error-request=El cuerpo de la solicitud debe tener un ejemplo definido
+OAR031.error-property=La propiedad ''{0}'' no tiene un ejemplo definido
 OAR032.error=Nombres de partes de path ambiguos no permitidos: {0}
 OAR033.error-header-required=La cabecera ''{0}'' debe ser obligatoria
 OAR035.error=El código de respuesta {0} debe estar definido cuando la operación tiene esquemas de seguridad definidos
diff --git a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/examples/OAR031.html b/src/main/resources/org/sonar/l10n/openapi/rules/openapi/examples/OAR031.html
index c20f54bc..7a862915 100644
--- a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/examples/OAR031.html
+++ b/src/main/resources/org/sonar/l10n/openapi/rules/openapi/examples/OAR031.html
@@ -1,6 +1,6 @@
 

The examples can help developers to understand the response data structure and representation.

Examples are validated as four independent levels: response, request body, parameter and property. The response, request-body and parameter levels require an example declared at the media-type or schema root; examples nested inside individual properties do not satisfy them. 204 responses are excluded.

-

Each level can be enabled or disabled independently with the rule parameters validate-response, validate-request-body, validate-parameter and validate-property (all enabled by default).

+

Each level can be enabled or disabled independently with the rule parameters validateResponse, validateRequestBody, validateParameter and validateProperty (all enabled by default).

Noncompliant Code Example (OpenAPI 2)

 swagger: "2.0"
@@ -87,7 +87,7 @@ 

Noncompliant Code Example (OpenAPI 3)

/pets: get: responses: - 206: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + 206: # Noncompliant {{OAR031: Response must have an example defined}} description: Pet list content: application/json: @@ -98,14 +98,14 @@

Noncompliant Code Example (OpenAPI 3)

pet: type: object properties: - name: # Noncompliant {{OAR031: Properties must have an example defined}} + name: # Noncompliant {{OAR031: Property 'name' is missing an example.}} type: string - type: # Noncompliant {{OAR031: Properties must have an example defined}} + type: # Noncompliant {{OAR031: Property 'type' is missing an example.}} type: string pets: type: object properties: - size: # Noncompliant {{OAR031: Properties must have an example defined}} + size: # Noncompliant {{OAR031: Property 'size' is missing an example.}} type: integer pets: type: array diff --git a/src/test/java/apiaddicts/sonar/openapi/checks/examples/OAR031ExamplesCheckTest.java b/src/test/java/apiaddicts/sonar/openapi/checks/examples/OAR031ExamplesCheckTest.java index 4f7f624d..667c257a 100644 --- a/src/test/java/apiaddicts/sonar/openapi/checks/examples/OAR031ExamplesCheckTest.java +++ b/src/test/java/apiaddicts/sonar/openapi/checks/examples/OAR031ExamplesCheckTest.java @@ -95,6 +95,16 @@ public void verifyInV32NestedProperties() { public void verifyInV2AllOfSchema() { verifyV2("allof-schema"); } + + @Test + public void verifyInV2AllOfSchemaMissingExample() { + verifyV2("allof-schema-missing-example.yaml"); + } + + @Test + public void verifyInV2OrphanSchema() { + verifyV2("orphan-schema.yaml"); + } @Test public void verifyInV3AllOfSchema() { verifyV3("allof-schema"); @@ -108,6 +118,32 @@ public void verifyInV32AllOfSchema() { verifyV32("allof-schema"); } + @Test + public void verifyInV3AllOfSchemaMissingExample() { + verifyV3("allof-schema-missing-example.yaml"); + } + @Test + public void verifyInV31AllOfSchemaMissingExample() { + verifyV31("allof-schema-missing-example.yaml"); + } + @Test + public void verifyInV32AllOfSchemaMissingExample() { + verifyV32("allof-schema-missing-example.yaml"); + } + + @Test + public void verifyInV3OrphanSchema() { + verifyV3("orphan-schema.yaml"); + } + @Test + public void verifyInV31OrphanSchema() { + verifyV31("orphan-schema.yaml"); + } + @Test + public void verifyInV32OrphanSchema() { + verifyV32("orphan-schema.yaml"); + } + @Override public void verifyRule() { assertRuleProperties("OAR031 - Examples - Responses, Request Body, Parameters and Properties must have an example defined", RuleType.BUG, Severity.MAJOR, tags("examples")); diff --git a/src/test/java/apiaddicts/sonar/openapi/checks/parameters/OAR026TotalParameterDefaultValueCheckTest.java b/src/test/java/apiaddicts/sonar/openapi/checks/parameters/OAR026TotalParameterDefaultValueCheckTest.java index c1c619a2..155db84d 100644 --- a/src/test/java/apiaddicts/sonar/openapi/checks/parameters/OAR026TotalParameterDefaultValueCheckTest.java +++ b/src/test/java/apiaddicts/sonar/openapi/checks/parameters/OAR026TotalParameterDefaultValueCheckTest.java @@ -63,6 +63,21 @@ public void verifyInV2WithoutParameters() { verifyV2("without-parameters"); } + @Test + public void verifyInV2PostOperationWith$total() { + verifyV2("post-with-$total-with-defval-true"); + } + + @Test + public void verifyInV2HeaderParamWith$total() { + verifyV2("header-with-$total-with-defval-true"); + } + + @Test + public void verifyInV2With$refUnreferencedWith$total() { + verifyV2("with-$ref-unreferenced-with-$total-with-defval-true"); + } + @Test public void verifyInV3With$totalWithDefvalFalse() { verifyV3("plain-with-$total-with-defval-false"); @@ -107,15 +122,142 @@ public void verifyInV2WithoutParameters() { public void verifyInV3WithoutParameters() { verifyV3("without-parameters"); } + + @Test + public void verifyInV3PostOperationWith$total() { + verifyV3("post-with-$total-with-defval-true"); + } + + @Test + public void verifyInV3HeaderParamWith$total() { + verifyV3("header-with-$total-with-defval-true"); + } + + @Test + public void verifyInV3With$refUnreferencedWith$total() { + verifyV3("with-$ref-unreferenced-with-$total-with-defval-true"); + } + + @Test + public void verifyInV31With$totalWithDefvalFalse() { + verifyV31("plain-with-$total-with-defval-false"); + } + + @Test + public void verifyInV31With$totalWithDefvalTrue() { + verifyV31("plain-with-$total-with-defval-true"); + } + + @Test + public void verifyInV31With$totalWithoutDefval() { + verifyV31("plain-with-$total-without-defval"); + } + + @Test + public void verifyInV31Without$total() { + verifyV31("plain-without-$total"); + } + + @Test + public void verifyInV31With$refWith$totalWithDefvalFalse() { + verifyV31("with-$ref-with-$total-with-defval-false"); + } + + @Test + public void verifyInV31With$refWith$totalWithDefvalTrue() { + verifyV31("with-$ref-with-$total-with-defval-true"); + } + + @Test + public void verifyInV31With$refWith$totalWithoutDefval() { + verifyV31("with-$ref-with-$total-without-defval"); + } + + @Test + public void verifyInV31With$refWithout$total() { + verifyV31("with-$ref-without-$total"); + } + @Test public void verifyInV31WithoutParameters() { verifyV31("without-parameters"); } + + @Test + public void verifyInV31PostOperationWith$total() { + verifyV31("post-with-$total-with-defval-true"); + } + + @Test + public void verifyInV31HeaderParamWith$total() { + verifyV31("header-with-$total-with-defval-true"); + } + + @Test + public void verifyInV31With$refUnreferencedWith$total() { + verifyV31("with-$ref-unreferenced-with-$total-with-defval-true"); + } + + @Test + public void verifyInV32With$totalWithDefvalFalse() { + verifyV32("plain-with-$total-with-defval-false"); + } + + @Test + public void verifyInV32With$totalWithDefvalTrue() { + verifyV32("plain-with-$total-with-defval-true"); + } + + @Test + public void verifyInV32With$totalWithoutDefval() { + verifyV32("plain-with-$total-without-defval"); + } + + @Test + public void verifyInV32Without$total() { + verifyV32("plain-without-$total"); + } + + @Test + public void verifyInV32With$refWith$totalWithDefvalFalse() { + verifyV32("with-$ref-with-$total-with-defval-false"); + } + + @Test + public void verifyInV32With$refWith$totalWithDefvalTrue() { + verifyV32("with-$ref-with-$total-with-defval-true"); + } + + @Test + public void verifyInV32With$refWith$totalWithoutDefval() { + verifyV32("with-$ref-with-$total-without-defval"); + } + + @Test + public void verifyInV32With$refWithout$total() { + verifyV32("with-$ref-without-$total"); + } + @Test public void verifyInV32WithoutParameters() { verifyV32("without-parameters"); } + @Test + public void verifyInV32PostOperationWith$total() { + verifyV32("post-with-$total-with-defval-true"); + } + + @Test + public void verifyInV32HeaderParamWith$total() { + verifyV32("header-with-$total-with-defval-true"); + } + + @Test + public void verifyInV32With$refUnreferencedWith$total() { + verifyV32("with-$ref-unreferenced-with-$total-with-defval-true"); + } + @Override public void verifyRule() { assertRuleProperties("OAR026 - TotalParameterDefaultValue - The $total parameter default value should be false", RuleType.BUG, Severity.CRITICAL, tags("parameters")); diff --git a/src/test/resources/checks/v2/examples/OAR031/allof-schema-missing-example.yaml b/src/test/resources/checks/v2/examples/OAR031/allof-schema-missing-example.yaml new file mode 100644 index 00000000..fbf92f9a --- /dev/null +++ b/src/test/resources/checks/v2/examples/OAR031/allof-schema-missing-example.yaml @@ -0,0 +1,28 @@ +swagger: "2.0" +info: + version: 1.0.0 + title: Swagger Petstore +definitions: + BaseEntity: + type: object + properties: + id: # Noncompliant {{OAR031: Property 'id' is missing an example.}} + type: integer + Pet: + allOf: + - $ref: '#/definitions/BaseEntity' + properties: + name: + type: string + example: "Fluffy" +paths: + /pets: + get: + responses: + 200: + description: Ok + schema: + $ref: '#/definitions/Pet' + examples: + application/json: + name: Fluffy diff --git a/src/test/resources/checks/v2/examples/OAR031/externalref.yaml b/src/test/resources/checks/v2/examples/OAR031/externalref.yaml index 18b488c1..102e8d94 100644 --- a/src/test/resources/checks/v2/examples/OAR031/externalref.yaml +++ b/src/test/resources/checks/v2/examples/OAR031/externalref.yaml @@ -10,14 +10,14 @@ paths: /users: get: responses: - 200: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + 200: # Noncompliant {{OAR031: Response must have an example defined}} description: OK schema: type: array items: $ref: '#/definitions/User' 400: - $ref: >- # Noncompliant {{OAR031: Responses must have one or more examples defined}} + $ref: >- # Noncompliant {{OAR031: Response must have an example defined}} http://localhost:18089/OAR031.yaml#/components/responses/server_error_response /users/{userId}: get: @@ -27,7 +27,7 @@ paths: required: true type: string responses: - 200: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + 200: # Noncompliant {{OAR031: Response must have an example defined}} description: A single user schema: $ref: '#/definitions/User' @@ -41,8 +41,10 @@ definitions: name: type: string example: "John" + # `Error` is intentionally never referenced by any path: it exercises the + # orphan-schema exclusion (property-level checks only cover reachable schemas). Error: type: object properties: - message: # Noncompliant {{OAR031: Properties must have an example defined}} + message: type: string \ No newline at end of file diff --git a/src/test/resources/checks/v2/examples/OAR031/nested-properties-examples.yaml b/src/test/resources/checks/v2/examples/OAR031/nested-properties-examples.yaml index 6b0b4816..defbd10c 100644 --- a/src/test/resources/checks/v2/examples/OAR031/nested-properties-examples.yaml +++ b/src/test/resources/checks/v2/examples/OAR031/nested-properties-examples.yaml @@ -6,7 +6,7 @@ paths: /profile: put: parameters: - - name: body # Noncompliant {{OAR031: Parameters must have one or more examples defined}} + - name: body # Noncompliant {{OAR031: Parameter 'body' must have an example defined}} in: body required: true schema: @@ -34,5 +34,5 @@ paths: type: string example: "28001" responses: - 200: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + 200: # Noncompliant {{OAR031: Response must have an example defined}} description: OK \ No newline at end of file diff --git a/src/test/resources/checks/v2/examples/OAR031/orphan-schema.yaml b/src/test/resources/checks/v2/examples/OAR031/orphan-schema.yaml new file mode 100644 index 00000000..f4f1f1dd --- /dev/null +++ b/src/test/resources/checks/v2/examples/OAR031/orphan-schema.yaml @@ -0,0 +1,28 @@ +swagger: "2.0" +info: + version: 1.0.0 + title: Swagger Petstore +paths: + /pets: + get: + responses: + 200: + description: Ok + schema: + $ref: '#/definitions/pet' + examples: + application/json: + name: Fluffy +definitions: + pet: + type: object + properties: + name: + type: string + example: "Fluffy" + # Never referenced by any path - must not be flagged (orphan-schema exclusion). + UnusedSchema: + type: object + properties: + unused_field: + type: string diff --git a/src/test/resources/checks/v2/examples/OAR031/valid.json b/src/test/resources/checks/v2/examples/OAR031/valid.json index ae8000e6..ed1ab2da 100644 --- a/src/test/resources/checks/v2/examples/OAR031/valid.json +++ b/src/test/resources/checks/v2/examples/OAR031/valid.json @@ -84,7 +84,7 @@ } }, "responses" : { - "server_error_response" : { # Noncompliant {{OAR031: Responses must have one or more examples defined}} + "server_error_response" : { # Noncompliant {{OAR031: Response must have an example defined}} "description" : "Default error response", "schema" : { "type" : "object", diff --git a/src/test/resources/checks/v2/examples/OAR031/without-examples.json b/src/test/resources/checks/v2/examples/OAR031/without-examples.json index 4e6beec9..c38288bd 100644 --- a/src/test/resources/checks/v2/examples/OAR031/without-examples.json +++ b/src/test/resources/checks/v2/examples/OAR031/without-examples.json @@ -11,7 +11,7 @@ "204": { "description": "No content" }, - "206" : { # Noncompliant {{OAR031: Responses must have one or more examples defined}} + "206" : { # Noncompliant {{OAR031: Response must have an example defined}} "description" : "Pet list", "schema" : { "$ref" : "#/definitions/pets" @@ -29,7 +29,7 @@ "$ref" : "#/parameters/id" } ], "responses" : { - "200" : { # Noncompliant {{OAR031: Responses must have one or more examples defined}} + "200" : { # Noncompliant {{OAR031: Response must have an example defined}} "description" : "One pet", "schema" : { "$ref" : "#/definitions/pet" @@ -57,10 +57,10 @@ "pet" : { "type" : "object", "properties" : { - "name" : { # Noncompliant {{OAR031: Properties must have an example defined}} + "name" : { # Noncompliant {{OAR031: Property 'name' is missing an example.}} "type" : "string" }, - "type" : { # Noncompliant {{OAR031: Properties must have an example defined}} + "type" : { # Noncompliant {{OAR031: Property 'type' is missing an example.}} "type" : "string" } } @@ -68,7 +68,7 @@ "pets" : { "type" : "object", "properties" : { - "size" : { # Noncompliant {{OAR031: Properties must have an example defined}} + "size" : { # Noncompliant {{OAR031: Property 'size' is missing an example.}} "type" : "integer" }, "pets" : { @@ -81,12 +81,12 @@ } }, "responses" : { - "server_error_response" : { # Noncompliant {{OAR031: Responses must have one or more examples defined}} + "server_error_response" : { # Noncompliant {{OAR031: Response must have an example defined}} "description" : "Default error response", "schema" : { "type" : "object", "properties" : { - "error" : { # Noncompliant {{OAR031: Properties must have an example defined}} + "error" : { # Noncompliant {{OAR031: Property 'error' is missing an example.}} "type" : "string" } } diff --git a/src/test/resources/checks/v2/examples/OAR031/without-examples.yaml b/src/test/resources/checks/v2/examples/OAR031/without-examples.yaml index cfb67cc7..8f2e2edf 100644 --- a/src/test/resources/checks/v2/examples/OAR031/without-examples.yaml +++ b/src/test/resources/checks/v2/examples/OAR031/without-examples.yaml @@ -8,7 +8,7 @@ paths: responses: 204: description: No content - 206: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + 206: # Noncompliant {{OAR031: Response must have an example defined}} description: Pet list schema: $ref: '#/definitions/pets' @@ -19,7 +19,7 @@ paths: parameters: - $ref: "#/parameters/id" responses: - 200: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + 200: # Noncompliant {{OAR031: Response must have an example defined}} description: One pet schema: $ref: "#/definitions/pet" @@ -39,24 +39,24 @@ definitions: pet: type: object properties: - name: # Noncompliant {{OAR031: Properties must have an example defined}} + name: # Noncompliant {{OAR031: Property 'name' is missing an example.}} type: string - type: # Noncompliant {{OAR031: Properties must have an example defined}} + type: # Noncompliant {{OAR031: Property 'type' is missing an example.}} type: string pets: type: object properties: - size: # Noncompliant {{OAR031: Properties must have an example defined}} + size: # Noncompliant {{OAR031: Property 'size' is missing an example.}} type: integer pets: type: array items: $ref: '#/definitions/pet' responses: - server_error_response: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + server_error_response: # Noncompliant {{OAR031: Response must have an example defined}} description: Default error response schema: type: object properties: - error: # Noncompliant {{OAR031: Properties must have an example defined}} + error: # Noncompliant {{OAR031: Property 'error' is missing an example.}} type: string \ No newline at end of file diff --git a/src/test/resources/checks/v2/parameters/OAR026/header-with-$total-with-defval-true.json b/src/test/resources/checks/v2/parameters/OAR026/header-with-$total-with-defval-true.json new file mode 100644 index 00000000..c8e9d445 --- /dev/null +++ b/src/test/resources/checks/v2/parameters/OAR026/header-with-$total-with-defval-true.json @@ -0,0 +1,24 @@ +{ + "swagger" : "2.0", + "info" : { + "version" : "1.0.0", + "title" : "Swagger Petstore" + }, + "paths" : { + "/pets" : { + "get" : { + "parameters" : [ { + "in" : "header", + "name" : "$total", + "type" : "boolean", + "default" : true + } ], + "responses" : { + "206" : { + "description" : "Ok" + } + } + } + } + } +} diff --git a/src/test/resources/checks/v2/parameters/OAR026/header-with-$total-with-defval-true.yaml b/src/test/resources/checks/v2/parameters/OAR026/header-with-$total-with-defval-true.yaml new file mode 100644 index 00000000..6a2b4dfd --- /dev/null +++ b/src/test/resources/checks/v2/parameters/OAR026/header-with-$total-with-defval-true.yaml @@ -0,0 +1,15 @@ +swagger: "2.0" +info: + version: 1.0.0 + title: Swagger Petstore +paths: + /pets: + get: + parameters: + - in: header + name: $total + type: boolean + default: true + responses: + 206: + description: Ok diff --git a/src/test/resources/checks/v2/parameters/OAR026/plain-with-$total-without-defval.json b/src/test/resources/checks/v2/parameters/OAR026/plain-with-$total-without-defval.json index 75b84003..1eae98e3 100644 --- a/src/test/resources/checks/v2/parameters/OAR026/plain-with-$total-without-defval.json +++ b/src/test/resources/checks/v2/parameters/OAR026/plain-with-$total-without-defval.json @@ -14,7 +14,7 @@ "items" : { "type" : "string" } - }, { # Noncompliant {{OAR026: The $total parameter default value should be false}} + }, { "in" : "query", "name" : "$total", "type" : "boolean" diff --git a/src/test/resources/checks/v2/parameters/OAR026/plain-with-$total-without-defval.yaml b/src/test/resources/checks/v2/parameters/OAR026/plain-with-$total-without-defval.yaml index b3f78a09..8c52f6e3 100644 --- a/src/test/resources/checks/v2/parameters/OAR026/plain-with-$total-without-defval.yaml +++ b/src/test/resources/checks/v2/parameters/OAR026/plain-with-$total-without-defval.yaml @@ -11,7 +11,7 @@ paths: type: array items: type: string - - in: query # Noncompliant {{OAR026: The $total parameter default value should be false}} + - in: query name: $total type: boolean responses: diff --git a/src/test/resources/checks/v2/parameters/OAR026/post-with-$total-with-defval-true.json b/src/test/resources/checks/v2/parameters/OAR026/post-with-$total-with-defval-true.json new file mode 100644 index 00000000..83837ae9 --- /dev/null +++ b/src/test/resources/checks/v2/parameters/OAR026/post-with-$total-with-defval-true.json @@ -0,0 +1,24 @@ +{ + "swagger" : "2.0", + "info" : { + "version" : "1.0.0", + "title" : "Swagger Petstore" + }, + "paths" : { + "/pets" : { + "post" : { + "parameters" : [ { + "in" : "query", + "name" : "$total", + "type" : "boolean", + "default" : true + } ], + "responses" : { + "201" : { + "description" : "Created" + } + } + } + } + } +} diff --git a/src/test/resources/checks/v2/parameters/OAR026/post-with-$total-with-defval-true.yaml b/src/test/resources/checks/v2/parameters/OAR026/post-with-$total-with-defval-true.yaml new file mode 100644 index 00000000..ee010c1e --- /dev/null +++ b/src/test/resources/checks/v2/parameters/OAR026/post-with-$total-with-defval-true.yaml @@ -0,0 +1,15 @@ +swagger: "2.0" +info: + version: 1.0.0 + title: Swagger Petstore +paths: + /pets: + post: + parameters: + - in: query + name: $total + type: boolean + default: true + responses: + 201: + description: Created diff --git a/src/test/resources/checks/v2/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json b/src/test/resources/checks/v2/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json new file mode 100644 index 00000000..45ec80db --- /dev/null +++ b/src/test/resources/checks/v2/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json @@ -0,0 +1,26 @@ +{ + "swagger" : "2.0", + "info" : { + "version" : "1.0.0", + "title" : "Swagger Petstore" + }, + "parameters" : { + "total" : { + "in" : "query", + "name" : "$total", + "type" : "boolean", + "default" : true + } + }, + "paths" : { + "/pets" : { + "get" : { + "responses" : { + "206" : { + "description" : "Ok" + } + } + } + } + } +} diff --git a/src/test/resources/checks/v2/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml b/src/test/resources/checks/v2/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml new file mode 100644 index 00000000..5de71af2 --- /dev/null +++ b/src/test/resources/checks/v2/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml @@ -0,0 +1,16 @@ +swagger: "2.0" +info: + version: 1.0.0 + title: Swagger Petstore +parameters: + total: + in: query + name: $total + type: boolean + default: true +paths: + /pets: + get: + responses: + 206: + description: Ok diff --git a/src/test/resources/checks/v2/parameters/OAR026/with-$ref-with-$total-without-defval.json b/src/test/resources/checks/v2/parameters/OAR026/with-$ref-with-$total-without-defval.json index 7c43ee1c..52632ee9 100644 --- a/src/test/resources/checks/v2/parameters/OAR026/with-$ref-with-$total-without-defval.json +++ b/src/test/resources/checks/v2/parameters/OAR026/with-$ref-with-$total-without-defval.json @@ -13,7 +13,7 @@ "type" : "string" } }, - "total" : { # Noncompliant {{OAR026: The $total parameter default value should be false}} + "total" : { "in" : "query", "name" : "$total", "type" : "boolean" diff --git a/src/test/resources/checks/v2/parameters/OAR026/with-$ref-with-$total-without-defval.yaml b/src/test/resources/checks/v2/parameters/OAR026/with-$ref-with-$total-without-defval.yaml index 9c6b56e2..663e7277 100644 --- a/src/test/resources/checks/v2/parameters/OAR026/with-$ref-with-$total-without-defval.yaml +++ b/src/test/resources/checks/v2/parameters/OAR026/with-$ref-with-$total-without-defval.yaml @@ -9,7 +9,7 @@ parameters: type: array items: type: string - total: # Noncompliant {{OAR026: The $total parameter default value should be false}} + total: in: query name: $total type: boolean diff --git a/src/test/resources/checks/v3/examples/OAR031/allof-schema-missing-example.yaml b/src/test/resources/checks/v3/examples/OAR031/allof-schema-missing-example.yaml new file mode 100644 index 00000000..9080133a --- /dev/null +++ b/src/test/resources/checks/v3/examples/OAR031/allof-schema-missing-example.yaml @@ -0,0 +1,32 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Swagger Petstore +components: + schemas: + BaseEntity: + type: object + properties: + id: # Noncompliant {{OAR031: Property 'id' is missing an example.}} + type: integer + Pet: + allOf: + - $ref: '#/components/schemas/BaseEntity' + properties: + name: + type: string + example: "Fluffy" +paths: + /pets: + get: + responses: + 200: + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + example: + name: Fluffy + 204: + description: No content diff --git a/src/test/resources/checks/v3/examples/OAR031/externalref.yaml b/src/test/resources/checks/v3/examples/OAR031/externalref.yaml index e747a397..24da3812 100644 --- a/src/test/resources/checks/v3/examples/OAR031/externalref.yaml +++ b/src/test/resources/checks/v3/examples/OAR031/externalref.yaml @@ -14,7 +14,7 @@ paths: summary: Get all users description: Returns a list of users. responses: - '200': # Noncompliant {{OAR031: Responses must have one or more examples defined}} + '200': # Noncompliant {{OAR031: Response must have an example defined}} description: A JSON array of user objects content: application/json: @@ -23,7 +23,7 @@ paths: items: $ref: '#/components/schemas/User' '400': - $ref: >- # Noncompliant {{OAR031: Responses must have one or more examples defined}} + $ref: >- # Noncompliant {{OAR031: Response must have an example defined}} http://localhost:18089/OAR031.yaml#/components/responses/server_error_response /users/{userId}: get: @@ -40,14 +40,14 @@ paths: name: Puppy type: dog responses: - '200': # Noncompliant {{OAR031: Responses must have one or more examples defined}} + '200': # Noncompliant {{OAR031: Response must have an example defined}} description: A single user object content: application/json: schema: $ref: '#/components/schemas/User' '400': - $ref: >- # Noncompliant {{OAR031: Responses must have one or more examples defined}} + $ref: >- # Noncompliant {{OAR031: Response must have an example defined}} http://localhost:18089/OAR031.yaml#/components/responses/server_error_response components: schemas: diff --git a/src/test/resources/checks/v3/examples/OAR031/nested-properties-examples.yaml b/src/test/resources/checks/v3/examples/OAR031/nested-properties-examples.yaml index 9a67dda1..0f027b25 100644 --- a/src/test/resources/checks/v3/examples/OAR031/nested-properties-examples.yaml +++ b/src/test/resources/checks/v3/examples/OAR031/nested-properties-examples.yaml @@ -6,7 +6,7 @@ paths: /profile: put: summary: Update user profile - requestBody: # Noncompliant {{OAR031: Request body must have one or more examples defined}} + requestBody: # Noncompliant {{OAR031: Request body must have an example defined}} required: true content: application/json: @@ -35,5 +35,5 @@ paths: type: string example: "28001" responses: - '200': # Noncompliant {{OAR031: Responses must have one or more examples defined}} + '200': # Noncompliant {{OAR031: Response must have an example defined}} description: OK \ No newline at end of file diff --git a/src/test/resources/checks/v3/examples/OAR031/orphan-schema.yaml b/src/test/resources/checks/v3/examples/OAR031/orphan-schema.yaml new file mode 100644 index 00000000..9ed22c0d --- /dev/null +++ b/src/test/resources/checks/v3/examples/OAR031/orphan-schema.yaml @@ -0,0 +1,32 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Swagger Petstore +paths: + /pets: + get: + responses: + 200: + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/pet' + example: + name: Fluffy + 204: + description: No content +components: + schemas: + pet: + type: object + properties: + name: + type: string + example: "Fluffy" + # Never referenced by any path - must not be flagged (orphan-schema exclusion). + UnusedSchema: + type: object + properties: + unused_field: + type: string diff --git a/src/test/resources/checks/v3/examples/OAR031/without-examples.yaml b/src/test/resources/checks/v3/examples/OAR031/without-examples.yaml index ec8cd2a0..eec0c9a7 100644 --- a/src/test/resources/checks/v3/examples/OAR031/without-examples.yaml +++ b/src/test/resources/checks/v3/examples/OAR031/without-examples.yaml @@ -6,7 +6,7 @@ paths: /pets: get: responses: - 206: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + 206: # Noncompliant {{OAR031: Response must have an example defined}} description: Pet list content: application/json: @@ -16,7 +16,7 @@ paths: $ref: "#/components/responses/server_error_response" /pets/{id}: parameters: - - in: query # Noncompliant {{OAR031: Parameters must have one or more examples defined}} + - in: query # Noncompliant {{OAR031: Parameter '$start' must have an example defined}} name: $start schema: type: integer @@ -24,7 +24,7 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: - 200: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + 200: # Noncompliant {{OAR031: Response must have an example defined}} description: One pet content: application/json: @@ -35,8 +35,8 @@ paths: components: parameters: - id: - in: path # Noncompliant {{OAR031: Parameters must have one or more examples defined}} + id: # Noncompliant {{OAR031: Parameter 'id' must have an example defined}} + in: path name: id schema: type: integer @@ -48,26 +48,26 @@ components: pet: type: object properties: - name: # Noncompliant {{OAR031: Properties must have an example defined}} + name: # Noncompliant {{OAR031: Property 'name' is missing an example.}} type: string - type: # Noncompliant {{OAR031: Properties must have an example defined}} + type: # Noncompliant {{OAR031: Property 'type' is missing an example.}} type: string pets: type: object properties: - size: # Noncompliant {{OAR031: Properties must have an example defined}} + size: # Noncompliant {{OAR031: Property 'size' is missing an example.}} type: integer pets: type: array items: $ref: '#/components/schemas/pet' responses: - server_error_response: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + server_error_response: # Noncompliant {{OAR031: Response must have an example defined}} description: Default error response content: application/json: schema: type: object properties: - error: # Noncompliant {{OAR031: Properties must have an example defined}} + error: # Noncompliant {{OAR031: Property 'error' is missing an example.}} type: string \ No newline at end of file diff --git a/src/test/resources/checks/v3/parameters/OAR026/header-with-$total-with-defval-true.json b/src/test/resources/checks/v3/parameters/OAR026/header-with-$total-with-defval-true.json new file mode 100644 index 00000000..5387f7ac --- /dev/null +++ b/src/test/resources/checks/v3/parameters/OAR026/header-with-$total-with-defval-true.json @@ -0,0 +1,26 @@ +{ + "openapi" : "3.0.0", + "info" : { + "version" : "1.0.0", + "title" : "Swagger Petstore" + }, + "paths" : { + "/pets" : { + "get" : { + "parameters" : [ { + "in" : "header", + "name" : "$total", + "schema" : { + "type" : "boolean", + "default" : true + } + } ], + "responses" : { + "206" : { + "description" : "Ok" + } + } + } + } + } +} diff --git a/src/test/resources/checks/v3/parameters/OAR026/header-with-$total-with-defval-true.yaml b/src/test/resources/checks/v3/parameters/OAR026/header-with-$total-with-defval-true.yaml new file mode 100644 index 00000000..e3a6097e --- /dev/null +++ b/src/test/resources/checks/v3/parameters/OAR026/header-with-$total-with-defval-true.yaml @@ -0,0 +1,16 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Swagger Petstore +paths: + /pets: + get: + parameters: + - in: header + name: $total + schema: + type: boolean + default: true + responses: + 206: + description: Ok diff --git a/src/test/resources/checks/v3/parameters/OAR026/plain-with-$total-without-defval.json b/src/test/resources/checks/v3/parameters/OAR026/plain-with-$total-without-defval.json index d756597f..46579305 100644 --- a/src/test/resources/checks/v3/parameters/OAR026/plain-with-$total-without-defval.json +++ b/src/test/resources/checks/v3/parameters/OAR026/plain-with-$total-without-defval.json @@ -16,7 +16,7 @@ "type" : "string" } } - }, { # Noncompliant {{OAR026: The $total parameter default value should be false}} + }, { "in" : "query", "name" : "$total", "schema": { diff --git a/src/test/resources/checks/v3/parameters/OAR026/plain-with-$total-without-defval.yaml b/src/test/resources/checks/v3/parameters/OAR026/plain-with-$total-without-defval.yaml index c2580dc0..c9eb7ad3 100644 --- a/src/test/resources/checks/v3/parameters/OAR026/plain-with-$total-without-defval.yaml +++ b/src/test/resources/checks/v3/parameters/OAR026/plain-with-$total-without-defval.yaml @@ -12,7 +12,7 @@ paths: type: array items: type: string - - in: query # Noncompliant {{OAR026: The $total parameter default value should be false}} + - in: query name: $total schema: type: boolean diff --git a/src/test/resources/checks/v3/parameters/OAR026/post-with-$total-with-defval-true.json b/src/test/resources/checks/v3/parameters/OAR026/post-with-$total-with-defval-true.json new file mode 100644 index 00000000..8366d62e --- /dev/null +++ b/src/test/resources/checks/v3/parameters/OAR026/post-with-$total-with-defval-true.json @@ -0,0 +1,26 @@ +{ + "openapi" : "3.0.0", + "info" : { + "version" : "1.0.0", + "title" : "Swagger Petstore" + }, + "paths" : { + "/pets" : { + "post" : { + "parameters" : [ { + "in" : "query", + "name" : "$total", + "schema" : { + "type" : "boolean", + "default" : true + } + } ], + "responses" : { + "201" : { + "description" : "Created" + } + } + } + } + } +} diff --git a/src/test/resources/checks/v3/parameters/OAR026/post-with-$total-with-defval-true.yaml b/src/test/resources/checks/v3/parameters/OAR026/post-with-$total-with-defval-true.yaml new file mode 100644 index 00000000..b1de7fb3 --- /dev/null +++ b/src/test/resources/checks/v3/parameters/OAR026/post-with-$total-with-defval-true.yaml @@ -0,0 +1,16 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Swagger Petstore +paths: + /pets: + post: + parameters: + - in: query + name: $total + schema: + type: boolean + default: true + responses: + 201: + description: Created diff --git a/src/test/resources/checks/v3/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json b/src/test/resources/checks/v3/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json new file mode 100644 index 00000000..7fd799f0 --- /dev/null +++ b/src/test/resources/checks/v3/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json @@ -0,0 +1,30 @@ +{ + "openapi" : "3.0.0", + "info" : { + "version" : "1.0.0", + "title" : "Swagger Petstore" + }, + "components" : { + "parameters" : { + "total" : { + "in" : "query", + "name" : "$total", + "schema" : { + "type" : "boolean", + "default" : true + } + } + } + }, + "paths" : { + "/pets" : { + "get" : { + "responses" : { + "206" : { + "description" : "Ok" + } + } + } + } + } +} diff --git a/src/test/resources/checks/v3/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml b/src/test/resources/checks/v3/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml new file mode 100644 index 00000000..ad5a0bbe --- /dev/null +++ b/src/test/resources/checks/v3/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml @@ -0,0 +1,18 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Swagger Petstore +components: + parameters: + total: + in: query + name: $total + schema: + type: boolean + default: true +paths: + /pets: + get: + responses: + 206: + description: Ok diff --git a/src/test/resources/checks/v3/parameters/OAR026/with-$ref-with-$total-without-defval.json b/src/test/resources/checks/v3/parameters/OAR026/with-$ref-with-$total-without-defval.json index 9c5ef562..dc7533fc 100644 --- a/src/test/resources/checks/v3/parameters/OAR026/with-$ref-with-$total-without-defval.json +++ b/src/test/resources/checks/v3/parameters/OAR026/with-$ref-with-$total-without-defval.json @@ -16,7 +16,7 @@ } } }, - "total" : { # Noncompliant {{OAR026: The $total parameter default value should be false}} + "total" : { "in" : "query", "name" : "$total", "schema": { diff --git a/src/test/resources/checks/v3/parameters/OAR026/with-$ref-with-$total-without-defval.yaml b/src/test/resources/checks/v3/parameters/OAR026/with-$ref-with-$total-without-defval.yaml index 68f5a74b..702bb880 100644 --- a/src/test/resources/checks/v3/parameters/OAR026/with-$ref-with-$total-without-defval.yaml +++ b/src/test/resources/checks/v3/parameters/OAR026/with-$ref-with-$total-without-defval.yaml @@ -11,7 +11,7 @@ components: type: array items: type: string - total: # Noncompliant {{OAR026: The $total parameter default value should be false}} + total: in: query name: $total schema: diff --git a/src/test/resources/checks/v31/examples/OAR031/allof-schema-missing-example.yaml b/src/test/resources/checks/v31/examples/OAR031/allof-schema-missing-example.yaml new file mode 100644 index 00000000..5705e186 --- /dev/null +++ b/src/test/resources/checks/v31/examples/OAR031/allof-schema-missing-example.yaml @@ -0,0 +1,32 @@ +openapi: "3.1.0" +info: + version: 1.0.0 + title: Swagger Petstore +components: + schemas: + BaseEntity: + type: object + properties: + id: # Noncompliant {{OAR031: Property 'id' is missing an example.}} + type: integer + Pet: + allOf: + - $ref: '#/components/schemas/BaseEntity' + properties: + name: + type: string + example: "Fluffy" +paths: + /pets: + get: + responses: + 200: + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + example: + name: Fluffy + 204: + description: No content diff --git a/src/test/resources/checks/v31/examples/OAR031/externalref.yaml b/src/test/resources/checks/v31/examples/OAR031/externalref.yaml index 4e6e96e7..4473d4db 100644 --- a/src/test/resources/checks/v31/examples/OAR031/externalref.yaml +++ b/src/test/resources/checks/v31/examples/OAR031/externalref.yaml @@ -14,7 +14,7 @@ paths: summary: Get all users description: Returns a list of users. responses: - '200': # Noncompliant {{OAR031: Responses must have one or more examples defined}} + '200': # Noncompliant {{OAR031: Response must have an example defined}} description: A JSON array of user objects content: application/json: @@ -23,7 +23,7 @@ paths: items: $ref: '#/components/schemas/User' '400': - $ref: >- # Noncompliant {{OAR031: Responses must have one or more examples defined}} + $ref: >- # Noncompliant {{OAR031: Response must have an example defined}} http://localhost:18089/OAR031.yaml#/components/responses/server_error_response /users/{userId}: get: @@ -40,14 +40,14 @@ paths: name: Puppy type: dog responses: - '200': # Noncompliant {{OAR031: Responses must have one or more examples defined}} + '200': # Noncompliant {{OAR031: Response must have an example defined}} description: A single user object content: application/json: schema: $ref: '#/components/schemas/User' '400': - $ref: >- # Noncompliant {{OAR031: Responses must have one or more examples defined}} + $ref: >- # Noncompliant {{OAR031: Response must have an example defined}} http://localhost:18089/OAR031.yaml#/components/responses/server_error_response components: schemas: diff --git a/src/test/resources/checks/v31/examples/OAR031/nested-properties-examples.yaml b/src/test/resources/checks/v31/examples/OAR031/nested-properties-examples.yaml index c48f0f18..86b9cc6b 100644 --- a/src/test/resources/checks/v31/examples/OAR031/nested-properties-examples.yaml +++ b/src/test/resources/checks/v31/examples/OAR031/nested-properties-examples.yaml @@ -6,7 +6,7 @@ paths: /profile: put: summary: Update user profile - requestBody: # Noncompliant {{OAR031: Request body must have one or more examples defined}} + requestBody: # Noncompliant {{OAR031: Request body must have an example defined}} required: true content: application/json: @@ -35,5 +35,5 @@ paths: type: string example: "28001" responses: - '200': # Noncompliant {{OAR031: Responses must have one or more examples defined}} + '200': # Noncompliant {{OAR031: Response must have an example defined}} description: OK \ No newline at end of file diff --git a/src/test/resources/checks/v31/examples/OAR031/orphan-schema.yaml b/src/test/resources/checks/v31/examples/OAR031/orphan-schema.yaml new file mode 100644 index 00000000..8e7784ca --- /dev/null +++ b/src/test/resources/checks/v31/examples/OAR031/orphan-schema.yaml @@ -0,0 +1,32 @@ +openapi: "3.1.0" +info: + version: 1.0.0 + title: Swagger Petstore +paths: + /pets: + get: + responses: + 200: + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/pet' + example: + name: Fluffy + 204: + description: No content +components: + schemas: + pet: + type: object + properties: + name: + type: string + example: "Fluffy" + # Never referenced by any path - must not be flagged (orphan-schema exclusion). + UnusedSchema: + type: object + properties: + unused_field: + type: string diff --git a/src/test/resources/checks/v31/examples/OAR031/without-examples.yaml b/src/test/resources/checks/v31/examples/OAR031/without-examples.yaml index 5fa170e9..42f0f6f9 100644 --- a/src/test/resources/checks/v31/examples/OAR031/without-examples.yaml +++ b/src/test/resources/checks/v31/examples/OAR031/without-examples.yaml @@ -6,7 +6,7 @@ paths: /pets: get: responses: - 206: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + 206: # Noncompliant {{OAR031: Response must have an example defined}} description: Pet list content: application/json: @@ -16,7 +16,7 @@ paths: $ref: "#/components/responses/server_error_response" /pets/{id}: parameters: - - in: query # Noncompliant {{OAR031: Parameters must have one or more examples defined}} + - in: query # Noncompliant {{OAR031: Parameter '$start' must have an example defined}} name: $start schema: type: integer @@ -24,7 +24,7 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: - 200: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + 200: # Noncompliant {{OAR031: Response must have an example defined}} description: One pet content: application/json: @@ -35,8 +35,8 @@ paths: components: parameters: - id: - in: path # Noncompliant {{OAR031: Parameters must have one or more examples defined}} + id: # Noncompliant {{OAR031: Parameter 'id' must have an example defined}} + in: path name: id schema: type: integer @@ -48,26 +48,26 @@ components: pet: type: object properties: - name: # Noncompliant {{OAR031: Properties must have an example defined}} + name: # Noncompliant {{OAR031: Property 'name' is missing an example.}} type: string - type: # Noncompliant {{OAR031: Properties must have an example defined}} + type: # Noncompliant {{OAR031: Property 'type' is missing an example.}} type: string pets: type: object properties: - size: # Noncompliant {{OAR031: Properties must have an example defined}} + size: # Noncompliant {{OAR031: Property 'size' is missing an example.}} type: integer pets: type: array items: $ref: '#/components/schemas/pet' responses: - server_error_response: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + server_error_response: # Noncompliant {{OAR031: Response must have an example defined}} description: Default error response content: application/json: schema: type: object properties: - error: # Noncompliant {{OAR031: Properties must have an example defined}} + error: # Noncompliant {{OAR031: Property 'error' is missing an example.}} type: string \ No newline at end of file diff --git a/src/test/resources/checks/v31/parameters/OAR026/header-with-$total-with-defval-true.json b/src/test/resources/checks/v31/parameters/OAR026/header-with-$total-with-defval-true.json new file mode 100644 index 00000000..940f0f1d --- /dev/null +++ b/src/test/resources/checks/v31/parameters/OAR026/header-with-$total-with-defval-true.json @@ -0,0 +1,26 @@ +{ + "openapi" : "3.1.0", + "info" : { + "version" : "1.0.0", + "title" : "Swagger Petstore" + }, + "paths" : { + "/pets" : { + "get" : { + "parameters" : [ { + "in" : "header", + "name" : "$total", + "schema" : { + "type" : "boolean", + "default" : true + } + } ], + "responses" : { + "206" : { + "description" : "Ok" + } + } + } + } + } +} diff --git a/src/test/resources/checks/v31/parameters/OAR026/header-with-$total-with-defval-true.yaml b/src/test/resources/checks/v31/parameters/OAR026/header-with-$total-with-defval-true.yaml new file mode 100644 index 00000000..7936548a --- /dev/null +++ b/src/test/resources/checks/v31/parameters/OAR026/header-with-$total-with-defval-true.yaml @@ -0,0 +1,16 @@ +openapi: "3.1.0" +info: + version: 1.0.0 + title: Swagger Petstore +paths: + /pets: + get: + parameters: + - in: header + name: $total + schema: + type: boolean + default: true + responses: + 206: + description: Ok diff --git a/src/test/resources/checks/v31/parameters/OAR026/plain-with-$total-without-defval.json b/src/test/resources/checks/v31/parameters/OAR026/plain-with-$total-without-defval.json index fe56facb..9278595e 100644 --- a/src/test/resources/checks/v31/parameters/OAR026/plain-with-$total-without-defval.json +++ b/src/test/resources/checks/v31/parameters/OAR026/plain-with-$total-without-defval.json @@ -16,7 +16,7 @@ "type" : "string" } } - }, { # Noncompliant {{OAR026: The $total parameter default value should be false}} + }, { "in" : "query", "name" : "$total", "schema": { diff --git a/src/test/resources/checks/v31/parameters/OAR026/plain-with-$total-without-defval.yaml b/src/test/resources/checks/v31/parameters/OAR026/plain-with-$total-without-defval.yaml index 76791b5a..d18a1745 100644 --- a/src/test/resources/checks/v31/parameters/OAR026/plain-with-$total-without-defval.yaml +++ b/src/test/resources/checks/v31/parameters/OAR026/plain-with-$total-without-defval.yaml @@ -12,7 +12,7 @@ paths: type: array items: type: string - - in: query # Noncompliant {{OAR026: The $total parameter default value should be false}} + - in: query name: $total schema: type: boolean diff --git a/src/test/resources/checks/v31/parameters/OAR026/post-with-$total-with-defval-true.json b/src/test/resources/checks/v31/parameters/OAR026/post-with-$total-with-defval-true.json new file mode 100644 index 00000000..418764a4 --- /dev/null +++ b/src/test/resources/checks/v31/parameters/OAR026/post-with-$total-with-defval-true.json @@ -0,0 +1,26 @@ +{ + "openapi" : "3.1.0", + "info" : { + "version" : "1.0.0", + "title" : "Swagger Petstore" + }, + "paths" : { + "/pets" : { + "post" : { + "parameters" : [ { + "in" : "query", + "name" : "$total", + "schema" : { + "type" : "boolean", + "default" : true + } + } ], + "responses" : { + "201" : { + "description" : "Created" + } + } + } + } + } +} diff --git a/src/test/resources/checks/v31/parameters/OAR026/post-with-$total-with-defval-true.yaml b/src/test/resources/checks/v31/parameters/OAR026/post-with-$total-with-defval-true.yaml new file mode 100644 index 00000000..9f7796c6 --- /dev/null +++ b/src/test/resources/checks/v31/parameters/OAR026/post-with-$total-with-defval-true.yaml @@ -0,0 +1,16 @@ +openapi: "3.1.0" +info: + version: 1.0.0 + title: Swagger Petstore +paths: + /pets: + post: + parameters: + - in: query + name: $total + schema: + type: boolean + default: true + responses: + 201: + description: Created diff --git a/src/test/resources/checks/v31/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json b/src/test/resources/checks/v31/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json new file mode 100644 index 00000000..8ba32f08 --- /dev/null +++ b/src/test/resources/checks/v31/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json @@ -0,0 +1,30 @@ +{ + "openapi" : "3.1.0", + "info" : { + "version" : "1.0.0", + "title" : "Swagger Petstore" + }, + "components" : { + "parameters" : { + "total" : { + "in" : "query", + "name" : "$total", + "schema" : { + "type" : "boolean", + "default" : true + } + } + } + }, + "paths" : { + "/pets" : { + "get" : { + "responses" : { + "206" : { + "description" : "Ok" + } + } + } + } + } +} diff --git a/src/test/resources/checks/v31/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml b/src/test/resources/checks/v31/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml new file mode 100644 index 00000000..595b9232 --- /dev/null +++ b/src/test/resources/checks/v31/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml @@ -0,0 +1,18 @@ +openapi: "3.1.0" +info: + version: 1.0.0 + title: Swagger Petstore +components: + parameters: + total: + in: query + name: $total + schema: + type: boolean + default: true +paths: + /pets: + get: + responses: + 206: + description: Ok diff --git a/src/test/resources/checks/v31/parameters/OAR026/with-$ref-with-$total-without-defval.json b/src/test/resources/checks/v31/parameters/OAR026/with-$ref-with-$total-without-defval.json index a550035d..bd00551f 100644 --- a/src/test/resources/checks/v31/parameters/OAR026/with-$ref-with-$total-without-defval.json +++ b/src/test/resources/checks/v31/parameters/OAR026/with-$ref-with-$total-without-defval.json @@ -16,7 +16,7 @@ } } }, - "total" : { # Noncompliant {{OAR026: The $total parameter default value should be false}} + "total" : { "in" : "query", "name" : "$total", "schema": { diff --git a/src/test/resources/checks/v31/parameters/OAR026/with-$ref-with-$total-without-defval.yaml b/src/test/resources/checks/v31/parameters/OAR026/with-$ref-with-$total-without-defval.yaml index a7888290..985a84f6 100644 --- a/src/test/resources/checks/v31/parameters/OAR026/with-$ref-with-$total-without-defval.yaml +++ b/src/test/resources/checks/v31/parameters/OAR026/with-$ref-with-$total-without-defval.yaml @@ -11,7 +11,7 @@ components: type: array items: type: string - total: # Noncompliant {{OAR026: The $total parameter default value should be false}} + total: in: query name: $total schema: diff --git a/src/test/resources/checks/v32/examples/OAR031/allof-schema-missing-example.yaml b/src/test/resources/checks/v32/examples/OAR031/allof-schema-missing-example.yaml new file mode 100644 index 00000000..7e9327df --- /dev/null +++ b/src/test/resources/checks/v32/examples/OAR031/allof-schema-missing-example.yaml @@ -0,0 +1,32 @@ +openapi: "3.2.0" +info: + version: 1.0.0 + title: Swagger Petstore +components: + schemas: + BaseEntity: + type: object + properties: + id: # Noncompliant {{OAR031: Property 'id' is missing an example.}} + type: integer + Pet: + allOf: + - $ref: '#/components/schemas/BaseEntity' + properties: + name: + type: string + example: "Fluffy" +paths: + /pets: + get: + responses: + 200: + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + example: + name: Fluffy + 204: + description: No content diff --git a/src/test/resources/checks/v32/examples/OAR031/externalref.yaml b/src/test/resources/checks/v32/examples/OAR031/externalref.yaml index 2c326a8b..e003f0f5 100644 --- a/src/test/resources/checks/v32/examples/OAR031/externalref.yaml +++ b/src/test/resources/checks/v32/examples/OAR031/externalref.yaml @@ -14,7 +14,7 @@ paths: summary: Get all users description: Returns a list of users. responses: - '200': # Noncompliant {{OAR031: Responses must have one or more examples defined}} + '200': # Noncompliant {{OAR031: Response must have an example defined}} description: A JSON array of user objects content: application/json: @@ -23,7 +23,7 @@ paths: items: $ref: '#/components/schemas/User' '400': - $ref: >- # Noncompliant {{OAR031: Responses must have one or more examples defined}} + $ref: >- # Noncompliant {{OAR031: Response must have an example defined}} http://localhost:18089/OAR031.yaml#/components/responses/server_error_response /users/{userId}: get: @@ -40,14 +40,14 @@ paths: name: Puppy type: dog responses: - '200': # Noncompliant {{OAR031: Responses must have one or more examples defined}} + '200': # Noncompliant {{OAR031: Response must have an example defined}} description: A single user object content: application/json: schema: $ref: '#/components/schemas/User' '400': - $ref: >- # Noncompliant {{OAR031: Responses must have one or more examples defined}} + $ref: >- # Noncompliant {{OAR031: Response must have an example defined}} http://localhost:18089/OAR031.yaml#/components/responses/server_error_response components: schemas: diff --git a/src/test/resources/checks/v32/examples/OAR031/nested-properties-examples.yaml b/src/test/resources/checks/v32/examples/OAR031/nested-properties-examples.yaml index e93c96a9..c9656aff 100644 --- a/src/test/resources/checks/v32/examples/OAR031/nested-properties-examples.yaml +++ b/src/test/resources/checks/v32/examples/OAR031/nested-properties-examples.yaml @@ -6,7 +6,7 @@ paths: /profile: put: summary: Update user profile - requestBody: # Noncompliant {{OAR031: Request body must have one or more examples defined}} + requestBody: # Noncompliant {{OAR031: Request body must have an example defined}} required: true content: application/json: @@ -35,5 +35,5 @@ paths: type: string example: "28001" responses: - '200': # Noncompliant {{OAR031: Responses must have one or more examples defined}} + '200': # Noncompliant {{OAR031: Response must have an example defined}} description: OK \ No newline at end of file diff --git a/src/test/resources/checks/v32/examples/OAR031/orphan-schema.yaml b/src/test/resources/checks/v32/examples/OAR031/orphan-schema.yaml new file mode 100644 index 00000000..391fd0fc --- /dev/null +++ b/src/test/resources/checks/v32/examples/OAR031/orphan-schema.yaml @@ -0,0 +1,32 @@ +openapi: "3.2.0" +info: + version: 1.0.0 + title: Swagger Petstore +paths: + /pets: + get: + responses: + 200: + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/pet' + example: + name: Fluffy + 204: + description: No content +components: + schemas: + pet: + type: object + properties: + name: + type: string + example: "Fluffy" + # Never referenced by any path - must not be flagged (orphan-schema exclusion). + UnusedSchema: + type: object + properties: + unused_field: + type: string diff --git a/src/test/resources/checks/v32/examples/OAR031/without-examples.yaml b/src/test/resources/checks/v32/examples/OAR031/without-examples.yaml index 9f62c796..1f5c0ad6 100644 --- a/src/test/resources/checks/v32/examples/OAR031/without-examples.yaml +++ b/src/test/resources/checks/v32/examples/OAR031/without-examples.yaml @@ -6,7 +6,7 @@ paths: /pets: get: responses: - 206: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + 206: # Noncompliant {{OAR031: Response must have an example defined}} description: Pet list content: application/json: @@ -16,7 +16,7 @@ paths: $ref: "#/components/responses/server_error_response" /pets/{id}: parameters: - - in: query # Noncompliant {{OAR031: Parameters must have one or more examples defined}} + - in: query # Noncompliant {{OAR031: Parameter '$start' must have an example defined}} name: $start schema: type: integer @@ -24,7 +24,7 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: - 200: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + 200: # Noncompliant {{OAR031: Response must have an example defined}} description: One pet content: application/json: @@ -35,8 +35,8 @@ paths: components: parameters: - id: - in: path # Noncompliant {{OAR031: Parameters must have one or more examples defined}} + id: # Noncompliant {{OAR031: Parameter 'id' must have an example defined}} + in: path name: id schema: type: integer @@ -48,26 +48,26 @@ components: pet: type: object properties: - name: # Noncompliant {{OAR031: Properties must have an example defined}} + name: # Noncompliant {{OAR031: Property 'name' is missing an example.}} type: string - type: # Noncompliant {{OAR031: Properties must have an example defined}} + type: # Noncompliant {{OAR031: Property 'type' is missing an example.}} type: string pets: type: object properties: - size: # Noncompliant {{OAR031: Properties must have an example defined}} + size: # Noncompliant {{OAR031: Property 'size' is missing an example.}} type: integer pets: type: array items: $ref: '#/components/schemas/pet' responses: - server_error_response: # Noncompliant {{OAR031: Responses must have one or more examples defined}} + server_error_response: # Noncompliant {{OAR031: Response must have an example defined}} description: Default error response content: application/json: schema: type: object properties: - error: # Noncompliant {{OAR031: Properties must have an example defined}} + error: # Noncompliant {{OAR031: Property 'error' is missing an example.}} type: string \ No newline at end of file diff --git a/src/test/resources/checks/v32/parameters/OAR026/header-with-$total-with-defval-true.json b/src/test/resources/checks/v32/parameters/OAR026/header-with-$total-with-defval-true.json new file mode 100644 index 00000000..9f80a425 --- /dev/null +++ b/src/test/resources/checks/v32/parameters/OAR026/header-with-$total-with-defval-true.json @@ -0,0 +1,26 @@ +{ + "openapi" : "3.2.0", + "info" : { + "version" : "1.0.0", + "title" : "Swagger Petstore" + }, + "paths" : { + "/pets" : { + "get" : { + "parameters" : [ { + "in" : "header", + "name" : "$total", + "schema" : { + "type" : "boolean", + "default" : true + } + } ], + "responses" : { + "206" : { + "description" : "Ok" + } + } + } + } + } +} diff --git a/src/test/resources/checks/v32/parameters/OAR026/header-with-$total-with-defval-true.yaml b/src/test/resources/checks/v32/parameters/OAR026/header-with-$total-with-defval-true.yaml new file mode 100644 index 00000000..8ef384dd --- /dev/null +++ b/src/test/resources/checks/v32/parameters/OAR026/header-with-$total-with-defval-true.yaml @@ -0,0 +1,16 @@ +openapi: "3.2.0" +info: + version: 1.0.0 + title: Swagger Petstore +paths: + /pets: + get: + parameters: + - in: header + name: $total + schema: + type: boolean + default: true + responses: + 206: + description: Ok diff --git a/src/test/resources/checks/v32/parameters/OAR026/plain-with-$total-without-defval.json b/src/test/resources/checks/v32/parameters/OAR026/plain-with-$total-without-defval.json index 82d1bd2c..72777f11 100644 --- a/src/test/resources/checks/v32/parameters/OAR026/plain-with-$total-without-defval.json +++ b/src/test/resources/checks/v32/parameters/OAR026/plain-with-$total-without-defval.json @@ -16,7 +16,7 @@ "type" : "string" } } - }, { # Noncompliant {{OAR026: The $total parameter default value should be false}} + }, { "in" : "query", "name" : "$total", "schema": { diff --git a/src/test/resources/checks/v32/parameters/OAR026/plain-with-$total-without-defval.yaml b/src/test/resources/checks/v32/parameters/OAR026/plain-with-$total-without-defval.yaml index fc709154..24b90ca9 100644 --- a/src/test/resources/checks/v32/parameters/OAR026/plain-with-$total-without-defval.yaml +++ b/src/test/resources/checks/v32/parameters/OAR026/plain-with-$total-without-defval.yaml @@ -12,7 +12,7 @@ paths: type: array items: type: string - - in: query # Noncompliant {{OAR026: The $total parameter default value should be false}} + - in: query name: $total schema: type: boolean diff --git a/src/test/resources/checks/v32/parameters/OAR026/post-with-$total-with-defval-true.json b/src/test/resources/checks/v32/parameters/OAR026/post-with-$total-with-defval-true.json new file mode 100644 index 00000000..d2712597 --- /dev/null +++ b/src/test/resources/checks/v32/parameters/OAR026/post-with-$total-with-defval-true.json @@ -0,0 +1,26 @@ +{ + "openapi" : "3.2.0", + "info" : { + "version" : "1.0.0", + "title" : "Swagger Petstore" + }, + "paths" : { + "/pets" : { + "post" : { + "parameters" : [ { + "in" : "query", + "name" : "$total", + "schema" : { + "type" : "boolean", + "default" : true + } + } ], + "responses" : { + "201" : { + "description" : "Created" + } + } + } + } + } +} diff --git a/src/test/resources/checks/v32/parameters/OAR026/post-with-$total-with-defval-true.yaml b/src/test/resources/checks/v32/parameters/OAR026/post-with-$total-with-defval-true.yaml new file mode 100644 index 00000000..81041fd2 --- /dev/null +++ b/src/test/resources/checks/v32/parameters/OAR026/post-with-$total-with-defval-true.yaml @@ -0,0 +1,16 @@ +openapi: "3.2.0" +info: + version: 1.0.0 + title: Swagger Petstore +paths: + /pets: + post: + parameters: + - in: query + name: $total + schema: + type: boolean + default: true + responses: + 201: + description: Created diff --git a/src/test/resources/checks/v32/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json b/src/test/resources/checks/v32/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json new file mode 100644 index 00000000..76c2f81a --- /dev/null +++ b/src/test/resources/checks/v32/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.json @@ -0,0 +1,30 @@ +{ + "openapi" : "3.2.0", + "info" : { + "version" : "1.0.0", + "title" : "Swagger Petstore" + }, + "components" : { + "parameters" : { + "total" : { + "in" : "query", + "name" : "$total", + "schema" : { + "type" : "boolean", + "default" : true + } + } + } + }, + "paths" : { + "/pets" : { + "get" : { + "responses" : { + "206" : { + "description" : "Ok" + } + } + } + } + } +} diff --git a/src/test/resources/checks/v32/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml b/src/test/resources/checks/v32/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml new file mode 100644 index 00000000..aefbef29 --- /dev/null +++ b/src/test/resources/checks/v32/parameters/OAR026/with-$ref-unreferenced-with-$total-with-defval-true.yaml @@ -0,0 +1,18 @@ +openapi: "3.2.0" +info: + version: 1.0.0 + title: Swagger Petstore +components: + parameters: + total: + in: query + name: $total + schema: + type: boolean + default: true +paths: + /pets: + get: + responses: + 206: + description: Ok diff --git a/src/test/resources/checks/v32/parameters/OAR026/with-$ref-with-$total-without-defval.json b/src/test/resources/checks/v32/parameters/OAR026/with-$ref-with-$total-without-defval.json index 0c9c05b7..11e2235a 100644 --- a/src/test/resources/checks/v32/parameters/OAR026/with-$ref-with-$total-without-defval.json +++ b/src/test/resources/checks/v32/parameters/OAR026/with-$ref-with-$total-without-defval.json @@ -16,7 +16,7 @@ } } }, - "total" : { # Noncompliant {{OAR026: The $total parameter default value should be false}} + "total" : { "in" : "query", "name" : "$total", "schema": { diff --git a/src/test/resources/checks/v32/parameters/OAR026/with-$ref-with-$total-without-defval.yaml b/src/test/resources/checks/v32/parameters/OAR026/with-$ref-with-$total-without-defval.yaml index 3ac00495..57681126 100644 --- a/src/test/resources/checks/v32/parameters/OAR026/with-$ref-with-$total-without-defval.yaml +++ b/src/test/resources/checks/v32/parameters/OAR026/with-$ref-with-$total-without-defval.yaml @@ -11,7 +11,7 @@ components: type: array items: type: string - total: # Noncompliant {{OAR026: The $total parameter default value should be false}} + total: in: query name: $total schema: From d697baa07f520f4b08d7a6da3b066361943e7ac1 Mon Sep 17 00:00:00 2001 From: Melsy Huamani Date: Fri, 11 Sep 2026 16:35:04 -0500 Subject: [PATCH 3/3] fix: oar041, oar043 rules --- CHANGELOG.md | 13 +- .../rules/openapi/apim/wso2/OAR041.html | 62 +++--- .../rules/openapi/apim/wso2/OAR041.json | 2 +- .../es/openapi/rules/openapi/core/OAR043.html | 190 ------------------ .../es/openapi/rules/openapi/core/OAR043.json | 13 -- .../rules/openapi/operations/OAR043.html | 133 ++++-------- .../rules/openapi/operations/OAR043.json | 2 +- .../rules/openapi/apim/wso2/OAR041.html | 4 +- .../openapi/rules/openapi/core/OAR043.html | 1 - .../openapi/rules/openapi/core/OAR043.json | 13 -- .../rules/openapi/operations/OAR043.html | 54 ++++- .../rules/openapi/operations/OAR043.json | 2 +- 12 files changed, 133 insertions(+), 356 deletions(-) delete mode 100644 src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/core/OAR043.html delete mode 100644 src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/core/OAR043.json delete mode 100644 src/main/resources/org/sonar/l10n/openapi/rules/openapi/core/OAR043.html delete mode 100644 src/main/resources/org/sonar/l10n/openapi/rules/openapi/core/OAR043.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 52cd61ef..757eeecf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,11 +9,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- OAR005 - UndefinedWso2ScopeUse - Resolve a `$ref` on `x-wso2-security` and on each individual scope, and iterate map-form `x-wso2-scopes` in addition to the array form (shared with `AbstractWso2ScopesCheck` through new `JsonNodeUtils` helpers), so an operation whose `x-scope` names a scope declared behind a reference or under a mapping key is no longer reported. Also accept the `~`/`Null`/`NULL` null spellings for the operation's `x-scope` (previously only the lowercase `null` scalar was treated as null). Matching remains on the scope `name` only, never on `key`. -- OAR009 / OAR010 - DefaultRequestMediaType / DefaultResponseMediaType - `AbstractDefaultMediaTypeCheck` now compares `default-media-type` and the document's actual media types case-insensitively (matching Spectral's `apq-response-media-type`), so a spec written with mixed-case media types (e.g. `Application/JSON`) or a `default-media-type` property configured with different casing no longer diverges from Spectral. -- OAR007 - UndefinedResponseMediaType - Fixed the rule description: paragraph 1 wrongly stated "the request data formats must be defined" and referenced the `"consumes"` keyword (copy-pasted from OAR006); corrected to describe response media types and the `"produces"` keyword, matching the already-correct Spanish translation and the rest of the description. -- OAR026 - TotalParameterDefaultValue - Rewritten to match Spectral exactly: subscribes to `GET` operations (was every `PARAMETER` node in the document) and only evaluates a `$total` parameter that is `in: query`, resolving `$ref`s (internal and external) along the way; a `$total` parameter under a non-`GET` operation, with a different `in`, or declared but never referenced by any `GET` is no longer flagged. A missing `default` is no longer reported (previously it was) - only an explicitly-declared non-`false` default raises an issue, matching Spectral's `falsy` semantics. -- OAR031 - Examples - Property-level checks (`validateProperty`) now only cover schemas actually reachable from a path's `parameters`/`requestBody`/`responses` (matching Spectral's `given` reach); an unreferenced `components.schemas`/`definitions` entry no longer produces false-positive property findings. Removed a hack that skipped every direct property of a schema with an `allOf` sibling key, and added `allOf`/`oneOf`/`anyOf` traversal to `isSchemaCovered` and the v2 response property walk, so a property declared only inside a combiner member (e.g. inherited via `allOf`) is now correctly checked (previously a false negative). Parameter- and property-level messages now interpolate the actual name (`Parameter '' must have an example defined`, `Property '' is missing an example.`), matching Spectral verbatim; response/request-body message text also corrected to match Spectral exactly (`Response must have an example defined`, `Request body must have an example defined`). Fixed the English rule doc listing the four toggle rule-property names in kebab-case (`validate-response`, ...) when the real keys are camelCase (`validateResponse`, ...). Also, found while cross-checking line numbers against Spectral: a `$ref`'d parameter's violation is now anchored at the shared definition's own key (e.g. `id:`) instead of its first content line, matching the response/request-body anchoring convention and Spectral's line; an OAS3 parameter example declared per media type under `content` is now recognized (previously always flagged as missing, regardless of a valid content-based example); the v2 response-driven property walk (`visitPathNode`) now excludes `204` responses, matching the primary walk; and Swagger 2.0 non-`body` parameters (query/path/header/formData) are now exempt from the parameter-level check in Spectral too (that field doesn't exist in the OAS2 parameter spec, only `default` does - Sonar already exempted them). +- OAR041 - UndefinedAuthTypeForWso2Scope - Fixed the `x-aut-type` typo in the HTML examples (should be `x-auth-type`) and rewrote the Spanish description, which described an unrelated scope-catalog structure instead of the actual check. +- OAR043 - ParsingError - Rewrote the English/Spanish HTML docs with real examples, expanded the JSON titles, and removed the orphaned `core/OAR043.*` resources (not loaded by any registered rule group). +- `tools/IssueDumper.java` - Now recovers from a `ValidationException` during test scanning for `OAR043ParsingErrorCheck`, so schema-invalid fixtures can be cross-checked against Spectral instead of crashing the harness. +- OAR005 - UndefinedWso2ScopeUse - Resolves `$ref`s on `x-wso2-security`/scopes and accepts map-form `x-wso2-scopes`, plus all null spellings for `x-scope`. +- OAR009 / OAR010 - DefaultRequestMediaType / DefaultResponseMediaType - Media type comparisons are now case-insensitive, matching Spectral. +- OAR007 - UndefinedResponseMediaType - Fixed the rule description, which wrongly described request media types (`consumes`) instead of response ones (`produces`). +- OAR026 - TotalParameterDefaultValue - Rewritten to match Spectral: only checks `GET`/`in: query` `$total` parameters, resolves `$ref`s, and no longer flags a missing `default`. +- OAR031 - Examples - Property checks now only cover schemas reachable from the path, traverse `allOf`/`oneOf`/`anyOf`, interpolate the actual name in messages, and fix several line-anchoring and OAS2-exemption divergences from Spectral. ## [1.6.0-beta-5] - 2026-09-09 diff --git a/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/apim/wso2/OAR041.html b/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/apim/wso2/OAR041.html index 949d12c0..bea3a1bf 100644 --- a/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/apim/wso2/OAR041.html +++ b/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/apim/wso2/OAR041.html @@ -1,34 +1,20 @@ -

- Los scopes disponibles se definen al final del documento de definición, a nivel raíz. Se definen mediante la siguiente estructura: -

+

El uso de un scope (x-scope) en una operación siempre requiere que se defina también un tipo de autenticación (x-auth-type).

+

Ejemplo de código no compatible

+swagger: "2.0"
 x-wso2-security:
   apim:
-  x-wso2-scopes:
-    - name: Nombre_scope_1
-      description: ""
-      key: Etiqueta_scope_1
-      roles: "Role_1, Role_2, …, Role_n"
-    - name: Nombre_scope_2>
-      description: ""
-      key: Etiqueta_scope_2
-      roles: "Role_1,Role_2,…,Role_n"
+    x-wso2-scopes:
+    - name: read
+      key: read
+      roles: READ_ROLE
+      description: Allows users to view records
+paths:
+  /pets:
+    get:
+      x-scope: read
 
-

- Cada elemento del array x-wso2-scopes contiene los siguientes elementos: -

-
    -
  • name: El nombre que recibirá el scope. -
      -
    • La nomenclatura es {Código POAP del API}_sc_{nombre-descriptivo}
    • -
    • Por ejemplo: USUG-API_sc_user-scope
    • -
    -
  • -
  • description: Breve descripción del scope. Opcional.
  • -
  • key: Etiqueta del scope. Se recomienda que coincida con el nombre para evitar confusiones.
  • -
  • roles: Cadena con todos los roles asociados al scope separados por coma (se corresponde con los perfiles de cada Aplicación obtenidos de USUG).
  • -
-

Noncompliant

+

Solución compatible

 swagger: "2.0"
 x-wso2-security:
@@ -42,10 +28,11 @@ 

Noncompliant

/pets: get: x-scope: read + x-auth-type: "Application & Application User"
-

Compliant

+

Ejemplo de código no compatible (OpenAPI 3)

-swagger: "2.0"
+openapi: "3.0.0"
 x-wso2-security:
   apim:
     x-wso2-scopes:
@@ -57,5 +44,20 @@ 

Compliant

/pets: get: x-scope: read - x-aut-type: "Application & Application User"
+

Solución compatible (OpenAPI 3)

+
+openapi: "3.0.0"
+x-wso2-security:
+  apim:
+    x-wso2-scopes:
+    - name: read
+      key: read
+      roles: READ_ROLE
+      description: Allows users to view records
+paths:
+  /pets:
+    get:
+      x-scope: read
+      x-auth-type: "Application & Application User"
+
\ No newline at end of file diff --git a/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/apim/wso2/OAR041.json b/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/apim/wso2/OAR041.json index 81bd0427..d9ab20a9 100644 --- a/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/apim/wso2/OAR041.json +++ b/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/apim/wso2/OAR041.json @@ -1,5 +1,5 @@ { - "title": "OAR041 - UndefinedAuthTypeForWso2Scope - El uso de x-scope require del uso de x-auth-type", + "title": "OAR041 - UndefinedAuthTypeForWso2Scope - El uso de x-scope requiere del uso de x-auth-type", "type": "VULNERABILITY", "status": "ready", "remediation": { diff --git a/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/core/OAR043.html b/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/core/OAR043.html deleted file mode 100644 index c611114f..00000000 --- a/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/core/OAR043.html +++ /dev/null @@ -1,190 +0,0 @@ -

El archivo con la especificación OpenAPI no puede contener líneas vacías, esto impedirá su análisis.

-

Ejemplo de código no compatible (OpenAPI 2)

-

JSON

-
-{
-    "swagger": "2.0", 
-    "info": {
-        "title": "Ejemplo de API", 
-        "version": "1.0.0"
-    }, 
-    "paths": {
-        "/clientes": {
-            "get": {
-                "summary": "Obtenci\u00f3n de una colecci\u00f3n de clientes", 
-                "description": "Permite obtener una colecci\u00f3n de clientes.\nPor ejemplo: /usuarios o /expedientes.\nPuede admitir cabeceras, *query parameters* y el objeto $filter en el body.\n\n**Scope Oauth:** clientes_sc_consulta\n", 
-                "responses": {
-                    "200": {
-                        "description": "OK"
-                    }
-                }
-            }
-        }
-    }
-}
-
-

YAML

-
-swagger: "2.0"
-info: 
-  title: Ejemplo de API
-  version: 1.0.0
-paths:
-
-  /clientes:
-  
-    get:
-      # 'summary': Es OBLIGATORIO usar este elemento en todos los paths. Se trata de una breve descripción del endpoint
-      summary: Obtención de una colección de clientes
-      # 'description': es OBLIGATORIO que el contenido de este campo esté cumplimentado y difiera del del campo 'summary'
-      # Debe darse una descripción lo más detallada posible de la funcionalidad del endpoint sin describir la lógica de negocio.
-      # Si el endpoint está protegido por un scope Oauth debe indicarse cuál és en la descripción.
-      description: |
-        Permite obtener una colección de clientes.
-        Por ejemplo: /usuarios o /expedientes.
-        Puede admitir cabeceras, *query parameters* y el objeto $filter en el body.
-
-        **Scope Oauth:** clientes_sc_consulta
-      
-      responses:
-        200:
-          description: OK
-
-

Solución compatible (OpenAPI 2)

-

JSON

-
-{
-    "swagger": "2.0", 
-    "info": {
-        "title": "Ejemplo de API", 
-        "version": "1.0.0"
-    }, 
-    "paths": {
-        "/clientes": {
-            "get": {
-                "summary": "Obtenci\u00f3n de una colecci\u00f3n de clientes", 
-                "description": "Permite obtener una colecci\u00f3n de clientes.\nPor ejemplo: /usuarios o /expedientes.\nPuede admitir cabeceras, *query parameters* y el objeto $filter en el body.\n**Scope Oauth:** clientes_sc_consulta\n", 
-                "responses": {
-                    "200": {
-                        "description": "OK"
-                    }
-                }
-            }
-        }
-    }
-}
-
-

YAML

-
-swagger: "2.0"
-info: 
-  title: Ejemplo de API
-  version: 1.0.0
-paths:
-  /clientes:
-    get:
-      # 'summary': Es OBLIGATORIO usar este elemento en todos los paths. Se trata de una breve descripción del endpoint
-      summary: Obtención de una colección de clientes
-      # 'description': es OBLIGATORIO que el contenido de este campo esté cumplimentado y difiera del del campo 'summary'
-      # Debe darse una descripción lo más detallada posible de la funcionalidad del endpoint sin describir la lógica de negocio.
-      # Si el endpoint está protegido por un scope Oauth debe indicarse cuál és en la descripción.
-      description: |
-        Permite obtener una colección de clientes.
-        Por ejemplo: /usuarios o /expedientes.
-        Puede admitir cabeceras, *query parameters* y el objeto $filter en el body.
-        **Scope Oauth:** clientes_sc_consulta
-      responses:
-        200:
-          description: OK
-
-

Ejemplo de código no compatible (OpenAPI 3)

-

JSON

-
-{
-    "openapi": "3.0.1", 
-    "info": {
-        "title": "Ejemplo de API", 
-        "version": "1.0.0"
-    }, 
-    "paths": {
-        "/clientes": {
-            "get": {
-                "summary": "Obtenci\u00f3n de una colecci\u00f3n de clientes", 
-                "description": "Permite obtener una colecci\u00f3n de clientes.\nPor ejemplo: /usuarios o /expedientes.\nPuede admitir cabeceras, *query parameters* y el objeto $filter en el body.\n\n**Scope Oauth:** clientes_sc_consulta\n", 
-                "responses": {
-                    "200": {
-                        "description": "OK"
-                    }
-                }
-            }
-        }
-    }
-}
-
-

YAML

-
-openapi: 3.0.1
-
-info:
-  title: Ejemplo de API
-  version: 1.0.0
-
-paths:
-
-  /clientes:
-
-    get:
-      summary: Obtención de una colección de clientes
-      description: |
-        Permite obtener una colección de clientes.
-        Por ejemplo: /usuarios o /expedientes.
-        Puede admitir cabeceras, *query parameters* y el objeto $filter en el body.
-
-        **Scope Oauth:** clientes_sc_consulta
-      responses:
-        200:
-          description: OK
-
-

Solución compatible (OpenAPI 3)

-

JSON

-
-{
-    "openapi": "3.0.1", 
-    "info": {
-        "title": "Ejemplo de API", 
-        "version": "1.0.0"
-    }, 
-    "paths": {
-        "/clientes": {
-            "get": {
-                "summary": "Obtenci\u00f3n de una colecci\u00f3n de clientes", 
-                "description": "Permite obtener una colecci\u00f3n de clientes.\nPor ejemplo: /usuarios o /expedientes.\nPuede admitir cabeceras, *query parameters* y el objeto $filter en el body.\n**Scope Oauth:** clientes_sc_consulta\n", 
-                "responses": {
-                    "200": {
-                        "description": "OK"
-                    }
-                }
-            }
-        }
-    }
-}
-
-

YAML

-
-openapi: 3.0.1
-info:
-  title: Ejemplo de API
-  version: 1.0.0
-paths:
-  /clientes:
-    get:
-      summary: Obtención de una colección de clientes
-      description: |
-        Permite obtener una colección de clientes.
-        Por ejemplo: /usuarios o /expedientes.
-        Puede admitir cabeceras, *query parameters* y el objeto $filter en el body.
-        **Scope Oauth:** clientes_sc_consulta
-      responses:
-        200:
-          description: OK
-
\ No newline at end of file diff --git a/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/core/OAR043.json b/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/core/OAR043.json deleted file mode 100644 index b9eb829f..00000000 --- a/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/core/OAR043.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "title": "OAR043 - ParsingError - El archivo no puede ser analizado", - "type": "BUG", - "status": "ready", - "remediation": { - "func": "Constant\/Issue", - "constantCost": "30min" - }, - "tags": [ - "core" - ], - "defaultSeverity": "BLOCKER" -} diff --git a/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/operations/OAR043.html b/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/operations/OAR043.html index 7e145323..a12302b8 100644 --- a/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/operations/OAR043.html +++ b/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/operations/OAR043.html @@ -1,116 +1,53 @@ -

El archivo con la especificación OpenAPI no puede contener líneas vacías, esto impedirá su análisis.

-

Ejemplo de código no compatible (OpenAPI 2)

+

Este archivo no es una definición válida de OpenAPI o Swagger. Esto incluye tanto documentos que un parser estricto ni siquiera puede cargar (sintaxis YAML o JSON mal formada) como documentos que sí cargan pero que no superan la validación estructural de la especificación.

+

Ejemplo de código no compatible (indentación YAML incorrecta)

-{
-    "swagger": "2.0", 
-    "info": {
-        "title": "Ejemplo de API", 
-        "version": "1.0.0"
-    }, 
-    "paths": {
-        "/clientes": {
-            "get": {
-                "summary": "Obtenci\u00f3n de una colecci\u00f3n de clientes", 
-                "description": "Permite obtener una colecci\u00f3n de clientes.\nPor ejemplo: /usuarios o /expedientes.\nPuede admitir cabeceras, *query parameters* y el objeto $filter en el body.\n\n**Scope Oauth:** clientes_sc_consulta\n", 
-                "responses": {
-                    "200": {
-                        "description": "OK"
-                    }
-                }
-            }
-        }
-    }
-}
-
-
-swagger: "2.0"
-info: 
-  title: Ejemplo de API
-  version: 1.0.0
-paths:
-
-  /clientes:
-  
-    get:
-      # 'summary': Es OBLIGATORIO usar este elemento en todos los paths. Se trata de una breve descripción del endpoint
-      summary: Obtención de una colección de clientes
-      # 'description': es OBLIGATORIO que el contenido de este campo esté cumplimentado y difiera del del campo 'summary'
-      # Debe darse una descripción lo más detallada posible de la funcionalidad del endpoint sin describir la lógica de negocio.
-      # Si el endpoint está protegido por un scope Oauth debe indicarse cuál és en la descripción.
-      description: |
-        Permite obtener una colección de clientes.
-        Por ejemplo: /usuarios o /expedientes.
-        Puede admitir cabeceras, *query parameters* y el objeto $filter en el body.
-
-        **Scope Oauth:** clientes_sc_consulta
-      
-      responses:
-        200:
-          description: OK
-
-

Solución compatible (OpenAPI 2)

-
-swagger: "2.0"
-info: 
+openapi: "3.0.0"
+info:
   title: Ejemplo de API
-  version: 1.0.0
+  version: "1.0.0"
 paths:
-  /clientes:
+  /pets:
     get:
-      # 'summary': Es OBLIGATORIO usar este elemento en todos los paths. Se trata de una breve descripción del endpoint
-      summary: Obtención de una colección de clientes
-      # 'description': es OBLIGATORIO que el contenido de este campo esté cumplimentado y difiera del del campo 'summary'
-      # Debe darse una descripción lo más detallada posible de la funcionalidad del endpoint sin describir la lógica de negocio.
-      # Si el endpoint está protegido por un scope Oauth debe indicarse cuál és en la descripción.
-      description: |
-        Permite obtener una colección de clientes.
-        Por ejemplo: /usuarios o /expedientes.
-        Puede admitir cabeceras, *query parameters* y el objeto $filter en el body.
-        **Scope Oauth:** clientes_sc_consulta
       responses:
         200:
           description: OK
+       "400":
+          description: Bad Request
 
-

Ejemplo de código no compatible (OpenAPI 3)

+

Solución compatible

-openapi: 3.0.1
-
+openapi: "3.0.0"
 info:
   title: Ejemplo de API
-  version: 1.0.0
-
+  version: "1.0.0"
 paths:
-
-  /clientes:
-
+  /pets:
     get:
-      summary: Obtención de una colección de clientes
-      description: |
-        Permite obtener una colección de clientes.
-        Por ejemplo: /usuarios o /expedientes.
-        Puede admitir cabeceras, *query parameters* y el objeto $filter en el body.
-
-        **Scope Oauth:** clientes_sc_consulta
       responses:
-        200:
+        "200":
           description: OK
+        "400":
+          description: Bad Request
 
-

Solución compatible (OpenAPI 3)

+

Ejemplo de código no compatible (coma colgante en JSON)

-openapi: 3.0.1
-info:
-  title: Ejemplo de API
-  version: 1.0.0
-paths:
-  /clientes:
-    get:
-      summary: Obtención de una colección de clientes
-      description: |
-        Permite obtener una colección de clientes.
-        Por ejemplo: /usuarios o /expedientes.
-        Puede admitir cabeceras, *query parameters* y el objeto $filter en el body.
-        **Scope Oauth:** clientes_sc_consulta
-      responses:
-        200:
-          description: OK
+{
+  "openapi": "3.0.0",
+  "info": {
+    "title": "Ejemplo de API",
+    "version": "1.0.0",
+  },
+  "paths": {}
+}
 
+

Solución compatible

+
+{
+  "openapi": "3.0.0",
+  "info": {
+    "title": "Ejemplo de API",
+    "version": "1.0.0"
+  },
+  "paths": {}
+}
+
\ No newline at end of file diff --git a/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/operations/OAR043.json b/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/operations/OAR043.json index 02a6e096..6ca56a29 100644 --- a/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/operations/OAR043.json +++ b/src/main/resources/org/sonar/l10n/es/openapi/rules/openapi/operations/OAR043.json @@ -1,5 +1,5 @@ { - "title": "OAR043 - ParsingError - El archivo no puede ser analizado", + "title": "OAR043 - ParsingError - El archivo no puede ser analizado o no supera la validación estructural", "type": "BUG", "status": "ready", "remediation": { diff --git a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/apim/wso2/OAR041.html b/src/main/resources/org/sonar/l10n/openapi/rules/openapi/apim/wso2/OAR041.html index 689f891f..6e4c8b37 100644 --- a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/apim/wso2/OAR041.html +++ b/src/main/resources/org/sonar/l10n/openapi/rules/openapi/apim/wso2/OAR041.html @@ -28,7 +28,7 @@

Compliant Solution

/pets: get: x-scope: read - x-aut-type: "Application & Application User" + x-auth-type: "Application & Application User"

Noncompliant Code Example (OpenAPI 3)

@@ -59,5 +59,5 @@ 

Compliant Solution (OpenAPI 3)

/pets: get: x-scope: read - x-aut-type: "Application & Application User" + x-auth-type: "Application & Application User"
\ No newline at end of file diff --git a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/core/OAR043.html b/src/main/resources/org/sonar/l10n/openapi/rules/openapi/core/OAR043.html deleted file mode 100644 index 6d8aedb8..00000000 --- a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/core/OAR043.html +++ /dev/null @@ -1 +0,0 @@ -

This file is not a valid OpenAPI or Swagger definition.

diff --git a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/core/OAR043.json b/src/main/resources/org/sonar/l10n/openapi/rules/openapi/core/OAR043.json deleted file mode 100644 index 9b62772f..00000000 --- a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/core/OAR043.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "title": "OAR043 - ParsingError - OpenAPI file cannot be parsed", - "type": "BUG", - "status": "ready", - "remediation": { - "func": "Constant\/Issue", - "constantCost": "30min" - }, - "tags": [ - "core" - ], - "defaultSeverity": "BLOCKER" -} diff --git a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/operations/OAR043.html b/src/main/resources/org/sonar/l10n/openapi/rules/openapi/operations/OAR043.html index b2e384a4..21ae94bc 100644 --- a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/operations/OAR043.html +++ b/src/main/resources/org/sonar/l10n/openapi/rules/openapi/operations/OAR043.html @@ -1 +1,53 @@ -

This file is not a valid OpenAPI or Swagger definition.

\ No newline at end of file +

This file is not a valid OpenAPI or Swagger definition. This includes documents that a strict parser cannot even load (malformed YAML or JSON syntax) as well as documents that load but fail the structural validation of the specification.

+

Noncompliant Code Example (broken YAML indentation)

+
+openapi: "3.0.0"
+info:
+  title: Example API
+  version: "1.0.0"
+paths:
+  /pets:
+    get:
+      responses:
+        200:
+          description: OK
+       "400":
+          description: Bad Request
+
+

Compliant Solution

+
+openapi: "3.0.0"
+info:
+  title: Example API
+  version: "1.0.0"
+paths:
+  /pets:
+    get:
+      responses:
+        "200":
+          description: OK
+        "400":
+          description: Bad Request
+
+

Noncompliant Code Example (trailing comma in JSON)

+
+{
+  "openapi": "3.0.0",
+  "info": {
+    "title": "Example API",
+    "version": "1.0.0",
+  },
+  "paths": {}
+}
+
+

Compliant Solution

+
+{
+  "openapi": "3.0.0",
+  "info": {
+    "title": "Example API",
+    "version": "1.0.0"
+  },
+  "paths": {}
+}
+
\ No newline at end of file diff --git a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/operations/OAR043.json b/src/main/resources/org/sonar/l10n/openapi/rules/openapi/operations/OAR043.json index 1910e884..4ecc73f9 100644 --- a/src/main/resources/org/sonar/l10n/openapi/rules/openapi/operations/OAR043.json +++ b/src/main/resources/org/sonar/l10n/openapi/rules/openapi/operations/OAR043.json @@ -1,5 +1,5 @@ { - "title": "OAR043 - ParsingError - OpenAPI file cannot be parsed", + "title": "OAR043 - ParsingError - OpenAPI file cannot be parsed or fails structural validation", "type": "BUG", "status": "ready", "remediation": {