Studio Ghibli · API Governance Rules

Studio Ghibli API Rules

Spectral linting rules defining API design standards and conventions for Studio Ghibli.

23 Rules error 5 warn 14 info 4
View Rules File View on GitHub

Rule Categories

info operation parameter path response schema servers

Rules

warn
info-title-studio-ghibli-prefix
API title MUST begin with "Studio Ghibli".
$.info.title
warn
info-description-required
API description MUST be present and non-trivial.
$.info
error
info-version-required
API version MUST be declared in info.version.
$.info
warn
info-license-required
Studio Ghibli API is MIT-licensed — info.license MUST be present.
$.info
error
servers-present
At least one server URL MUST be declared.
$
info
servers-canonical-host
The first server URL SHOULD point to the current canonical Vercel deployment.
$.servers[0].url
warn
path-lowercase-kebab
Path segments MUST be lowercase. The Studio Ghibli API uses single-word plural collection nouns.
$.paths[*]~
warn
path-plural-collections
Collection paths MUST use plural nouns (films, people, locations, species, vehicles).
$.paths[*]~
error
operation-operationid-required
Every operation MUST declare an operationId.
$.paths[*][get,post,put,patch,delete]
warn
operation-operationid-camelcase
operationId MUST be camelCase (e.g. listFilms, getFilm).
$.paths[*][get,post,put,patch,delete].operationId
warn
operation-summary-required
Every operation MUST have a Title Case summary.
$.paths[*][get,post,put,patch,delete]
info
operation-summary-title-case
Operation summaries SHOULD use Title Case.
$.paths[*][get,post,put,patch,delete].summary
warn
operation-description-required
Every operation MUST have a description.
$.paths[*][get,post,put,patch,delete]
warn
operation-tags-required
Every operation MUST be tagged with one of the five Studio Ghibli resource groups.
$.paths[*][get,post,put,patch,delete]
warn
operation-tags-allowed
Operation tags MUST be one of Films, People, Locations, Species, Vehicles.
$.paths[*][get,post,put,patch,delete].tags[*]
warn
parameter-description-required
Every parameter MUST have a description.
$..parameters[*]
error
parameter-schema-required
Every parameter MUST have a schema with a type.
$..parameters[*]
info
parameter-snake-case
Parameter names SHOULD be snake_case to match the response field casing.
$..parameters[?(@.in=='query')].name
error
response-200-required
Every GET operation MUST declare a 200 success response.
$.paths[*].get.responses
warn
response-404-on-by-id
Single-resource (by-id) operations MUST declare a 404 response.
$.paths[?(@property.match(/.*\{id\}$/))].get.responses
warn
response-content-application-json
Success responses MUST use application/json.
$.paths[*].get.responses.200.content
warn
schema-required-id
All five resource schemas MUST require an id field.
$.components.schemas[Film,Person,Location,Species,Vehicle]
info
schema-property-snake-case
Schema property names SHOULD be snake_case (matches API responses).
$.components.schemas[*].properties[*]~

Spectral Ruleset

Raw ↑
# Studio Ghibli API Spectral Ruleset
#
# Enforces conventions used by the community-built Studio Ghibli API
# (https://github.com/janaipakos/ghibliapi). The API is a read-only REST surface
# over five resource collections (films, people, locations, species, vehicles)
# and uses these conventions:
#
#   OpenAPI version : 3.0.3 (converted from original Swagger 2.0)
#   Title prefix    : "Studio Ghibli ..."
#   Path casing     : lowercase, plural collection nouns
#   OperationId     : camelCase, verb-noun (listFilms, getFilm)
#   Parameter names : snake_case (matches response field casing)
#   Schema props    : snake_case
#   Security        : none — public API
#   Required errors : 400, 404 (per Swagger source)
extends:
  - "spectral:oas"
formats:
  - oas3
rules:

  # ─── INFO / METADATA ──────────────────────────────────────────────────────
  info-title-studio-ghibli-prefix:
    description: API title MUST begin with "Studio Ghibli".
    message: "{{property}} must start with 'Studio Ghibli'."
    severity: warn
    given: $.info.title
    then:
      function: pattern
      functionOptions:
        match: "^Studio Ghibli"

  info-description-required:
    description: API description MUST be present and non-trivial.
    severity: warn
    given: $.info
    then:
      - field: description
        function: truthy
      - field: description
        function: length
        functionOptions:
          min: 60

  info-version-required:
    description: API version MUST be declared in info.version.
    severity: error
    given: $.info
    then:
      field: version
      function: truthy

  info-license-required:
    description: Studio Ghibli API is MIT-licensed — info.license MUST be present.
    severity: warn
    given: $.info
    then:
      field: license
      function: truthy

  # ─── SERVERS ──────────────────────────────────────────────────────────────
  servers-present:
    description: At least one server URL MUST be declared.
    severity: error
    given: $
    then:
      field: servers
      function: truthy

  servers-canonical-host:
    description: The first server URL SHOULD point to the current canonical Vercel deployment.
    severity: info
    given: $.servers[0].url
    then:
      function: pattern
      functionOptions:
        match: "^https://ghibliapi\\.(vercel\\.app|herokuapp\\.com)"

  # ─── PATHS ────────────────────────────────────────────────────────────────
  path-lowercase-kebab:
    description: Path segments MUST be lowercase. The Studio Ghibli API uses single-word plural collection nouns.
    message: "Path '{{value}}' must be lowercase."
    severity: warn
    given: $.paths[*]~
    then:
      function: pattern
      functionOptions:
        match: "^/[a-z0-9/_{}-]+$"

  path-plural-collections:
    description: Collection paths MUST use plural nouns (films, people, locations, species, vehicles).
    severity: warn
    given: $.paths[*]~
    then:
      function: pattern
      functionOptions:
        match: "^/(films|people|locations|species|vehicles)(/\\{id\\})?$"

  # ─── 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 MUST be camelCase (e.g. listFilms, getFilm).
    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 Title Case summary.
    severity: warn
    given: $.paths[*][get,post,put,patch,delete]
    then:
      field: summary
      function: truthy

  operation-summary-title-case:
    description: Operation summaries SHOULD use Title Case.
    severity: info
    given: $.paths[*][get,post,put,patch,delete].summary
    then:
      function: pattern
      functionOptions:
        match: "^[A-Z][A-Za-z0-9 ]+$"

  operation-description-required:
    description: Every operation MUST have a description.
    severity: warn
    given: $.paths[*][get,post,put,patch,delete]
    then:
      field: description
      function: truthy

  operation-tags-required:
    description: Every operation MUST be tagged with one of the five Studio Ghibli resource groups.
    severity: warn
    given: $.paths[*][get,post,put,patch,delete]
    then:
      field: tags
      function: truthy

  operation-tags-allowed:
    description: Operation tags MUST be one of Films, People, Locations, Species, Vehicles.
    severity: warn
    given: $.paths[*][get,post,put,patch,delete].tags[*]
    then:
      function: enumeration
      functionOptions:
        values:
          - Films
          - People
          - Locations
          - Species
          - Vehicles

  # ─── PARAMETERS ───────────────────────────────────────────────────────────
  parameter-description-required:
    description: Every parameter MUST have a description.
    severity: warn
    given: $..parameters[*]
    then:
      field: description
      function: truthy

  parameter-schema-required:
    description: Every parameter MUST have a schema with a type.
    severity: error
    given: $..parameters[*]
    then:
      field: schema
      function: truthy

  parameter-snake-case:
    description: Parameter names SHOULD be snake_case to match the response field casing.
    severity: info
    given: $..parameters[?(@.in=='query')].name
    then:
      function: pattern
      functionOptions:
        match: "^[a-z][a-z0-9_]*$"

  # ─── RESPONSES ────────────────────────────────────────────────────────────
  response-200-required:
    description: Every GET operation MUST declare a 200 success response.
    severity: error
    given: $.paths[*].get.responses
    then:
      field: "200"
      function: truthy

  response-404-on-by-id:
    description: Single-resource (by-id) operations MUST declare a 404 response.
    severity: warn
    given: $.paths[?(@property.match(/.*\{id\}$/))].get.responses
    then:
      field: "404"
      function: truthy

  response-content-application-json:
    description: Success responses MUST use application/json.
    severity: warn
    given: $.paths[*].get.responses.200.content
    then:
      field: application/json
      function: truthy

  # ─── SCHEMAS ──────────────────────────────────────────────────────────────
  schema-required-id:
    description: All five resource schemas MUST require an id field.
    severity: warn
    given: $.components.schemas[Film,Person,Location,Species,Vehicle]
    then:
      field: required
      function: schema
      functionOptions:
        schema:
          type: array
          contains:
            const: id

  schema-property-snake-case:
    description: Schema property names SHOULD be snake_case (matches API responses).
    severity: info
    given: $.components.schemas[*].properties[*]~
    then:
      function: pattern
      functionOptions:
        match: "^[a-z][a-z0-9_]*$"