extends: - spectral:oas functions: [] rules: # --- Provider-required auth --- parseflow-uses-api-key-auth: description: "Every Parseflow OpenAPI must declare the X-API-Key apiKey security scheme." message: "Parseflow requires an `ApiKeyAuth` apiKey scheme named `X-API-Key` (in: header)." severity: error given: "$.components.securitySchemes" then: - field: ApiKeyAuth function: truthy - field: ApiKeyAuth.type function: pattern functionOptions: match: "^apiKey$" - field: ApiKeyAuth.in function: pattern functionOptions: match: "^header$" - field: ApiKeyAuth.name function: pattern functionOptions: match: "^X-API-Key$" parseflow-global-security-applied: description: "Root-level `security` must reference ApiKeyAuth." severity: error given: "$.security" then: function: schema functionOptions: schema: type: array minItems: 1 contains: type: object required: [ApiKeyAuth] # --- Path discipline: v2 namespace --- parseflow-paths-versioned: description: "All new (non-legacy, non-health, non-billing) operations must live under /v2." message: "Path `{{path}}` must be prefixed with `/v2` (legacy `/process`, `/pack`, `/health` exempt)." severity: warn given: "$.paths[?(@property != '/health' && @property != '/process' && @property != '/pack')]~" then: function: pattern functionOptions: match: "^/v2(/|$)" # --- Summary style: Title Case --- parseflow-summary-title-case: description: "Operation summaries must be Title Case." message: "Summary `{{value}}` must use Title Case (capitalize each significant word)." severity: warn given: "$.paths.*[get,post,put,patch,delete].summary" then: function: pattern functionOptions: match: "^([A-Z][a-zA-Z0-9]*)(\\s+(?:[A-Z][a-zA-Z0-9]*|V\\d+|[A-Z]{2,}))*$" parseflow-summary-required: description: "Every operation must declare a `summary`." severity: error given: "$.paths.*[get,post,put,patch,delete]" then: field: summary function: truthy parseflow-operation-id-required: description: "Every operation must declare an `operationId`." severity: error given: "$.paths.*[get,post,put,patch,delete]" then: field: operationId function: truthy parseflow-byok-headers-optional: description: "X-BYOK-Key, when present, must be an optional header parameter." severity: warn given: "$.paths.*[get,post,put,patch,delete].parameters[?(@.name == 'X-BYOK-Key')]" then: field: required function: falsy