spectral.yaml (658 lines of code) (raw):

extends: spectral:oas functionsDir: './functions' functions: - consistent-response-body - error-response - has-header - lro-response-schema - naming-convention - operation-id - pagination-parameters - operation-security - pagination-response - param-names - param-names-unique - param-order - patch-content-type - path-param-schema - path-param-names - put-request-and-response-body - property-default-not-allowed - readonly-in-response-schema - security-definitions - security-requirements - schema-type-and-format - unused-definition - version-policy rules: info-contact: off no-$ref-siblings: off oas2-api-host: off oas2-api-schemes: off oas2-unused-definition: off openapi-tags: off operation-description: off operation-tags: off operation-tag-defined: off # Note: The Spectral VSCode extension will not display "hint" messages, so # use "info" rather than "hint". az-additional-properties-and-properties: description: Don't specify additionalProperties as a sibling of properties. severity: warn formats: ['oas2', 'oas3'] given: $..[?(@object() && @.type === 'object' && @.properties)] then: field: additionalProperties function: falsy az-additional-properties-object: description: additionalProperties with type object is a common error. severity: info formats: ['oas2', 'oas3'] # This rule produces redundant errors if run on the resolved spec. resolved: false given: $..[?(@property == 'additionalProperties' && @.type == 'object' && @.properties == undefined)] then: function: falsy az-api-version-enum: description: The api-version parameter should not be an enum. severity: warn # oas3 support has broken - disable for now formats: ['oas2'] given: - $.paths[*].parameters.[?(@.name == 'api-version')] - $.paths.*[get,put,post,patch,delete,options,head].parameters.[?(@.name == 'api-version')] then: field: enum function: falsy az-boolean-naming-convention: description: Do not use "is" prefix in names of boolean values severity: warn formats: ['oas2','oas3'] given: $ then: function: naming-convention functionOptions: type: boolean notMatch: '^is[A-Z]' az-consistent-response-body: description: Ensure the get, put, and patch response body schemas are consistent. message: '{{error}}' severity: warn formats: ['oas2'] given: $.paths.* then: function: consistent-response-body az-default-response: description: All operations should have a default (error) response. message: Operation is missing a default response. severity: warn given: $.paths.*.*.responses then: field: default function: truthy az-datetime-naming-convention: description: Use an "At" suffix in names of date-time values. severity: warn formats: ['oas2','oas3'] given: $ then: function: naming-convention functionOptions: type: date-time match: 'At$' az-delete-response-codes: description: A delete operation should have a 204 response. message: A delete operation should have a `204` response. severity: warn formats: ['oas2','oas3'] # The responses object of a delete operation given: $.paths[*].delete.responses then: function: schema functionOptions: schema: oneOf: - required: ['202'] - required: ['204'] not: required: ['200'] az-error-code-response-header: description: Error response should contain a x-ms-error-code header. severity: warn formats: ['oas2'] given: - $.paths[*][*].responses[?(@property >= 400)] - $.paths[*][*].responses["default"] then: function: schema functionOptions: schema: type: object required: ['headers'] properties: headers: type: object required: ["x-ms-error-code"] az-error-response: description: Error response body should conform to Microsoft Azure API Guidelines. message: '{{error}}' severity: warn formats: ['oas2'] given: $.paths[*][*].responses then: function: error-response az-formdata: description: Check for appropriate use of formData parameters. severity: info formats: ['oas2'] given: $.paths.*[get,put,post,patch,delete,options,head].parameters.[?(@.in == "formData")] then: function: falsy az-header-disallowed: description: Authorization, Content-type, and Accept headers should not be defined explicitly. message: 'Header parameter "{{value}}" should not be defined explicitly.' severity: warn # oas3 support has broken - disable for now formats: ['oas2'] given: - $.paths[*].parameters.[?(@.in == 'header')] - $.paths.*[get,put,post,patch,delete,options,head].parameters.[?(@.in == 'header')] then: function: pattern field: name functionOptions: notMatch: '/^(authorization|content-type|accept)$/i' az-lro-extension: description: "Operations with a 202 response should specify `x-ms-long-running-operation: true`." message: "Operations with a 202 response should specify `x-ms-long-running-operation: true`." severity: warn formats: ['oas2'] given: $.paths[*][*].responses[?(@property == '202')]^^ then: field: x-ms-long-running-operation function: truthy az-lro-get-not-allowed: description: Get operations should not be long-running. severity: warn formats: ['oas2','oas3'] given: $.paths[*].get.responses.202 then: function: falsy az-lro-patch-not-allowed: description: Patch operations should not be long-running. severity: warn formats: ['oas2','oas3'] given: $.paths[*].patch.responses.202 then: function: falsy az-lro-put-response-codes: description: Long-running PUT should not return a 202 response. severity: warn formats: ['oas2','oas3'] given: $.paths[*].put.responses.202 then: function: falsy az-lro-response-codes: description: An operation that returns 202 should not return other 2XX responses. severity: warn formats: ['oas2','oas3'] # The responses object of an operation that includes a 202 response # Exclude get, put and patch since the 202 for these will be flagged in other rules given: $.paths[*].[post,delete].responses[?(@property == '202')]^ then: function: schema functionOptions: schema: not: anyOf: - required: ['200'] - required: ['201'] - required: ['204'] az-lro-response-headers: description: A 202 response should include an Operation-Location response header. message: A 202 response should include an Operation-Location response header. severity: warn formats: ['oas2'] given: $.paths[*][*].responses[?(@property == '202')] then: function: has-header functionOptions: name: Operation-location az-lro-response-schema: description: A 202 response should include a schema for the operation status monitor. message: '{{error}}' severity: warn formats: ['oas2'] given: $.paths[*][*].responses[?(@property == '202')] then: function: lro-response-schema az-204-no-response-body: description: A 204 response should have no response body. severity: warn formats: ['oas2'] given: $.paths[*][*].responses.204 then: field: schema function: falsy az-ms-client-flatten: description: The use of x-ms-client-flatten extension is discouraged. severity: warn formats: ['oas2', 'oas3'] resolved: false given: $..x-ms-client-flatten then: function: undefined az-ms-enum-descriptions: description: Include descriptions for all values in the x-ms-enum extension. severity: warn formats: ['oas2', 'oas3'] given: $..x-ms-enum then: function: schema functionOptions: schema: type: object properties: values: type: array items: type: object required: ['value', 'description'] required: ['values'] az-ms-paths: description: Don't use x-ms-paths except where necessary to support legacy APIs. severity: warn formats: ['oas2', 'oas3'] given: $.x-ms-paths then: function: falsy az-nullable: description: Avoid the use of x-nullable. severity: warn formats: ['oas2', 'oas3'] resolved: false given: $..x-nullable then: function: undefined az-operation-id: description: OperationId should conform to Azure API Guidelines message: '{{error}}' severity: warn given: - $.paths.*[get,put,post,patch,delete,options,head] then: function: operation-id az-operation-security: description: Operation should have a security requirement or globally. message: Operation should have a security requirement. severity: warn formats: ['oas2', 'oas3'] given: $.paths.*[get,put,post,patch,delete,options,head] then: function: operation-security az-operation-summary-or-description: description: Operation should have a summary or description. message: Operation should have a summary or description. severity: warn given: - $.paths[*][?( @property === 'get' && !@.summary && !@.description )] - $.paths[*][?( @property === 'put' && !@.summary && !@.description )] - $.paths[*][?( @property === 'post' && !@.summary && !@.description )] - $.paths[*][?( @property === 'patch' && !@.summary && !@.description )] - $.paths[*][?( @property === 'delete' && !@.summary && !@.description )] - $.paths[*][?( @property === 'options' && !@.summary && !@.description )] - $.paths[*][?( @property === 'head' && !@.summary && !@.description )] - $.paths[*][?( @property === 'trace' && !@.summary && !@.description )] then: function: falsy az-pagination-parameters: description: Pagination parameters must conform to Azure guidelines. message: '{{error}}' severity: warn formats: ['oas2'] given: - $.paths.*[get,post] then: function: pagination-parameters az-pagination-response: description: An operation that returns a list that is potentially large should support pagination. message: '{{error}}' severity: warn formats: ['oas2'] given: - $.paths.*[get,post] then: function: pagination-response az-pageable-post: description: Post operations that specify x-ms-pageable are problematic. severity: info formats: ['oas2', 'oas3'] given: - $.paths.*[post] then: field: x-ms-pageable function: falsy az-parameter-default-not-allowed: description: A required parameter should not specify a default value. severity: warn # oas3 support has broken - restrict to oas2 for now formats: ['oas2'] given: - $.paths[*].parameters.[?(@.required)] - $.paths.*[get,put,post,patch,delete,options,head].parameters.[?(@.required)] then: field: default function: falsy az-parameter-description: description: All parameters should have a description. message: Parameter should have a description. severity: warn # In oas3 the description might be within the schema -- should not flag those formats: ['oas2'] given: - $.paths[*].parameters.* - $.paths.*[get,put,post,patch,delete,options,head].parameters.* then: field: description function: truthy az-parameter-names-convention: description: Parameter names should conform to Azure naming conventions. message: '{{error}}' severity: warn given: - $.paths[*].parameters.* - $.paths.*[get,put,post,patch,delete,options,head].parameters.* then: function: param-names az-parameter-names-unique: description: All parameter names for an operation should be case-insensitive unique. message: '{{error}}' severity: warn formats: ['oas2', 'oas3'] given: $.paths[*] then: function: param-names-unique az-parameter-order: description: Path parameters must be in the same order as in the path. message: '{{error}}' severity: warn formats: ['oas2', 'oas3'] given: $.paths then: function: param-order # Patch request body content type should be application/merge-patch+json az-patch-content-type: description: The request body content type for patch operations should be JSON merge patch. message: '{{error}}' severity: warn formats: ['oas2'] given: $ then: function: patch-content-type # Patch on a path that does not end in path parameter is uncommon. az-patch-path: description: Patch on a path that does not end with a path parameter is uncommon. severity: info formats: ['oas2', 'oas3'] given: $.paths[?(!@path.match(/\}']$/))] then: field: patch function: falsy # Static path segments should be kebab-case az-path-case-convention: description: Static path segments should be kebab-case. message: Static path segments should be kebab-case. severity: info formats: ['oas2', 'oas3'] given: $.paths.*~ then: function: pattern functionOptions: # Check each path segment individually and ignore param segments # Note: the ':' is only allowed in the final path segment match: '^(\/([a-z][a-z0-9-]+|{[^}]+}))*\/([a-z][a-z0-9-]+|{[^}]*})?(:[A-Za-z0-9]+)?$' # DO limit your URLs characters to 0-9 A-Z a-z - . _ ~ : az-path-characters: description: Path should contain only recommended characters. message: Path contains non-recommended characters. severity: info formats: ['oas2', 'oas3'] given: $.paths.*~ then: function: pattern functionOptions: # Check each path segment individually and ignore param segments # Note: the ':' is only allowed in the final path segment match: '^(\/([0-9A-Za-z._~-]+|{[^}]+}))*\/([0-9A-Za-z._~-]+|{[^}]*})?(:[0-9A-Za-z._~-]+)?$' az-path-parameter-names: description: Path parameter names should be consistent across all paths. message: '{{error}}' severity: warn formats: ['oas2', 'oas3'] given: $.paths then: function: path-param-names az-path-parameter-schema: description: 'Path parameter should be type: string and specify maxLength and pattern.' message: '{{error}}' severity: info formats: ['oas2', 'oas3'] given: - $.paths[*].parameters[?(@.in == 'path')] - $.paths[*][get,put,post,patch,delete,options,head].parameters[?(@.in == 'path')] then: function: path-param-schema az-post-201-response: description: Using post for a create operation is discouraged. message: Using post for a create operation is discouraged. severity: warn formats: ['oas2'] given: $.paths[*].post.responses then: field: '201' function: falsy az-property-default-not-allowed: description: A required property should not specify a default value. message: '{{error}}' severity: warn formats: ['oas2'] given: - $.paths[*].[put,post,patch].parameters.[?(@.in == 'body')].schema - $.paths[*].[get,put,post,patch,delete].responses[*].schema then: function: property-default-not-allowed az-property-description: description: All schema properties should have a description. message: Property should have a description. severity: warn resolved: false given: $..properties[?(@object() && @.$ref == undefined)] then: field: description function: truthy # https://github.com/microsoft/api-guidelines/blob/vNext/Guidelines.md#172-casing az-property-names-convention: description: Property names should be camel case. message: Property name should be camel case. severity: warn # This rule can report false positives if run on the resolved spec. # Issue: https://github.com/stoplightio/spectral/issues/1316 resolved: false given: $..[?(@.type === 'object' && @.properties)].properties.*~ then: function: casing functionOptions: type: camel az-property-type: description: All schema properties should have a defined type. message: Property should have a defined type. severity: warn resolved: false # Exclude properties that contains allOf or oneOf or anyOf to avoid false positives. given: $..properties[?(@object() && @.$ref == undefined && @.allOf == undefined && @.oneOf == undefined && @.anyOf == undefined)] then: field: type function: truthy az-put-path: description: Put on a path that does not end with a path parameter is uncommon. severity: info formats: ['oas2', 'oas3'] given: $.paths[*].put^~ then: function: pattern functionOptions: match: '/\}$/' az-put-request-and-response-body: description: A PUT operation should use the same schema for the request and response body. severity: info formats: ['oas2'] # Run on the unresolved document so that we compare the $ref'ed schema resolved: false given: $.paths[*].put then: function: put-request-and-response-body az-readonly-in-response-schema: description: Properties in response-only schemas should not be marked as readOnly true severity: warn formats: ['oas2'] given: $.definitions[*] then: function: readonly-in-response-schema az-request-body-not-allowed: description: A get or delete operation must not accept a body parameter. severity: error formats: ['oas2'] given: - $.paths[*].[get,delete].parameters[*] then: field: in function: pattern functionOptions: notMatch: '/^body$/' az-request-body-optional: description: Flag optional request body -- common oversight. message: The body parameter is not marked as required. severity: info formats: ['oas2'] given: # Don't flag request body if it explicitly specifies required: false - $.paths[*].[put,post,patch].parameters.[?(@.in == 'body' && @.required == undefined)] then: function: falsy az-request-body-type: description: Request body schema must not be a bare array. severity: warn formats: ['oas2'] given: - $.paths[*].[put,post,patch].parameters.[?(@.in == 'body')].schema then: field: type function: pattern functionOptions: notMatch: '/^array$/' az-response-body-type: description: Response body schema must not be a bare array. severity: warn formats: ['oas2', 'oas3'] given: $.paths[*][*][responses][*].schema then: field: type function: pattern functionOptions: notMatch: '/^array$/' az-schema-description-or-title: description: All schemas should have a description or title. message: Schema should have a description or title. severity: warn formats: ['oas2', 'oas3'] given: - $.definitions[?(!@.description && !@.title)] - $.components.schemas[?(!@.description && !@.title)] then: function: falsy az-schema-names-convention: description: Schema names should be Pascal case. message: Schema name should be Pascal case. severity: info formats: ['oas2'] given: $.definitions.*~ then: # Pascal case with optional "." separator function: pattern functionOptions: match: '^([A-Z][a-z0-9]+\.?)*[A-Z][a-z0-9]+$' az-schema-type-and-format: description: Schema should use well-defined type and format. message: '{{error}}' severity: warn formats: ['oas2'] given: - $.paths[*].[put,post,patch].parameters.[?(@.in == 'body')].schema - $.paths[*].[get,put,post,patch,delete].responses[*].schema then: function: schema-type-and-format az-security-definition-description: description: A security definition should have a description. message: Security definition should have a description. severity: warn formats: ['oas2', 'oas3'] given: - $.securityDefinitions[*] - $.components.securitySchemes[*] then: field: description function: truthy az-security-definitions: description: Security definitions must follow Azure conventions. message: '{{error}}' severity: warn formats: ['oas2'] given: $ then: function: security-definitions az-security-requirements: description: The security requirement should reference a defined security scheme. message: '{{error}}' severity: warn # Drop oas3 format for now formats: ['oas2'] given: - $.security - $.paths.*[get,put,post,patch,delete,options,head].security then: function: security-requirements az-security-min-length: description: Security property should specify at least one security requirement. severity: warn formats: ['oas2', 'oas3'] given: - $.security - $.paths.*[get,put,post,patch,delete,options,head].security then: function: length functionOptions: min: 1 # All success responses except 204 should define a response body # ref: https://github.com/microsoft/api-guidelines/blob/vNext/Guidelines.md#1321-put az-success-response-body: description: All success responses except 204 should define a response body. severity: warn formats: ['oas2'] # list http methods explicitly to exclude head # exclude 202 to avoid duplication with az-lro-response-schema rule given: $.paths[*][get,put,post,patch,delete].responses[?(@property >= 200 && @property < 300 && @property != '202' && @property != '204')] then: field: schema function: truthy az-unused-definition: description: Potentially unused definition has been detected. severity: warn formats: ['oas2'] resolved: false given: $.definitions then: function: unused-definition az-version-convention: description: API version should be a date in YYYY-MM-DD format, optionally suffixed with '-preview'. severity: error formats: ['oas2', 'oas3'] given: $.info.version then: function: pattern functionOptions: match: '^\d\d\d\d-\d\d-\d\d(-preview)?$' az-version-policy: description: Specify API version using `api-version` query parameter, not in path. message: '{{error}}' severity: warn formats: ['oas2'] given: $ then: function: version-policy