{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://api-commons.github.io/spotlight-spec/schema/v1/spotlight-ruleset.schema.json",
  "title": "Spotlight Ruleset",
  "description": "Standalone JSON Schema for the Spotlight (Spectral) ruleset format — the rules and rulesets used to lint JSON/YAML API descriptions such as OpenAPI, AsyncAPI, and Arazzo. Self-contained bundle of Spectral's internal meta-schemas; describes the serializable, implementation-neutral form.",
  "$comment": "GENERATED by tools/sync-from-cli.mjs from Stoplight Spectral (Apache-2.0). Do not edit by hand. The 'errorMessage' keyword is an ajv-errors annotation ignored by standard validators. See PROVENANCE.md.",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "documentationUrl": {
      "type": "string",
      "format": "url",
      "errorMessage": "must be a valid URL"
    },
    "description": {
      "type": "string"
    },
    "rules": {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/$defs/Rule"
      }
    },
    "functions": {
      "$ref": "#/$defs/Functions"
    },
    "functionsDir": {
      "$ref": "#/$defs/FunctionsDir"
    },
    "formats": {
      "$ref": "#/$defs/Formats"
    },
    "extends": {
      "$ref": "#/$defs/Extends"
    },
    "parserOptions": {
      "type": "object",
      "properties": {
        "duplicateKeys": {
          "$ref": "#/$defs/Severity"
        },
        "incompatibleValues": {
          "$ref": "#/$defs/Severity"
        }
      },
      "additionalProperties": false
    },
    "overrides": {
      "type": "array",
      "minItems": 1,
      "items": {
        "if": {
          "type": "object",
          "properties": {
            "files": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "string",
                "minLength": 1,
                "pattern": "^[^#]+#"
              },
              "errorMessage": "must be an non-empty array of glob patterns"
            }
          },
          "required": [
            "files"
          ]
        },
        "then": {
          "type": "object",
          "properties": {
            "files": true,
            "rules": {
              "type": "object",
              "additionalProperties": {
                "$ref": "#/$defs/Severity"
              },
              "errorMessage": {
                "enum": "must be a valid severity level"
              }
            }
          },
          "required": [
            "rules"
          ],
          "additionalProperties": false,
          "errorMessage": {
            "required": "must contain rules when JSON Pointers are defined",
            "additionalProperties": "must not override any other property than rules when JSON Pointers are defined"
          }
        },
        "else": {
          "allOf": [
            {
              "type": "object",
              "properties": {
                "files": {
                  "type": "array",
                  "minItems": 1,
                  "items": {
                    "type": "string",
                    "pattern": "[^#]",
                    "minLength": 1
                  },
                  "errorMessage": "must be an non-empty array of glob patterns"
                }
              },
              "required": [
                "files"
              ],
              "errorMessage": {
                "type": "must be an override, i.e. { \"files\": [\"v2/**/*.json\"], \"rules\": {} }"
              }
            },
            {
              "type": "object",
              "properties": {
                "formats": {
                  "$ref": "#/$defs/Formats"
                },
                "extends": {
                  "$ref": "#/properties/extends"
                },
                "rules": {
                  "$ref": "#/properties/rules"
                },
                "parserOptions": {
                  "$ref": "#/properties/parserOptions"
                },
                "aliases": {
                  "$ref": "#/properties/aliases"
                }
              },
              "anyOf": [
                {
                  "required": [
                    "extends"
                  ]
                },
                {
                  "required": [
                    "rules"
                  ]
                }
              ]
            }
          ]
        }
      },
      "errorMessage": {
        "minItems": "must not be empty"
      }
    },
    "aliases": {
      "type": "object",
      "propertyNames": {
        "pattern": "^[A-Za-z][A-Za-z0-9_-]*$",
        "errorMessage": {
          "pattern": "to avoid confusion the name must match /^[A-Za-z][A-Za-z0-9_-]*$/ regular expression",
          "minLength": "the name of an alias must not be empty"
        }
      },
      "additionalProperties": {
        "if": {
          "type": "object"
        },
        "then": {
          "type": "object",
          "properties": {
            "description": {
              "type": "string"
            },
            "targets": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "object",
                "properties": {
                  "formats": {
                    "$ref": "#/$defs/Formats"
                  },
                  "given": {
                    "$ref": "#/$defs/ArrayishGiven"
                  }
                },
                "required": [
                  "formats",
                  "given"
                ],
                "errorMessage": "a valid target must contain given and non-empty formats"
              },
              "errorMessage": {
                "minItems": "targets must have at least a single alias definition"
              }
            }
          },
          "required": [
            "targets"
          ],
          "errorMessage": {
            "required": "targets must be present and have at least a single alias definition"
          }
        },
        "else": {
          "$ref": "#/$defs/ArrayishGiven"
        }
      }
    }
  },
  "patternProperties": {
    "^x-": true
  },
  "anyOf": [
    {
      "required": [
        "extends"
      ]
    },
    {
      "required": [
        "rules"
      ]
    },
    {
      "required": [
        "overrides"
      ]
    }
  ],
  "$defs": {
    "ArrayishGiven": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/PathExpression"
      },
      "minItems": 1,
      "errorMessage": {
        "minItems": "must be a non-empty array of expressions"
      }
    },
    "DiagnosticSeverity": {
      "enum": [
        -1,
        0,
        1,
        2,
        3
      ]
    },
    "Extends": {
      "oneOf": [
        {
          "type": "string"
        },
        {
          "type": "array",
          "items": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "minItems": 2,
                "prefixItems": [
                  {
                    "type": "string"
                  },
                  {
                    "enum": [
                      "all",
                      "recommended",
                      "off"
                    ],
                    "errorMessage": "allowed types are \"off\", \"recommended\" and \"all\""
                  }
                ],
                "items": false
              }
            ]
          }
        }
      ]
    },
    "Format": {
      "type": "string",
      "errorMessage": "must be a valid format"
    },
    "Formats": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/Format"
      },
      "errorMessage": "must be an array of formats"
    },
    "Function": {
      "type": "object",
      "properties": {
        "function": {
          "type": "string"
        }
      },
      "required": [
        "function"
      ]
    },
    "Functions": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "FunctionsDir": {
      "type": "string"
    },
    "Given": {
      "if": {
        "type": "array"
      },
      "then": {
        "$ref": "#/$defs/ArrayishGiven"
      },
      "else": {
        "$ref": "#/$defs/PathExpression"
      }
    },
    "HumanReadableSeverity": {
      "enum": [
        "error",
        "warn",
        "info",
        "hint",
        "off"
      ]
    },
    "PathExpression": {
      "if": {
        "type": "string"
      },
      "then": {
        "type": "string",
        "if": {
          "pattern": "^#"
        },
        "then": {},
        "else": {
          "pattern": "^\\$",
          "errorMessage": "must be a valid JSON Path expression or a reference to the existing Alias optionally paired with a JSON Path expression subset"
        }
      },
      "else": {
        "not": {},
        "errorMessage": "must be a valid JSON Path expression or a reference to the existing Alias optionally paired with a JSON Path expression subset"
      }
    },
    "Rule": {
      "if": {
        "type": "object"
      },
      "then": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string"
          },
          "documentationUrl": {
            "type": "string",
            "format": "url",
            "errorMessage": "must be a valid URL"
          },
          "recommended": {
            "type": "boolean"
          },
          "given": {
            "$ref": "#/$defs/Given"
          },
          "resolved": {
            "type": "boolean"
          },
          "severity": {
            "$ref": "#/$defs/Severity"
          },
          "message": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "description": "Spotlight tags classifying the rule — the first Spotlight extension beyond the Spectral baseline. Tags are namespaced strings; recommended namespaces: `format:<artifact>` (the artifact type, e.g. `format:openapi`, `format:apis-json`), `spec:<location>` (where in the document it applies, e.g. `spec:operations`, `spec:responses`, `spec:schemas`), `experience:<dimension>` (the developer-experience / quality dimension it improves — one of `documentation`, `naming`, `consistency`, `security`, `error-handling`, `versioning`, `pagination`, `discoverability`, `reliability`, `data-modeling`, `usability`, `governance`, `performance`, `observability`), `topic:<feature>` (the cross-cutting feature family it belongs to, e.g. `topic:caching`, `topic:rate-limiting`, `topic:tracing`, `topic:cors`, `topic:pagination`, `topic:idempotency`, `topic:deprecation`, `topic:conditional-requests`, `topic:content-negotiation`), and `owasp:<category>` (the OWASP API Security Top 10 category it addresses, e.g. `owasp:api1` … `owasp:api10`). A rule may carry multiple tags; tooling groups and filters by them.",
            "items": {
              "type": "string"
            },
            "examples": [
              [
                "format:openapi",
                "spec:responses",
                "topic:rate-limiting",
                "experience:reliability",
                "experience:performance",
                "owasp:api4"
              ]
            ]
          },
          "formats": {
            "$ref": "#/$defs/Formats"
          },
          "then": {
            "if": {
              "type": "array"
            },
            "then": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/RuleThen"
              }
            },
            "else": {
              "$ref": "#/$defs/RuleThen"
            }
          },
          "type": {
            "enum": [
              "style",
              "validation"
            ],
            "type": "string",
            "errorMessage": "allowed types are \"style\" and \"validation\""
          },
          "extensions": {
            "type": "object"
          },
          "title": {
            "type": "string",
            "description": "A short Title Case display name for the rule — the second Spotlight extension beyond the Spectral baseline (after `tags`). Conventionally the Title Case form of the rule key (e.g. `response-define-429` -> `Response Define 429`). Tooling uses it as the human-readable label in rule catalogs and lint output.",
            "examples": [
              "Response Define 429",
              "Security No HTTP Basic Auth"
            ]
          },
          "reference": {
            "type": "string",
            "format": "url",
            "description": "A canonical documentation URL for the rule — the third Spotlight extension beyond the Spectral baseline (after `tags` and `title`). Points to the rule's detail page so tooling can deep-link from lint output to an explanation. The Spotlight catalog points every rule at its page on https://spotlight-rules.com/spec/rules/<artifact>/<slug>/; other implementers may point `reference` at their own internal documentation.",
            "examples": [
              "https://spotlight-rules.com/spec/rules/openapi/response-define-429/"
            ]
          },
          "prompt": {
            "type": "string",
            "description": "A natural-language instruction that an AI assistant (Claude, Gemini, ChatGPT, etc.) can apply to FIX a violation of this rule — the fourth Spotlight extension beyond the Spectral baseline (after `tags`, `title`, and `reference`). It states the requirement, the precise corrective action, and the location, and asks the model to return the corrected artifact. Tooling (e.g. the Spotlight validator's Fix action) sends this prompt — together with the artifact and the specific lint findings — to a configured model to auto-remediate the rule.",
            "examples": [
              "You are editing an OpenAPI document to satisfy the Spotlight rule 'Response Define 429'. Requirement: operations should define a 429 (Too Many Requests) response. To fix: add a `429` response with a description and error schema to each operation that can be rate-limited. Return only the complete corrected document."
            ]
          }
        },
        "required": [
          "given",
          "then"
        ],
        "additionalProperties": false,
        "patternProperties": {
          "^x-": true
        },
        "errorMessage": {
          "required": "the rule must have at least \"given\" and \"then\" properties"
        }
      },
      "else": {
        "oneOf": [
          {
            "$ref": "#/$defs/HumanReadableSeverity"
          },
          {
            "type": "boolean"
          }
        ]
      }
    },
    "RuleThen": {
      "type": "object",
      "allOf": [
        {
          "properties": {
            "field": {
              "type": "string"
            }
          }
        },
        {
          "$ref": "#/$defs/Function"
        },
        {
          "if": {
            "properties": {
              "function": {
                "const": "pattern"
              }
            },
            "required": [
              "function"
            ]
          },
          "then": {
            "properties": {
              "functionOptions": {
                "type": "object",
                "properties": {
                  "match": {
                    "type": "string"
                  },
                  "notMatch": {
                    "type": "string"
                  }
                },
                "anyOf": [
                  {
                    "required": [
                      "match"
                    ]
                  },
                  {
                    "required": [
                      "notMatch"
                    ]
                  }
                ],
                "additionalProperties": false
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "function": {
                "const": "length"
              }
            },
            "required": [
              "function"
            ]
          },
          "then": {
            "properties": {
              "functionOptions": {
                "type": "object",
                "properties": {
                  "min": {
                    "type": "number"
                  },
                  "max": {
                    "type": "number"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "function": {
                "const": "enumeration"
              }
            },
            "required": [
              "function"
            ]
          },
          "then": {
            "properties": {
              "functionOptions": {
                "type": "object",
                "properties": {
                  "values": {
                    "type": "array"
                  }
                },
                "required": [
                  "values"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "function": {
                "const": "casing"
              }
            },
            "required": [
              "function"
            ]
          },
          "then": {
            "properties": {
              "functionOptions": {
                "type": "object",
                "properties": {
                  "type": {
                    "enum": [
                      "flat",
                      "camel",
                      "pascal",
                      "kebab",
                      "cobol",
                      "snake",
                      "macro"
                    ]
                  },
                  "disallowDigits": {
                    "type": "boolean"
                  },
                  "separator": {
                    "type": "object",
                    "properties": {
                      "char": {
                        "type": "string"
                      },
                      "allowLeading": {
                        "type": "boolean"
                      }
                    }
                  }
                },
                "required": [
                  "type"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "function": {
                "const": "schema"
              }
            },
            "required": [
              "function"
            ]
          },
          "then": {
            "properties": {
              "functionOptions": {
                "type": "object",
                "properties": {
                  "schema": {
                    "type": "object"
                  },
                  "dialect": {
                    "type": "string"
                  },
                  "allErrors": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "schema"
                ]
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "function": {
                "const": "alphabetical"
              }
            },
            "required": [
              "function"
            ]
          },
          "then": {
            "properties": {
              "functionOptions": {
                "type": "object",
                "properties": {
                  "keyedBy": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        {
          "if": {
            "properties": {
              "function": {
                "const": "xor"
              }
            },
            "required": [
              "function"
            ]
          },
          "then": {
            "properties": {
              "functionOptions": {
                "type": "object",
                "properties": {
                  "properties": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "properties"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      ]
    },
    "Severity": {
      "oneOf": [
        {
          "$ref": "#/$defs/DiagnosticSeverity"
        },
        {
          "$ref": "#/$defs/HumanReadableSeverity"
        }
      ],
      "errorMessage": "the value has to be one of: 0, 1, 2, 3 or \"error\", \"warn\", \"info\", \"hint\", \"off\""
    }
  }
}
