Linters
Linters are also called Linter Fuzzers.
Usually a good OpenAPI contract must follow several good practices in order to make it easy digestible by the service clients and act as much as possible as self-sufficient documentation:
- follow good and consistent practices for naming the contract elements like paths, query params, headers, requests, responses
- always use plural for the resources
- provide tags for all operations in order to avoid breaking code generation on some languages and have a logical grouping of the API operations
- provide good description for all paths, methods and request/response elements
- provide meaningful responses for
POST,PATCHandPUTrequests - provide examples for all requests/response elements
- provide structural constraints for (ideally) all request/response properties (min, max, regex)
- have some sort of
CorrelationIds/TraceIdsheaders for traceability - have at least a security schema in place
- avoid having the API version part of the paths
- document response codes for both "happy" and "unhappy" flows
- avoid using
xmlpayload unless there is a really good reason (like documenting an old API for example) - json types and properties do not use the same naming (like having a
Petwith a property namedpet)
CATS has currently 58 registered Linter Fuzzers or Linters. The names below
match the current output of cats list --linters:
ArraySchemaLimitGlobalLinter- verifies that all global array schemas specify maxItemsArraySchemaLimitPathLevelLinter- verifies that array schemas specify maxItems for inline schemas of the current path/methodArrayWithoutItemsLinter- detects array schemas that do not define anitemspropertyAuthResponseCodesConsistencyLinter- verifies that secured operations document 401/403 error responses and public operations opting out of security (security: []) do not document 401CollectionPaginationLinter- verifies that collection GET operations support paginationContradictorySchemaConstraintsLinter- detects contradictory or invalid schema constraints (min > max bounds, invalid regex patterns, undeclared required fields, and invalid enum defaults/examples)DeleteHasBodyLinter- checks if DELETE methods have a bodyEmptyPathsLinter- verifies that each path contains at least one operationEmptyRequestSchemaLinter- detects request schemas without properties, references, or compositionEmptyResponseSchemaLinter- detects response schemas without properties, references, or compositionEnumCaseGlobalLinter- verifies consistent casing for string enum values across the contractEnumCasePathLevelLinter- verifies enum casing for inline path-level schemasErrorResponseConsistencyLinter- verifies that 4xx and 5xx error responses across the contract share a consistent structured error schemaGetHasBodyLinter- checks if GET methods have a bodyHeadHasBodyLinter- checks if HEAD methods have a bodyHeadersCaseLinter- verifies that HTTP headers follow naming conventionsHttpMethodConsistencyLinter- flags missing REST HTTP methods (POST on collection paths and GET, PUT/PATCH, DELETE on item paths) across resource groupsHttpStatusCodeInRangeLinter- verifies that response codes are between 100 and 599JsonObjectsCaseLinter- verifies that JSON elements follow naming conventionsMissingOperationMetadataLinter- verifies that every operation defines a non-blank operationId and at least one of summary or descriptionMultipleSuccessCodesLinter- flags operations with multiple 2xx response codesNumericSchemaBoundsGlobalLinter- verifies that all global numeric schemas specify minimum and maximum bounds or enumNumericSchemaBoundsPathLevelLinter- verifies that numeric schemas specify minimum and maximum bounds or enum for inline schemas of the current path/methodOneOfAmbiguousVariantsLinter- detects oneOf schemas without a discriminator where one variant accepts every instance of another variant, making payloads match more than one variantOperationIdVerbPrefixLinter- verifies operationId prefixes for HTTP methodsPaginationConsistencyLinter- verifies that paginated GET operations across the contract use consistent pagination parameter names and return pagination metadata rather than a bare arrayPatchWithoutBodyLinter- verifies that PATCH operations define a request bodyPathCaseLinter- verifies that path elements follow naming conventionsPathNounsLinter- verifies that path elements use nouns and custom action segments are terminal and nested under a resourcePathParameterDeclarationLinter- verifies that URL path template variables ({param}) match declaredin: pathparameters and haverequired: truePathPluralsLinter- verifies plural collection resource names while allowing singular singletons and terminal custom operationsPathTagsLinter- verifies path tags and top-level tag consistencyPathVariableConsistencyLinter- verifies that path variables use consistent names per resource segment and consistent schema types/formats across all operationsPolymorphismDiscriminatorLinter- validates that oneOf/anyOf discriminator definitions specify a non-blank propertyName present in sub-schemas and valid mapping referencesPostWithoutBodyLinter- verifies that POST operations define a request bodyPropertySemanticsConsistencyLinter- verifies that audit timestamp properties share a consistent type/format across schemas and flags floating-point monetary fieldsPutWithoutBodyLinter- verifies that PUT operations define a request bodyQueryParamsCaseLinter- verifies that query parameters follow naming conventionsRecommendedHttpCodesLinter- verifies recommended response codesResourceSchemaSymmetryLinter- verifies that properties shared between write request schemas (POST/PUT/PATCH) and GET response schemas within a resource group have consistent types and formatsResponsesWithBodiesLinter- verifies response bodies are present except for 204 and 304SchemaValueConformanceLinter- detects default and example values that violate the type, format, length, range, pattern or item constraints of their own schemaSecuritySchemesLinter- verifies valid security schemes are configuredSensitiveDataInQueryLinter- flags query parameters whose names indicate credentials, secrets, or sensitive PII (such as password, secret, apiKey, accessToken, ssn, cvv, cardNumber)StringSchemaLimitGlobalLinter- verifies string schemas havemaxLengthorenumStringSchemaPathLevelLinter- verifies limits for inline path-level string schemasTopLevelElementsLinter- verifies meaningful contract-level metadataTracingHeadersLinter- verifies recommended tracing headersUnconstrainedAdditionalPropertiesLinter- flags request body object schemas that explicitly allow unconstrained additionalProperties (true or an untyped free-form schema)UniqueOperationIdsLinter- verifies that operationIds are uniqueUnusedExamplesLinter- flags unreferenced component examplesUnusedHeadersLinter- flags unreferenced component headersUnusedParametersLinter- flags unreferenced component parametersUnusedRequestBodiesLinter- flags unreferenced component request bodiesUnusedResponsesLinter- flags unreferenced component responsesUnusedSchemasLinter- flags unreferenced component schemasVersionsLinter- verifies that paths do not contain versioning informationXmlContentTypeLinter- verifies that requests and responses do not offerapplication/xml
You can run only these Fuzzers using cats lint --contract=CONTRACT.
Filtering and Strict Mode in cats lint
cats lint supports granular filtering and strictness flags:
--linters=NAME,...(--linter): Run only matching linters (full or partial names).--skipLinters=NAME,...(--skipLinter): Skip matching linters globally, or scope skips to specific paths/wildcards using/path=Linter1;Linter2or/api/me/*=PathPluralsLinter.--skipLintersForExtension=x-ext=val:Linter1,Linter2: Skip specific linters on endpoints matching an OpenAPIx-*extension.-p, --paths=PATH,...and--skipPaths=PATH,...: Include or skip paths (supports wildcards like/api/*).-t, --tags=TAG,...and--skipTags=TAG,...: Include or skip OpenAPI tags.--operationIds=ID,...and--skipOperationIds=ID,...: Include or skip specific operationIds.-X, --httpMethods=METHOD,...and--skipHttpMethods=METHOD,...: Include or skip HTTP methods.--skipDeprecatedOperations: Skip linting deprecated operations.--strict: Escalates all linter warnings to errors.
Naming conventions can be configured using the following arguments:
--headersNaming=<headersNaming>Naming strategy for HTTP headers. Possible valuesSNAKE, KEBAB, PASCAL, CAMEL, HTTP_HEADER, UPPER_UNDERSCORE, LOWER_UNDERSCORE. Default:HTTP_HEADER--jsonObjectsNaming=<jsonObjectsNaming>Naming strategy for json objects. Default:PASCAL--jsonPropertiesNaming=<jsonPropertiesNaming>Naming strategy for json object properties. Default:CAMEL--pathNaming=<pathNaming>Naming strategy for paths (excluding path variables). Default:KEBAB--pathVariablesNaming=<pathVariablesNaming>Naming strategy for path variables. Default:CAMEL--queryParamsNaming=<queryParamsNaming>Naming strategy for query parameters. Default:SNAKE--enumsNaming=<enumsNaming>Naming strategy for enums. Default:UPPER_UNDERSCORE--operationPrefixMapFile=FILECustom properties file mapping HTTP verbs to allowedoperationIdverb prefixes.
Linter Fuzzers are disabled by default. You must either use the cats lint ... command to run only the linters or
the --includeLinters argument to run them along other Fuzzers.
📄️ Empty Paths
| Item | Description |
📄️ Headers Case
| Item | Description |
📄️ Json Objects Case
| Item | Description |
📄️ Path Case
| Item | Description |
📄️ Path Nouns
| Item | Description |
📄️ Path Plural
| Item | Description |
📄️ Path Tags
| Item | Description |
📄️ Query Params Case
| Item | Description |
📄️ Recommended HTTP Codes
| Item | Description |
📄️ Tracing Headers
| Item | Description |
📄️ Security Schemes
| Item | Description |
📄️ HTTP Status Code In Valid Range
| Item | Description |
📄️ Top Level Elements
| Item | Description |
📄️ Tracing Headers
| Item | Description |
📄️ Unique Operations
| Item | Description |
📄️ Versions
| Item | Description |
📄️ XML Content Type
| Item | Description |