extends: [spectral:oas2, spectral:oas3] rules: # --------------------------------------------------------------------------- # General OAS rules # --------------------------------------------------------------------------- operation-operationId: false operation-tags: info operation-2xx-response: error paths-camelCase: description: All YAML/JSON paths MUST follow camelCase severity: warn recommended: true message: "{{property}} is not camelCase: {{error}}" given: $.paths[*]~ then: function: pattern functionOptions: # match: "/^(\/{1}(([{]?[a-z])[A-Za-z0-9]*[}]?)*)+$/" # - more generic one, allows /asasd{asdas}sadas pattern but also not closed braces match: "^\/([a-z][a-zA-Z0-9]+)?(\/[a-z][a-zA-Z0-9]+|\/{[a-z][a-zA-Z0-9]+})*$" # doesn't allow /asasd{asdas}sadas pattern or not closed braces definitions-camelCase-alphanumeric: description: All YAML/JSON definitions MUST follow fields-camelCase and be ASCII alphanumeric characters or `_` or `$`. severity: error recommended: true message: "{{property}} MUST follow camelCase and be ASCII alphanumeric characters or `_` or `$`." given: $.definitions[*]~ then: function: pattern functionOptions: match: "/^[a-z$_]{1}[A-Z09$_]*/" properties-camelCase-alphanumeric: description: All JSON Schema properties MUST follow fields-camelCase and be ASCII alphanumeric characters or `_` or `$`. severity: error recommended: true message: "{{property}} MUST follow camelCase and be ASCII alphanumeric characters or `_` or `$`." given: $.definitions..properties[*]~ then: function: pattern functionOptions: match: "/^[a-z$_]{1}[A-Z09$_]*/" request-GET-no-body: description: "A 'GET' request MUST NOT accept a 'body` parameter" severity: error given: $.paths..get.parameters..in then: function: pattern functionOptions: notMatch: "/^body$/" uri-template-cannot-dash: description: "The 'URI' template (RFC 6570 - https://tools.ietf.org/html/rfc6570) cannot contain a '-' character" severity: error recommended: true message: "{{property}}: {{description}}" given: "$.paths[*]~" then: function: pattern functionOptions: notMatch: "/-/" headers-no-x-headers: description: "All 'HTTP' headers SHOULD NOT include 'X-' headers (https://tools.ietf.org/html/rfc6648)." severity: warning given: "$..parameters[?(@.in == 'header')].name" message: "HTTP headers SHOULD NOT include 'X-' prefix." recommended: true type: style then: function: pattern functionOptions: notMatch: "/^X-([A-Z][a-z0-9]-)*([A-Z][a-z0-9])+/" # --------------------------------------------------------------------------- # Only OAS2 rules # --------------------------------------------------------------------------- protocol-https-only: description: "ALL requests MUST go through `https` protocol only" formats: - oas2 recommended: true severity: error type: "style" message: "Schemes MUST be https and no other value is allowed." given: $ then: field: schemes function: schema functionOptions: schema: type: array items: type: string enum: ["https"] maxItems: 1 request-support-json: description: Every request SHOULD support `application/json` media type formats: - oas2 severity: warn message: "{{description}}: {{error}}" recommended: true given: "$..consumes" then: function: schema functionOptions: schema: type: array contains: type: string enum: - application/json example-exists-in-parameters: description: All models MUST have a valid example. severity: error recommended: true formats: - oas2 message: "{{ property }} MUST have a valid example." given: "$..parameters..[?(@.in == 'body' && (@.example || @.schema.$ref))]" then: function: truthy # example-exists-in-definitions: # description: All models MUST have a valid example. # severity: error # recommended: true # formats: # - oas2 # message: "{{ property }} MUST have a valid example." # given: "$..definitions..[?(!@.example || !@..$ref)]" # then: # function: falsy # "$..parameters..[?(@.in == 'body')]..[?(@property !== 'properties' && @.example && ( @.type || @.format || @.$ref ))]" response-success-hal: # schemes and/or produces description: "All success responses MUST be of media type `application/hal+json`" severity: error given: $.paths..responses[?( @property >= 200 && @property < 300 && @property != 204)] recommended: true type: "style" formats: - oas2 message: "Response documents MUST follow application/hal+json: {{error}}" then: field: schema function: schema functionOptions: schema: $ref: "./supermodel/adidas/api/HAL.yaml" response-error-problem: # schemas and/or produces description: All error responses MUST be of media type `application/problem+json` severity: error formats: - oas2 given: $.paths..responses[?( @property >= 400 && @property < 600 )] recommended: true type: "style" message: "Error response document MUST follow application/problem+json: {{error}}" then: field: schema.example function: schema functionOptions: schema: $ref: "./supermodel/adidas/api/ProblemDetail.yaml" # --------------------------------------------------------------------------- # Only OAS3 rules # --------------------------------------------------------------------------- request-support-json-oas3: description: Every request SHOULD support `application/json` media type formats: - oas3 recommended: true severity: error message: "{{description}}: {{error}}" given: $.paths.[*].requestBody.content[?(@property.indexOf('json') === -1)]^ then: function: pattern functionOptions: match: falsy valid-example-in-parameters: description: Examples must be valid against their defined schema. message: "{{error}}" recommended: true formats: - oas3 severity: 0 type: validation given: "$..parameters..[?(@.in == 'body')]..[?(@property !== 'properties' && @.example && ( @.type || @.format || @.$ref ))]" then: function: schemaPath functionOptions: field: example schemaPath: "$" valid-example-in-definitions: description: Examples must be valid against their defined schema. message: "{{error}}" recommended: true formats: - oas3 severity: 0 type: validation given: "$..definitions..[?(@property !== 'properties' && @.example && (@.type || @.format || @.$ref))]" then: function: schemaPath functionOptions: field: example schemaPath: "$" protocol-https-only-oas3: # checks how does the servers array values start description: "ALL requests MUST go through `https` protocol only" formats: - oas3 recommended: true severity: error message: "Servers MUST be https and no other protocol is allowed." given: $.servers..url then: function: pattern functionOptions: match: "/^https:[a-zA-Z0-9./_@-~]+/" response-success-hal-oas3: description: "All success responses MUST be of media type `application/hal+json`" severity: error given: $.paths..responses[?( @property >= 200 && @property < 300 && @property != 204)].content[*]~ recommended: true # type: "style" formats: - oas3 message: "Response documents MUST be of application/hal+json media type: {{error}}" then: function: enumeration functionOptions: values: - application/hal+json response-success-hal-body-oas3: # schemes and/or produces description: "All success responses MUST follow `application/hal+json` schema" severity: error given: $.paths..responses[?( @property >= 200 && @property < 300 && @property != 204)].content[?(@property === "application/hal+json")] recommended: true type: "style" formats: - oas3 message: "Response documents MUST follow application/hal+json schema: {{error}}" then: field: schema function: schema functionOptions: schema: $ref: "./supermodel/adidas/api/HAL.yaml" # --------------------------------------------------------------------------- # Not implemented # --------------------------------------------------------------------------- # Waiting for implementation of casing for hyphenated pascal case in spectral # headers-hyphenated-pascal-case: # description: All `HTTP` headers MUST use `Hyphenated-Pascal-Case` notation # severity: error # given: $..parameters[*].in # heders-no-x-headers: # description: All `HTTP` headers SHOULD NOT include `X-` headers (https://tools.ietf.org/html/rfc6648). All non-standard headers are named without the `X-` prefix. # severity: warning # given: $..parameters[*].in # --------------------------------------------------------------------------- ## Other rules which are redundant or not feasible # --------------------------------------------------------------------------- # fields-date-iso8601: # description: Date and time MUST follow [`ISO 8601` standard](https://www.iso.org/iso-8601-date-and-time-format.html) # severity: error # fields-language-iso639: # description: Language codes MUST follow [`ISO 639` standard](https://www.iso.org/iso-639-language-codes.html) # severity: error # fields-country-iso3166: # description: Country codes MUST follow [`ISO 3166 alpha-2` standard](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) # severity: error # fields-currency-iso4217: # description: Currency codes MUST follow [`ISO 4217` standard](https://en.wikipedia.org/wiki/ISO_4217) # severity: error # response-303-async-link-header: # description: A successful and finished async api request returns `303` response code and sends the target resource location in the `Link` header # severity: hint