/spectral-ruleset

Custom Spectral API Linter ruleset for Zalando RESTful API Guidelines.

Primary LanguageTypeScriptApache License 2.0Apache-2.0

Gitpod

spectral-ruleset

👷🚧🛠️ in development 👷🚧🛠️

Custom Spectral API Linter ruleset for Zalando RESTful API Guidelines.

There are two flavors of the ruleset:

Please refer to the table below for details.

Use it

Possibility A: Reference via Github URL

# zalando flavor:
npx @stoplight/spectral lint \
    --ruleset https://raw.githubusercontent.com/baloise-incubator/spectral-ruleset/main/zalando.yml \
    example/example-openapi.yml

# baloise flavor:
npx @stoplight/spectral lint \
    --ruleset https://raw.githubusercontent.com/baloise-incubator/spectral-ruleset/main/baloise.yml \
    example/example-openapi.yml

Or just create a .spectral.yml extending it

echo "extends: [https://raw.githubusercontent.com/baloise-incubator/spectral-ruleset/main/baloise.yml]" \
    > .spectral.yml
npx @stoplight/spectral lint example/example-openapi.yml

If you're behind a proxy you can pass it via PROXY environment variable:

PROXY=<PROXY URL> npx @stoplight/spectral lint <...>

Possibility B: Install via npm

npm i @baloise/spectral-rules

# zalando flavor:
npx @stoplight/spectral lint \
    --ruleset ./node_modules/@baloise/spectral-rules/zalando.yml \
    example/example-openapi.yml

# baloise flavor:
npx @stoplight/spectral lint \
    --ruleset ./node_modules/@baloise/spectral-rules/baloise.yml \
    example/example-openapi.yml

Or just create a .spectral.yml extending it

echo "extends: [./node_modules/@baloise/spectral-rules/baloise.yml]" > .spectral.yml
npx @stoplight/spectral lint example/example-openapi.yml

Development

Adding a new Rule

  1. Choose a new, unsupported rule from the table below. For example #151 MUST specify success and error responses.
  2. Make sure tests/fixtures/base-openapi.yml satisfies the rule.
  3. Add a test tests/151-MUST-specify-success-and-error-responses.test.ts that
    1. Takes the base-openapi.yaml as input
    2. Modifies it to break the new rule
    3. Expect that spectral finds the error (this will fail for now)
  4. Extend zalando.yml with the new rule, so that the previously added test succeeds. See https://meta.stoplight.io/docs/spectral/docs/guides/4-custom-rulesets.md on how to define custom rules.
  5. Add a ✔️ to the table below.
  6. Create a PR

Alternative baloise rules are marked by appending the rule number with an a. For example zalando rule #115 versus baloise rule #115a. The zalando rule #115 is defined in zalando.yml. The baloise rule #115a is defined in baloise.yml while deactivating the original zalando rule #115a.

Setup

npm install
npm run test
npm run lint
npm run lint-fix # format source files

Currently supported rules from the zalando restful-api-guidelines

✔️ = rule implemented
❕ = rule implementation not possible or to complex

id title zalando.yml baloise.yml prio (A, B, C)
#100 MUST follow API first principle B
#101 MUST provide API specification using OpenAPI A
#102 SHOULD provide API user manual - - C
#103 MUST write APIs using U.S. English A
#104 MUST secure endpoints with OAuth 2.0 - - B
#105 MUST define and assign permissions (scopes) - - B
#106 MUST not break backward compatibility - - B
#107 SHOULD prefer compatible extensions -
#108 MUST prepare clients accept compatible API extensions C
#109 SHOULD design APIs conservatively -
#110 MUST always return JSON objects as top-level data structures ✔️ ✔️ A
#111 MUST treat Open API specification as open for extension by default -
#112 SHOULD used open-ended list of values (x-extensible-enum) for enumerations ✔️ ✔️ -
#113 SHOULD avoid versioning B
#114 MUST use media type versioning -
#115 MUST not use URI versioning ✔️ - A
#115a CAN use correct URI versioning: ^((?!.*\/v\d+(\/.*)?\/v\d+)\/.*)$ - ✔️ A
#116 MUST use semantic versioning ✔️ ✔️ B
#118 MUST property names must be ASCII snake_case (and never camelCase): ^[a-z_][a-z_0-9]*$ ✔️ - A
#118a MUST property names must be ASCII camelCase: ^[a-z]+((\d)([A-Z0-9][a-z0-9]+))*([A-Z])?$ - ✔️ A
#120 SHOULD pluralize array names - - B
#122 MUST not use null for boolean properties -
#123 MUST use same semantics for null and absent properties -
#124 SHOULD not use null for empty arrays -
#125 SHOULD represent enumerations as strings - - ?
#126 SHOULD define dates properties compliant with RFC 3339 - - ?
#127 SHOULD define time durations and intervals properties conform to ISO 8601 -
#128 SHOULD use standards for country, language and currency codes - - ?
#129 MUST use lowercase separate words with hyphens for path segments ✔️ ✔️ A
#130 MUST use snake_case (never camelCase) for query parameters ✔️ - B
#130a MUST use camelCase (never snake_case) for query parameters - ✔️ B
#132 SHOULD prefer hyphenated-pascal-case for HTTP header fields ✔️ ✔️ B
#133 MAY use standardized headers - - -
#134 MUST pluralize resource names - - A
#135 SHOULD not use /api as base path ✔️ ✔️ A
#136 MUST use normalized paths without empty path segments and trailing slashes ✔️ ✔️ B
#137 MUST stick to conventional query parameters -
#138 MUST avoid actions — think about resources A
#139 SHOULD model complete business processes -
#140 SHOULD define useful resources -
#141 MUST keep URLs verb-free A
#142 MUST use domain-specific resource names -
#143 MUST identify resources and sub-resources via path segments - - -
#144 SHOULD only use UUIDs if necessary -
#145 MAY consider using (non-)nested URLs -
#146 SHOULD limit number of resource types ✔️ ✔️ B
#147 SHOULD limit number of sub-resource levels ✔️ ✔️ B
#148 MUST use HTTP methods correctly A
#149 MUST fulfill common method properties -
#150 MUST use standard HTTP status codes ✔️ -
#150a MUST use additional standard HTTP status codes - ✔️ -
#151 MUST specify success and error responses ✔️ ✔️ B
#152 MUST use code 207 for batch or bulk requests C
#153 MUST use code 429 with headers for rate limits C
#154 MUST define collection format of header and query parameters -
#155 SHOULD reduce bandwidth needs and improve responsiveness -
#156 SHOULD use gzip compression -
#157 SHOULD support partial responses via filtering -
#158 SHOULD allow optional embedding of sub-resources -
#159 MUST support pagination - - -
#160 SHOULD prefer cursor-based pagination, avoid offset-based pagination - - -
#161 SHOULD use pagination links where applicable - - -
#162 MUST use REST maturity level 2 - - -
#163 MAY use REST maturity level 3 - HATEOAS - - -
#164 MUST use common hypertext controls - - -
#165 SHOULD use simple hypertext controls for pagination and self-references - - -
#166 MUST not use link headers with JSON entities - - -
#167 MUST use JSON to encode structured data - - -
#168 MAY use non JSON media types for binary data or alternative content representations -
#169 MUST use standard date and time formats A
#170 SHOULD use standards for country, language and currency codes - - B
#171 MUST define format for number and integer types ✔️ - -
#172 SHOULD prefer standard media type name application/json ✔️ ✔️ B
#173 MUST use the common money object -
#174 MUST use common field names and semantics -
#176 MUST support problem JSON ✔️ ✔️ -
#177 MUST not expose stack traces -
#178 MUST use Content-* headers correctly -
#179 MAY use Content-Location header -
#180 SHOULD use Location header instead of Content-Location header - - -
#181 MAY consider to support Prefer header to handle processing preferences -
#182 MAY consider to support ETag together with If-Match/If-None-Match header -
#183 SHOULD use only the specified proprietary Zalando headers - - -
#184 MUST propagate proprietary headers - - -
#185 MUST obtain approval of clients before API shut down -
#186 MUST collect external partner consent on deprecation time span -
#187 MUST reflect deprecation in API specifications -
#188 MUST monitor usage of deprecated API scheduled for sunset -
#189 SHOULD add Deprecation and Sunset header to responses -
#190 SHOULD add monitoring for Deprecation and Sunset header -
#191 MUST not start using deprecated APIs B
#192 MUST publish Open API specification A
#193 SHOULD monitor API usage -
#194 MUST treat events as part of the service interface - - -
#195 MUST make event schema available for review - - -
#196 MUST ensure event schema conforms to Open API schema object - - -
#197 MUST ensure that events are registered as event types - - -
#198 MUST ensure that events conform to a well-known event category - - -
#199 MUST ensure that events define useful business resources - - -
#200 MUST ensure that events do not provide sensitive data - - -
#201 MUST use the general event category to signal steps and arrival points in business processes - - -
#202 MUST use data change events to signal mutations - - -
#203 SHOULD provide means for explicit event ordering - - -
#204 SHOULD use the hash partition strategy for data change events - - -
#205 SHOULD ensure that data change events match the APIs resources - - -
#207 MUST indicate ownership of event types - - -
#208 MUST define event payloads compliant with overall API guidelines - - -
#209 MUST maintain backwards compatibility for events - - -
#210 SHOULD avoid additionalProperties in event type definitions - - -
#211 MUST use unique event identifiers - - -
#212 SHOULD design for idempotent out-of-order processing - - -
#213 MUST follow naming convention for event type names - - -
#214 MUST prepare event consumers for duplicate events - - -
#215 MUST provide API identifiers ✔️ ✔️ -
#216 SHOULD define maps using additionalProperties - - -
#217 MUST use full, absolute URI - - -
#218 MUST contain API meta information ✔️ ✔️ -
#219 MUST provide API audience ✔️ - -
#219a MUST provide baloise API audience - ✔️ -
#220 MUST use most specific HTTP status codes -
#223 MUST-SHOULD use functional naming schema -
#224 MUST follow naming convention for hostnames -
#225 MUST follow naming convention for permissions (scopes) -
#226 MUST document implicit filtering -
#227 MUST document cachable GET, HEAD, and POST endpoints -
#228 MUST use URL-friendly resource identifiers: [a-zA-Z0-9:._-/]* A
#229 SHOULD consider to design POST and PATCH idempotent -
#230 MAY consider to support Idempotency-Key header -
#231 Should use secondary key for idempotent POST design -
#233a MUST request must use b3 tracing headers - ✔️ -
#234 MUST only use durable and immutable remote references -
#235 SHOULD name date/time properties with _at suffix - - -
#236 SHOULD design simple query languages using query parameters -
#237 SHOULD design complex query languages using JSON -
#238 SHOULD use standardized property formats -
#239 SHOULD encode embedded binary data in base64url -
#240 SHOULD declare enum values using UPPER_SNAKE_CASE format ✔️ ✔️ -
#241 MAY expose compound keys as resource identifiers -