extends: - spectral:oas rules: paragon-info-title-prefix: description: All Paragon OpenAPI specs must have a title starting with "Paragon ". severity: error given: $.info.title then: function: pattern functionOptions: match: '^Paragon ' paragon-info-license-proprietary: description: License should be marked Proprietary, linking to Terms of Service. severity: warn given: $.info.license then: - field: name function: pattern functionOptions: match: '^Proprietary$' - field: url function: pattern functionOptions: match: '^https://www\.useparagon\.com/terms-of-service$' paragon-server-cloud: description: Spec must include the canonical Paragon cloud server URL. severity: error given: $.servers[*].url then: function: pattern functionOptions: match: '^https://[a-z\-]+\.useparagon\.com' paragon-operation-summary-prefix: description: Operation summaries must begin with "Paragon ". severity: warn given: $.paths.*[get,post,put,patch,delete].summary then: function: pattern functionOptions: match: '^Paragon ' paragon-operation-summary-title-case: description: Operation summaries must use Title Case (no all-lowercase tokens after the prefix). severity: warn given: $.paths.*[get,post,put,patch,delete].summary then: function: pattern functionOptions: match: '^Paragon ([A-Z][a-zA-Z0-9]*\s?)+$' paragon-bearer-auth: description: Paragon APIs authenticate via Bearer User Token (JWT). All paths must be secured. severity: error given: $.components.securitySchemes then: function: schema functionOptions: schema: type: object required: - bearerAuth paragon-operation-id-camel: description: operationId must be lowerCamelCase. severity: warn given: $.paths.*[get,post,put,patch,delete].operationId then: function: pattern functionOptions: match: '^[a-z][a-zA-Z0-9]*$' paragon-tag-title-case: description: Tags must use Title Case. severity: warn given: $.tags[*].name then: function: pattern functionOptions: match: '^([A-Z][a-zA-Z0-9]*)( [A-Z][a-zA-Z0-9]*)*$'