# Spectral ruleset for the Edamam API surface. # # Generated by analyzing the Edamam OpenAPI specifications in openapi/: # - edamam-nutrition-analysis-api-openapi.yml # - edamam-food-and-grocery-database-api-openapi.yml # - edamam-recipe-search-api-openapi.yml # - edamam-meal-planner-api-openapi.yml # # These rules codify Edamam's observed conventions: OpenAPI 3.1, HTTPS # api.edamam.com server, kebab-case versioned paths (/api/.../v2/...), # camelCase operationIds and schema properties, Title Case tags, operation # summaries prefixed with "Edamam", and app_id/app_key credential auth. rules: # ── INFO / METADATA ────────────────────────────────────────────── info-title-required: description: The API must have a title. severity: error given: $.info then: field: title function: truthy info-title-edamam-prefix: description: API title should start with "Edamam". severity: warn given: $.info.title then: function: pattern functionOptions: match: '^Edamam' info-description-required: description: The API must have a meaningful description. severity: warn given: $.info then: field: description function: truthy info-description-min-length: description: The API description should be at least 40 characters. severity: info given: $.info.description then: function: length functionOptions: min: 40 info-version-required: description: The API must declare a version. severity: error given: $.info then: field: version function: truthy info-contact-required: description: The API should declare contact information. severity: info given: $.info then: field: contact function: truthy # ── OPENAPI VERSION ────────────────────────────────────────────── openapi-version-3-1: description: Edamam specs target OpenAPI 3.1.x. severity: warn given: $.openapi then: function: pattern functionOptions: match: '^3\.1\.' # ── SERVERS ────────────────────────────────────────────────────── servers-defined: description: At least one server must be defined. severity: error given: $.servers then: function: length functionOptions: min: 1 servers-https-only: description: Servers must use HTTPS. severity: error given: $.servers[*].url then: function: pattern functionOptions: match: '^https://' servers-edamam-host: description: Production server should be api.edamam.com. severity: info given: $.servers[*].url then: function: pattern functionOptions: match: 'api\.edamam\.com' servers-description: description: Each server should have a description. severity: info given: $.servers[*] then: field: description function: truthy # ── PATHS — NAMING CONVENTIONS ─────────────────────────────────── paths-no-trailing-slash: description: Paths must not end with a trailing slash. severity: warn given: $.paths[*]~ then: function: pattern functionOptions: notMatch: '.+/$' paths-kebab-case: description: Path segments should be lowercase kebab-case (allowing version tokens like v2 and {param} placeholders). severity: warn given: $.paths[*]~ then: function: pattern functionOptions: match: '^(/(\{[a-zA-Z0-9_]+\}|[a-z0-9]+(-[a-z0-9]+)*))+$' paths-no-query-string: description: Path keys must not contain query strings. severity: error given: $.paths[*]~ then: function: pattern functionOptions: notMatch: '\?' # ── OPERATIONS ─────────────────────────────────────────────────── operation-operationId-required: description: Every operation must declare an operationId. severity: error given: $.paths[*][get,post,put,patch,delete] then: field: operationId function: truthy operation-operationId-camelcase: description: operationId should be camelCase (e.g. searchRecipes, analyzeIngredient). severity: warn given: $.paths[*][get,post,put,patch,delete].operationId then: function: pattern functionOptions: match: '^[a-z][a-zA-Z0-9]*$' operation-summary-required: description: Every operation must have a summary. severity: warn given: $.paths[*][get,post,put,patch,delete] then: field: summary function: truthy operation-summary-edamam-prefix: description: Operation summaries should be prefixed with "Edamam". severity: warn given: $.paths[*][get,post,put,patch,delete].summary then: function: pattern functionOptions: match: '^Edamam ' operation-description-required: description: Every operation should have a description. severity: info given: $.paths[*][get,post,put,patch,delete] then: field: description function: truthy operation-tags-required: description: Every operation must be tagged. severity: warn given: $.paths[*][get,post,put,patch,delete] then: field: tags function: truthy # ── TAGS ───────────────────────────────────────────────────────── tags-global-defined: description: A global tags array should be defined. severity: info given: $ then: field: tags function: truthy tag-description-required: description: Each global tag should have a description. severity: info given: $.tags[*] then: field: description function: truthy tag-title-case: description: Tag names should be Title Case (e.g. "Recipe Search", "Food Database"). severity: warn given: $.tags[*].name then: function: pattern functionOptions: match: '^[A-Z][A-Za-z0-9]*( [A-Z][A-Za-z0-9]*)*$' # ── PARAMETERS ─────────────────────────────────────────────────── parameter-description-required: description: Every parameter should have a description. severity: warn given: $.paths[*][*].parameters[*] then: field: description function: truthy parameter-schema-type: description: Every parameter schema must declare a type. severity: warn given: $.paths[*][*].parameters[*].schema then: field: type function: truthy parameter-example-encouraged: description: Parameters should provide an example value. severity: info given: $.paths[*][*].parameters[*] then: field: example function: truthy # ── REQUEST BODIES ─────────────────────────────────────────────── request-body-json: description: Request bodies should offer application/json content. severity: warn given: $.paths[*][post,put,patch].requestBody.content then: field: application/json function: truthy # ── RESPONSES ──────────────────────────────────────────────────── response-2xx-required: description: Every operation must define at least one 2xx response. severity: error given: $.paths[*][get,post,put,patch,delete].responses then: field: '200' function: truthy response-401-defined: description: Authenticated operations should document a 401 response. severity: info given: $.paths[*][get,post,put,patch,delete].responses then: field: '401' function: truthy response-description-required: description: Every response must have a description. severity: warn given: $.paths[*][*].responses[*] then: field: description function: truthy # ── SCHEMAS — PROPERTY NAMING ──────────────────────────────────── schema-property-camelcase: description: >- Schema property names should be camelCase, matching Edamam's JSON fields (e.g. totalNutrients, healthLabels, foodId). Underscore-prefixed HATEOAS keys like _links and SCREAMING_SNAKE nutrient codes are permitted. severity: info given: $.components.schemas[*].properties[*]~ then: function: pattern functionOptions: match: '^(_?[a-z][a-zA-Z0-9]*|[A-Z][A-Z0-9_.]*)$' schema-object-type: description: Schemas should declare a type. severity: info given: $.components.schemas[*] then: field: type function: truthy # ── SECURITY ───────────────────────────────────────────────────── security-global-defined: description: A global security requirement should be defined. severity: warn given: $ then: field: security function: truthy security-schemes-defined: description: Security schemes must be defined under components. severity: warn given: $.components then: field: securitySchemes function: truthy security-scheme-description: description: Each security scheme should be described. severity: info given: $.components.securitySchemes[*] then: field: description function: truthy # ── HTTP METHOD CONVENTIONS ────────────────────────────────────── get-no-request-body: description: GET operations must not declare a request body. severity: error given: $.paths[*].get then: field: requestBody function: falsy post-has-request-body: description: POST operations should declare a request body. severity: info given: $.paths[*].post then: field: requestBody function: truthy # ── GENERAL QUALITY ────────────────────────────────────────────── operation-microcks-extension: description: Operations should carry an x-microcks-operation extension for mock-server compatibility. severity: info given: $.paths[*][get,post,put,patch,delete] then: field: x-microcks-operation function: truthy response-examples-encouraged: description: JSON responses should provide examples. severity: info given: $.paths[*][*].responses[*].content.application/json then: field: examples function: truthy