7shifts · API Governance Rules

7shifts API Rules

Spectral linting rules defining API design standards and conventions for 7shifts.

41 Rules error 10 warn 21 info 10
View Rules File View on GitHub

Rule Categories

delete get global info no openapi operation parameter path paths query request response schema security server servers tag

Rules

error
info-title-required
API must have a title.
$.info
warn
info-title-prefix
Title should start with "7shifts".
$.info.title
warn
info-description-required
API must have a non-trivial description.
$.info
error
info-version-required
API must declare a version.
$.info
info
info-contact-required
API should provide contact information.
$.info
warn
openapi-version-3-1
Specs should target OpenAPI 3.1.x.
$.openapi
error
servers-defined
At least one server must be defined.
$.servers
error
servers-https
Server URLs must use HTTPS.
$.servers[*].url
info
server-7shifts-host
Production server should be api.7shifts.com.
$.servers[*].url
warn
paths-version-prefix
Resource paths should be versioned under /v2 (OAuth token is the exception).
$.paths[?(@property != '/oauth2/token' && @property != '/whoami')]~
warn
paths-snake-or-kebab-case
Path segments must be snake_case or kebab-case (no camelCase or PascalCase).
$.paths[*]~
error
paths-no-trailing-slash
Paths must not end with a trailing slash.
$.paths[*]~
error
paths-no-query-string
Paths must not contain query strings.
$.paths[*]~
error
operation-operationid-required
Every operation must have an operationId.
$.paths[*][get,post,put,patch,delete]
warn
operation-operationid-camelcase-verb
operationId should be camelCase and begin with a verb (list/get/retrieve/create/update/delete/approve/decline).
$.paths[*][get,post,put,patch,delete].operationId
warn
operation-summary-required
Every operation must have a summary.
$.paths[*][get,post,put,patch,delete]
info
operation-summary-title-case
Operation summaries should be Title Case (each significant word capitalized).
$.paths[*][get,post,put,patch,delete].summary
warn
operation-tags-required
Every operation must be tagged.
$.paths[*][get,post,put,patch,delete]
info
global-tags-defined
A global tags array should be defined.
$
info
tag-description-required
Each global tag should have a description.
$.tags[*]
warn
tag-title-case
Tags should be Title Case.
$.tags[*].name
info
parameter-description-required
Parameters should have descriptions.
$..parameters[*]
warn
parameter-snake-case
Parameter names should be snake_case (filter bracket params like start[gte] permitted).
$..parameters[?(@.in=='query' || @.in=='path')].name
info
parameter-pagination-cursor
Collection pagination should use cursor and limit parameters.
$..parameters[?(@.in=='query')].name
warn
request-body-json
Request bodies should accept application/json.
$.paths[*][post,put,patch].requestBody.content
error
response-success-required
Every operation must define at least one 2xx response.
$.paths[*][get,post,put,patch,delete].responses
warn
response-description-required
Responses must have descriptions.
$.paths[*][*].responses[*]
info
response-auth-errors
Secured operations should document 401/403 responses.
$.paths[*][get,post,put,patch,delete]
warn
schema-property-snake-case
Schema properties should be snake_case.
$.components.schemas[*].properties[*]~
info
schema-title-required
Top-level schemas should declare a title.
$.components.schemas[*]
info
schema-types-defined
Schema properties should declare a type or $ref.
$.components.schemas[*].properties[*]
error
security-schemes-defined
Security schemes must be defined.
$.components.securitySchemes
warn
security-bearer-present
A bearer (access token) security scheme should be present.
$.components.securitySchemes
error
get-no-request-body
GET operations must not declare a request body.
$.paths[*].get
warn
delete-no-request-body
DELETE operations should not declare a request body.
$.paths[*].delete
warn
path-params-casing
Path parameters should be snake_case (the dominant convention in this API).
$.paths[*].parameters[?(@.in=='path')].name
warn
query-params-casing
Query parameters should be snake_case (the dominant convention in this API).
$.paths[*][get,post,put,patch,delete].parameters[?(@.in=='query')]
warn
schema-names-casing
Component schema names should be PascalCase (the dominant convention in this API).
$.components.schemas
warn
schema-properties-casing
Schema properties should be snake_case (the dominant convention in this API).
$.components.schemas[*].properties
warn
operation-security-required
Every operation should declare its security requirements.
$.paths[*][get,post,put,patch,delete]
warn
no-empty-descriptions
Descriptions must not be empty strings.
$..description

Spectral Ruleset

Raw ↑
# 7shifts — Spectral ruleset (strengthened)
# Plain Spectral. Existing hand-authored rules preserved; measured rules added
# from this provider's own OpenAPI conventions by strengthen_ruleset.py,
# then self-validated against the spec.
#
# Provenance:
#   - servers-https-only: 100% of servers already https (error)
#   - servers-expected-domain: 1/1 servers on 7shifts.com
#   - path-params-casing: snake @ 100% (n=39)
#   - query-params-casing: snake @ 92% (n=52)
#   - operationid-casing: camel @ 100% (n=33)
#   - schema-names-casing: pascal @ 100% (n=16)
#   - schema-properties-casing: snake @ 100% (n=127)
#   - operation-security-required: 32/33 ops declare per-op security
#   - pagination params observed: ['cursor', 'limit']
#   - merge: kept 35 existing, added 6 measured, upgraded 0
#   - added: path-params-casing, query-params-casing, schema-names-casing, schema-properties-casing, operation-security-required, no-empty-descriptions
extends:
  - spectral:oas
rules:
  info-title-required:
    description: API must have a title.
    given: $.info
    severity: error
    then:
      field: title
      function: truthy
  info-title-prefix:
    description: Title should start with "7shifts".
    given: $.info.title
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: ^7shifts
  info-description-required:
    description: API must have a non-trivial description.
    given: $.info
    severity: warn
    then:
      field: description
      function: truthy
  info-version-required:
    description: API must declare a version.
    given: $.info
    severity: error
    then:
      field: version
      function: truthy
  info-contact-required:
    description: API should provide contact information.
    given: $.info
    severity: info
    then:
      field: contact
      function: truthy
  openapi-version-3-1:
    description: Specs should target OpenAPI 3.1.x.
    given: $.openapi
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: ^3\.1\.
  servers-defined:
    description: At least one server must be defined.
    given: $.servers
    severity: error
    then:
      function: length
      functionOptions:
        min: 1
  servers-https:
    description: Server URLs must use HTTPS.
    given: $.servers[*].url
    severity: error
    then:
      function: pattern
      functionOptions:
        match: ^https://
  server-7shifts-host:
    description: Production server should be api.7shifts.com.
    given: $.servers[*].url
    severity: info
    then:
      function: pattern
      functionOptions:
        match: api\.7shifts\.com
  paths-version-prefix:
    description: Resource paths should be versioned under /v2 (OAuth token is the exception).
    given: $.paths[?(@property != '/oauth2/token' && @property != '/whoami')]~
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: ^/v2/
  paths-snake-or-kebab-case:
    description: Path segments must be snake_case or kebab-case (no camelCase or PascalCase).
    given: $.paths[*]~
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: ^(/[a-z0-9_\-]+|/\{[a-z0-9_]+\})*/?$
  paths-no-trailing-slash:
    description: Paths must not end with a trailing slash.
    given: $.paths[*]~
    severity: error
    then:
      function: pattern
      functionOptions:
        notMatch: .+/$
  paths-no-query-string:
    description: Paths must not contain query strings.
    given: $.paths[*]~
    severity: error
    then:
      function: pattern
      functionOptions:
        notMatch: \?
  operation-operationid-required:
    description: Every operation must have an operationId.
    given: $.paths[*][get,post,put,patch,delete]
    severity: error
    then:
      field: operationId
      function: truthy
  operation-operationid-camelcase-verb:
    description: operationId should be camelCase and begin with a verb (list/get/retrieve/create/update/delete/approve/decline).
    given: $.paths[*][get,post,put,patch,delete].operationId
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: ^(list|get|retrieve|create|update|put|delete|approve|decline|sync|test|configure|save|fetch|deactivate)[A-Za-z0-9]*$
  operation-summary-required:
    description: Every operation must have a summary.
    given: $.paths[*][get,post,put,patch,delete]
    severity: warn
    then:
      field: summary
      function: truthy
  operation-summary-title-case:
    description: Operation summaries should be Title Case (each significant word capitalized).
    given: $.paths[*][get,post,put,patch,delete].summary
    severity: info
    then:
      function: pattern
      functionOptions:
        match: ^[A-Z]
  operation-tags-required:
    description: Every operation must be tagged.
    given: $.paths[*][get,post,put,patch,delete]
    severity: warn
    then:
      field: tags
      function: truthy
  global-tags-defined:
    description: A global tags array should be defined.
    given: $
    severity: info
    then:
      field: tags
      function: truthy
  tag-description-required:
    description: Each global tag should have a description.
    given: $.tags[*]
    severity: info
    then:
      field: description
      function: truthy
  tag-title-case:
    description: Tags should be Title Case.
    given: $.tags[*].name
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: ^[A-Z][A-Za-z0-9]*( [A-Z][A-Za-z0-9]*)*$
  parameter-description-required:
    description: Parameters should have descriptions.
    given: $..parameters[*]
    severity: info
    then:
      field: description
      function: truthy
  parameter-snake-case:
    description: Parameter names should be snake_case (filter bracket params like start[gte] permitted).
    given: $..parameters[?(@.in=='query' || @.in=='path')].name
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: ^[a-z][a-z0-9_]*(\[[a-z]+\])?$
  parameter-pagination-cursor:
    description: Collection pagination should use cursor and limit parameters.
    given: $..parameters[?(@.in=='query')].name
    severity: info
    then:
      function: pattern
      functionOptions:
        match: .*
  request-body-json:
    description: Request bodies should accept application/json.
    given: $.paths[*][post,put,patch].requestBody.content
    severity: warn
    then:
      field: application/json
      function: truthy
  response-success-required:
    description: Every operation must define at least one 2xx response.
    given: $.paths[*][get,post,put,patch,delete].responses
    severity: error
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          patternProperties:
            ^2[0-9][0-9]$: {}
          minProperties: 1
  response-description-required:
    description: Responses must have descriptions.
    given: $.paths[*][*].responses[*]
    severity: warn
    then:
      field: description
      function: truthy
  response-auth-errors:
    description: Secured operations should document 401/403 responses.
    given: $.paths[*][get,post,put,patch,delete]
    severity: info
    then:
      function: defined
  schema-property-snake-case:
    description: Schema properties should be snake_case.
    given: $.components.schemas[*].properties[*]~
    severity: warn
    then:
      function: pattern
      functionOptions:
        match: ^[a-z][a-z0-9_]*$|^(in|out)$
  schema-title-required:
    description: Top-level schemas should declare a title.
    given: $.components.schemas[*]
    severity: info
    then:
      field: title
      function: truthy
  schema-types-defined:
    description: Schema properties should declare a type or $ref.
    given: $.components.schemas[*].properties[*]
    severity: info
    then:
      function: defined
  security-schemes-defined:
    description: Security schemes must be defined.
    given: $.components.securitySchemes
    severity: error
    then:
      function: truthy
  security-bearer-present:
    description: A bearer (access token) security scheme should be present.
    given: $.components.securitySchemes
    severity: warn
    then:
      field: bearerAuth
      function: truthy
  get-no-request-body:
    description: GET operations must not declare a request body.
    given: $.paths[*].get
    severity: error
    then:
      field: requestBody
      function: undefined
  delete-no-request-body:
    description: DELETE operations should not declare a request body.
    given: $.paths[*].delete
    severity: warn
    then:
      field: requestBody
      function: undefined
  path-params-casing:
    description: Path parameters should be snake_case (the dominant convention in this API).
    severity: warn
    given: $.paths[*].parameters[?(@.in=='path')].name
    then:
      function: casing
      functionOptions:
        type: snake
  query-params-casing:
    description: Query parameters should be snake_case (the dominant convention in this API).
    severity: warn
    given: $.paths[*][get,post,put,patch,delete].parameters[?(@.in=='query')]
    then:
      field: name
      function: casing
      functionOptions:
        type: snake
  schema-names-casing:
    description: Component schema names should be PascalCase (the dominant convention in this API).
    severity: warn
    given: $.components.schemas
    then:
      field: '@key'
      function: pattern
      functionOptions:
        match: ^[A-Z][A-Za-z0-9]*$
  schema-properties-casing:
    description: Schema properties should be snake_case (the dominant convention in this API).
    severity: warn
    given: $.components.schemas[*].properties
    then:
      field: '@key'
      function: casing
      functionOptions:
        type: snake
  operation-security-required:
    description: Every operation should declare its security requirements.
    severity: warn
    given: $.paths[*][get,post,put,patch,delete]
    then:
      field: security
      function: truthy
  no-empty-descriptions:
    description: Descriptions must not be empty strings.
    severity: warn
    given: $..description
    then:
      function: truthy