# Rackspace Technology — Spectral Ruleset # # Opinionated rules derived from the four Rackspace OpenAPI specs in this # repo (Cloud DNS, Cloud Identity, Customer Service, Offer). The rules # enforce conventions Rackspace docs and SDK code consistently use: # - X-Auth-Token-based authentication (Cloud Identity-issued tokens) # - kebab-case (or lowercase) path segments under tenant-scoped /{account} # - camelCase JSON property names (Java/Jackson convention) # - 202 Accepted for async DNS jobs, 200 for synchronous reads # - Title Case tag names extends: ["spectral:oas"] functions: [] rules: # --------------------------------------------------------------------- # INFO / METADATA # --------------------------------------------------------------------- rackspace-info-title: description: API title should begin with "Rackspace ". severity: error given: $.info then: field: title function: pattern functionOptions: match: "^Rackspace " rackspace-info-description-required: description: API description must be present and substantive (>= 80 chars). severity: error given: $.info then: field: description function: length functionOptions: min: 80 rackspace-info-version-required: description: API version is required. severity: error given: $.info then: field: version function: truthy rackspace-info-contact-required: description: Contact information should be provided. severity: warn given: $.info then: field: contact function: truthy rackspace-info-license-required: description: License should be provided (Apache 2.0 is standard for Rackspace OSS). severity: warn given: $.info then: field: license function: truthy # --------------------------------------------------------------------- # OPENAPI VERSION # --------------------------------------------------------------------- rackspace-openapi-version: description: Use OpenAPI 3.0.x. severity: error given: $ then: field: openapi function: pattern functionOptions: match: "^3\\.0\\." # --------------------------------------------------------------------- # SERVERS # --------------------------------------------------------------------- rackspace-servers-defined: description: At least one server must be defined. severity: error given: $ then: field: servers function: truthy rackspace-servers-https: description: All server URLs must use HTTPS. severity: error given: $.servers[*] then: field: url function: pattern functionOptions: match: "^https://" rackspace-servers-rackspacecloud: description: Production servers should be hosted under the rackspacecloud.com or rackspace.com domains. severity: warn given: $.servers[*] then: field: url function: pattern functionOptions: match: "(rackspacecloud\\.com|rackspace\\.com)" # --------------------------------------------------------------------- # PATHS — NAMING CONVENTIONS # --------------------------------------------------------------------- rackspace-paths-no-trailing-slash: description: Paths must not end with a trailing slash. severity: error given: $.paths then: function: pattern functionOptions: notMatch: "/$" field: "@key" rackspace-paths-kebab-or-lowercase: description: Path segments should be lowercase, kebab-case, or camelCase identifiers (no UPPER_SNAKE_CASE except curly-brace path params). severity: warn given: $.paths then: function: pattern functionOptions: match: "^(/[a-z0-9][a-zA-Z0-9_\\-:.]*|/\\{[a-zA-Z0-9_]+\\}|/v[0-9]+(\\.[0-9]+)?)+$" field: "@key" # --------------------------------------------------------------------- # OPERATIONS # --------------------------------------------------------------------- rackspace-operation-id-required: description: Every operation must have an operationId. severity: error given: $.paths[*][get,post,put,patch,delete,options,head] then: field: operationId function: truthy rackspace-operation-id-camelcase: description: operationId must use camelCase (verb prefix preferred — get/list/show/create/update/delete/add). severity: error given: $.paths[*][get,post,put,patch,delete,options,head] then: field: operationId function: pattern functionOptions: match: "^[a-z][a-zA-Z0-9]+$" rackspace-operation-summary-required: description: Every operation must have a summary. severity: error given: $.paths[*][get,post,put,patch,delete,options,head] then: field: summary function: truthy rackspace-operation-summary-title-case: description: Operation summaries should use Title Case (each major word capitalized). severity: warn given: $.paths[*][get,post,put,patch,delete,options,head] then: field: summary function: pattern functionOptions: match: "^[A-Z][A-Za-z0-9]*([ \\-/][A-Z0-9][A-Za-z0-9]*)*$" rackspace-operation-description-required: description: Every operation must have a description. severity: warn given: $.paths[*][get,post,put,patch,delete,options,head] then: field: description function: truthy rackspace-operation-tags-required: description: Every operation must have at least one tag. severity: error given: $.paths[*][get,post,put,patch,delete,options,head] then: field: tags function: schema functionOptions: schema: type: array minItems: 1 # --------------------------------------------------------------------- # TAGS # --------------------------------------------------------------------- rackspace-tags-defined: description: Tags must be declared at the root level. severity: warn given: $ then: field: tags function: truthy rackspace-tags-pascal-case: description: Tag names should be PascalCase or Title Case (e.g. CustomerAccounts, Reverse DNS). severity: warn given: $.tags[*] then: field: name function: pattern functionOptions: match: "^[A-Z][A-Za-z0-9]*( [A-Z][A-Za-z0-9]*)*$" # --------------------------------------------------------------------- # PARAMETERS # --------------------------------------------------------------------- rackspace-parameter-description-required: description: All parameters must have a description. severity: warn given: $..parameters[?(@.in)] then: field: description function: truthy rackspace-parameter-schema-required: description: All parameters must have a schema. severity: error given: $..parameters[?(@.in)] then: field: schema function: truthy rackspace-parameter-camelcase: description: Parameter names should be camelCase (Rackspace convention). severity: warn given: $..parameters[?(@.in == 'query' || @.in == 'header')] then: field: name function: pattern functionOptions: match: "^[a-zA-Z][a-zA-Z0-9_\\-]*$" rackspace-pagination-limit-offset: description: Pagination should use limit + offset (Cloud DNS, Identity) or limit + marker (Offer API). severity: hint given: $.paths[*][get].parameters[?(@.in == 'query')] then: field: name function: enumeration functionOptions: values: [limit, offset, marker, name, type, data, status, lineOfBusiness, apply_rcn_roles, include_endpoints, include_accessible_domains, belongsTo, showRecords, showSubdomains, deleteSubdomains, changes, cloneName, cloneSubdomains, modifyRecordData, modifyEmailAddress, modifyComment, href, ip, id, key, offeringCode, offeringVersion] # --------------------------------------------------------------------- # RESPONSES # --------------------------------------------------------------------- rackspace-response-description-required: description: Every response object must have a description. severity: error given: $.paths[*][*].responses[*] then: field: description function: truthy rackspace-response-success-required: description: Every operation must declare a 2xx success response. severity: error given: $.paths[*][get,post,put,patch,delete] then: field: responses function: schema functionOptions: schema: type: object patternProperties: "^2[0-9][0-9]$": {} minProperties: 1 rackspace-response-error-401: description: Tenant-scoped operations should declare a 401 Unauthorized response. severity: warn given: $.paths[?(@property.match(/\\{account\\}|\\{tenantId\\}/))][get,post,put,patch,delete].responses then: field: "401" function: truthy rackspace-response-async-job-202: description: Mutating Cloud DNS operations should return 202 Accepted (async job pattern). severity: warn given: $.paths[?(@property.match(/dns|domains/))][post,put,delete].responses then: field: "202" function: truthy # --------------------------------------------------------------------- # SCHEMAS — PROPERTY NAMING # --------------------------------------------------------------------- rackspace-schema-property-camelcase: description: JSON properties should be camelCase (Rackspace Java/Jackson convention). severity: warn given: $.components.schemas[*].properties then: function: pattern functionOptions: match: "^[a-z][a-zA-Z0-9_\\-]*$|^RAX-AUTH:[a-zA-Z]+$|^OS-KSADM:[a-zA-Z]+$|^RAX-KSKEY:[a-zA-Z]+$" field: "@key" rackspace-schema-types-defined: description: Schema properties must declare a type or $ref. severity: warn given: $.components.schemas[*].properties[*] then: function: schema functionOptions: schema: oneOf: - required: [type] - required: [$ref] - required: [allOf] - required: [oneOf] - required: [anyOf] - required: [enum] - required: [additionalProperties] # --------------------------------------------------------------------- # SECURITY # --------------------------------------------------------------------- rackspace-security-global: description: Global security must be defined. severity: error given: $ then: field: security function: truthy rackspace-security-x-auth-token: description: Rackspace APIs use the X-Auth-Token header (Cloud Identity-issued bearer token). severity: warn given: $.components.securitySchemes[*] then: function: schema functionOptions: schema: type: object properties: type: { const: apiKey } in: { const: header } name: { const: X-Auth-Token } required: [type, in, name] # --------------------------------------------------------------------- # HTTP METHOD CONVENTIONS # --------------------------------------------------------------------- rackspace-get-no-request-body: description: GET operations must not have a requestBody. severity: error given: $.paths[*].get then: field: requestBody function: falsy rackspace-delete-no-request-body: description: DELETE operations should not have a requestBody (use query parameters). severity: warn given: $.paths[*].delete then: field: requestBody function: falsy # --------------------------------------------------------------------- # GENERAL QUALITY # --------------------------------------------------------------------- rackspace-microcks-extension: description: Operations should include x-microcks-operation for mock dispatching. severity: hint given: $.paths[*][get,post,put,patch,delete] then: field: x-microcks-operation function: truthy