# Otter Public API — Spectral Ruleset # Generated by the API Evangelist profiling pipeline from openapi/otter-public-api-openapi.yml # Encodes the conventions observed in the Otter (TryOtter) Public API: # - OpenAPI 3.0.x # - OAuth 2.0 (client_credentials + authorization_code) bearer tokens # - camelCase operationIds, Title Case tags ("Orders Endpoints", "Menus Webhooks") # - versioned, kebab/lower path segments under /v1 and /manager/{domain}/v1 # - snake_case-leaning JSON schema properties, X-Store-Id / X-HMAC-SHA256 headers rules: # ── INFO / METADATA ───────────────────────────────────────────── info-title-required: description: API must declare an info.title. given: $.info severity: error then: field: title function: truthy info-description-required: description: API must have a meaningful info.description. given: $.info severity: warn then: field: description function: truthy info-contact-required: description: API must declare a maintainer contact. given: $.info severity: warn then: field: contact function: truthy info-version-required: description: API must declare info.version. given: $.info severity: error then: field: version function: truthy # ── OPENAPI VERSION ───────────────────────────────────────────── openapi-version-3: description: Specs should target OpenAPI 3.0.x as the Otter Public API does. given: $.openapi severity: warn then: function: pattern functionOptions: match: '^3\.0\.\d+$' # ── SERVERS ───────────────────────────────────────────────────── servers-defined: description: At least one server must be defined. given: $.servers severity: error then: function: truthy server-description-required: description: Each server should describe how its host is provisioned (Otter hosts are account-specific). given: $.servers[*] severity: warn then: field: description function: truthy # ── PATHS — NAMING CONVENTIONS ────────────────────────────────── path-no-trailing-slash: description: Paths must not end with a trailing slash. given: $.paths[*]~ severity: warn then: function: pattern functionOptions: notMatch: '.+/$' path-segments-lower: description: Static path segments use lower-case (camelCase placeholders like {orderId} are allowed). given: $.paths[*]~ severity: info then: function: pattern functionOptions: match: '^(/(v1|manager|[a-z0-9-]+|\{[A-Za-z0-9]+\}))+$' path-versioned: description: Otter Public API paths are versioned; expect a /v1 segment. given: $.paths[*]~ severity: info then: function: pattern functionOptions: match: 'v1' # ── OPERATIONS ────────────────────────────────────────────────── operation-operationid-required: description: Every operation must declare an operationId. given: $.paths[*][get,post,put,patch,delete] severity: error then: field: operationId function: truthy operation-operationid-camelcase: description: operationIds follow camelCase (createOrder, getManagerOrder). given: $.paths[*][get,post,put,patch,delete].operationId severity: warn then: function: pattern functionOptions: match: '^[a-z][a-zA-Z0-9]+$' operation-summary-required: description: Every operation must declare a summary. given: $.paths[*][get,post,put,patch,delete] severity: warn then: field: summary function: truthy operation-summary-otter-prefix: description: Operation summaries are prefixed with the provider name "Otter". given: $.paths[*][get,post,put,patch,delete].summary severity: info then: function: pattern functionOptions: match: '^Otter ' operation-tags-required: description: Every operation must be tagged. given: $.paths[*][get,post,put,patch,delete] severity: warn then: field: tags function: truthy # ── TAGS ──────────────────────────────────────────────────────── tag-title-case: description: Tags use Title Case with spaces (e.g. "Orders Endpoints", "Menus Webhooks"). given: $.paths[*][get,post,put,patch,delete].tags[*] severity: warn then: function: pattern functionOptions: match: '^[A-Z][A-Za-z]+( [A-Z][A-Za-z]+)*$' global-tags-described: description: Global tag definitions should carry a description. given: $.tags[*] severity: info then: field: description function: truthy # ── PARAMETERS ────────────────────────────────────────────────── parameter-description-required: description: Parameters should be described. given: $.paths[*][get,post,put,patch,delete].parameters[*] severity: info then: field: description function: truthy parameter-schema-required: description: Parameters must define a schema with a type. given: $.paths[*][get,post,put,patch,delete].parameters[?(@.in != 'body')] severity: warn then: field: schema function: truthy store-id-header-name: description: Store-scoped requests identify the store via the X-Store-Id header. given: $.paths[*][get,post,put,patch,delete].parameters[?(@.in=='header' && @.name)] severity: info then: field: name function: pattern functionOptions: match: '^(X-Store-Id|X-HMAC-SHA256|Authorization|[A-Za-z-]+)$' # ── REQUEST BODIES ────────────────────────────────────────────── request-body-json: description: Request bodies should offer application/json content. given: $.paths[*][post,put,patch].requestBody.content severity: info then: field: application/json function: truthy # ── RESPONSES ─────────────────────────────────────────────────── response-success-defined: description: Operations must define at least one 2xx response. given: $.paths[*][get,post,put,patch,delete].responses severity: warn then: function: schema functionOptions: schema: type: object patternProperties: '^2\d\d$': true minProperties: 1 response-description-required: description: Every response must have a description. given: $.paths[*][get,post,put,patch,delete].responses[*] severity: warn then: field: description function: truthy # ── SCHEMAS — PROPERTY NAMING ─────────────────────────────────── schema-type-defined: description: Component schemas should define a type or composition keyword. given: $.components.schemas[*] severity: info then: function: schema functionOptions: schema: anyOf: - required: [type] - required: [allOf] - required: [oneOf] - required: [anyOf] - required: [$ref] - required: [enum] # ── SECURITY ──────────────────────────────────────────────────── security-schemes-defined: description: Security schemes must be defined (Otter uses OAuth 2.0 bearer tokens). given: $.components.securitySchemes severity: error then: function: truthy security-oauth2-present: description: The OAuth2.0 security scheme should be present. given: $.components.securitySchemes severity: info then: field: OAuth2.0 function: truthy # ── HTTP METHOD CONVENTIONS ───────────────────────────────────── get-no-request-body: description: GET operations must not define a request body. given: $.paths[*].get severity: error then: field: requestBody function: falsy # ── GENERAL QUALITY ───────────────────────────────────────────── no-empty-description: description: Descriptions, where present, must not be empty. given: $..description severity: warn then: function: truthy microcks-operation-encouraged: description: Operations should carry x-microcks-operation for mock-server compatibility. given: $.paths[*][get,post,put,patch,delete] severity: info then: field: x-microcks-operation function: truthy