extends:
  - spectral:oas

# Severity levels: error, warn, info, hint, off
# Rules from the built-in "spectral:oas" ruleset are active by default.
# Below we tune severity and add custom rules for our conventions.
#
# This ruleset mirrors Comfy-Org/cloud/.spectral.yaml so specs across the
# organization are linted against a single consistent standard.

rules:
  # -----------------------------------------------------------------------
  # Built-in rule severity overrides
  # -----------------------------------------------------------------------
  operation-operationId: error
  operation-description: warn
  operation-tag-defined: error
  info-contact: off
  info-description: warn
  no-eval-in-markdown: error
  no-$ref-siblings: error

  # -----------------------------------------------------------------------
  # Custom rules: naming conventions
  # -----------------------------------------------------------------------

  # Property names should be snake_case
  property-name-snake-case:
    description: Property names must be snake_case
    severity: warn
    given: "$.components.schemas.*.properties[*]~"
    then:
      function: pattern
      functionOptions:
        match: "^[a-z][a-z0-9]*(_[a-z0-9]+)*$"

  # Operation IDs should be camelCase
  operation-id-camel-case:
    description: Operation IDs must be camelCase
    severity: warn
    given: "$.paths.*.*.operationId"
    then:
      function: pattern
      functionOptions:
        match: "^[a-z][a-zA-Z0-9]*$"

  # -----------------------------------------------------------------------
  # Custom rules: response conventions
  # -----------------------------------------------------------------------

  # Error responses (4xx, 5xx) should use a consistent shape
  error-response-schema:
    description: Error responses should reference a standard error schema
    severity: hint
    given: "$.paths.*.*.responses[?(@property >= '400' && @property < '600')].content['application/json'].schema"
    then:
      field: "$ref"
      function: truthy

  # All 2xx responses with JSON body should have a schema
  response-schema-defined:
    description: Success responses with JSON content should define a schema
    severity: warn
    given: "$.paths.*.*.responses[?(@property >= '200' && @property < '300')].content['application/json']"
    then:
      field: schema
      function: truthy

  # -----------------------------------------------------------------------
  # Custom rules: best practices
  # -----------------------------------------------------------------------

  # Path parameters must have a description
  path-param-description:
    description: Path parameters should have a description
    severity: warn
    given:
      - "$.paths.*.parameters[?(@.in == 'path')]"
      - "$.paths.*.*.parameters[?(@.in == 'path')]"
    then:
      field: description
      function: truthy

  # Schemas should have a description
  schema-description:
    description: Component schemas should have a description
    severity: hint
    given: "$.components.schemas.*"
    then:
      field: description
      function: truthy

overrides:
  # /ws uses HTTP 101 (Switching Protocols) — a legitimate response for a
  # WebSocket upgrade, but not a 2xx, so operation-success-response fires
  # as a false positive. OpenAPI 3.x has no native WebSocket support.
  - files:
      - "openapi.yaml#/paths/~1ws"
    rules:
      operation-success-response: off
