extends: spectral:oas rules: runsignup-operation-id-required: description: All operations must have an operationId severity: error given: "$.paths[*][get,post,put,patch,delete]" then: field: operationId function: truthy runsignup-operation-id-camel-case: description: >- RunSignup operationIds use camelCase convention (e.g., getRaces, postRaceResults, getBibChipAssignments). This ensures consistent SDK method naming. severity: warn given: "$.paths[*][get,post,put,patch,delete].operationId" then: function: pattern functionOptions: match: "^[a-z][a-zA-Z0-9]+$" runsignup-tags-required: description: All operations must have at least one tag severity: error given: "$.paths[*][get,post,put,patch,delete]" then: field: tags function: truthy runsignup-tags-title-case: description: Tags must use Title Case (e.g., "Races", "Participants", "Results") severity: warn given: "$.paths[*][get,post,put,patch,delete].tags[*]" then: function: pattern functionOptions: match: "^[A-Z][a-zA-Z ]+$" runsignup-summary-required: description: All operations must have a summary severity: error given: "$.paths[*][get,post,put,patch,delete]" then: field: summary function: truthy runsignup-summary-title-case: description: >- Operation summaries must use Title Case to match RunSignup documentation conventions (e.g., "Get Races", "Post Race Results", "Get Bib and Chip Assignments"). severity: warn given: "$.paths[*][get,post,put,patch,delete].summary" then: function: pattern functionOptions: match: "^[A-Z][a-zA-Z0-9 ]+$" runsignup-description-required: description: All operations must have a description severity: warn given: "$.paths[*][get,post,put,patch,delete]" then: field: description function: truthy runsignup-race-id-path-param-required: description: >- All paths containing {race_id} must define the race_id parameter as required. RunSignup organizes all race-specific resources under the race_id path parameter. severity: error given: "$.paths[~/race_id~][*].parameters[?(@.name == 'race_id')]" then: field: required function: truthy runsignup-responses-must-include-401: description: Authenticated endpoints must document 401 Unauthorized response severity: warn given: "$.paths[*][get,post,put,patch,delete].responses" then: field: "401" function: truthy runsignup-get-must-return-200: description: GET operations must define a 200 success response severity: error given: "$.paths[*].get.responses" then: field: "200" function: truthy runsignup-post-must-return-200: description: POST operations must define a 200 success response severity: warn given: "$.paths[*].post.responses" then: field: "200" function: truthy runsignup-format-query-param: description: >- RunSignup API supports json and xml response formats via a ?format= query parameter. GET endpoints should document this parameter. severity: info given: "$.paths[*].get.parameters[?(@.name == 'format')].schema.enum" then: function: schema functionOptions: schema: type: array contains: const: "json" runsignup-pagination-params-consistent: description: >- RunSignup uses consistent pagination parameters: page (integer, default 1) and results_per_page (integer, max 1000). List endpoints should document these. severity: info given: "$.paths[*].get.parameters[?(@.name == 'page')].schema" then: field: type function: enumeration functionOptions: values: - integer runsignup-schema-properties-typed: description: All schema properties should define a type severity: warn given: "$.components.schemas[*].properties[*]" then: field: type function: truthy runsignup-path-uses-kebab-case: description: >- RunSignup API paths use snake_case and hyphens for resource names (e.g., /race/{race_id}/get-bib-chip, /delete-participants). Paths should not use camelCase segments. severity: info given: "$.paths" then: function: pattern functionOptions: notMatch: "[A-Z]" runsignup-servers-defined: description: At least one server must be defined severity: error given: "$" then: field: servers function: truthy