Skip to content

openapi init source ​

The team ruleset for OpenAPI documents, run by Spectral. It turns the "OpenAPI" section of conventional/RESTfulAPI.md into a check, so a missing operationId, an unversioned path or a GET without a cache policy is found in the merge request, not by a client.

FileWhat it is
.spectral.yamlThe ruleset. error is a MUST of the standard and fails the job; warn is a SHOULD and only prints
functions/versionedPath.jsJoins Swagger 2.0's basePath to each path before checking it, because swaggo puts /api/v1 there
openapi.gitlab-ci.ymlA job for a repository whose aioz-ci-template version does not have validate:openapi yet
testdata/A spec that must pass clean and one that must trip every rule; tests/openapi-ruleset/run.sh runs both

Run it locally ​

From the repository root, after make swagger:

npx --yes @stoplight/spectral-cli@6.17.0 lint -r .spectral.yaml doc/swagger.json

The VS Code Spectral extension reads the same .spectral.yaml and marks problems as you edit annotations.

Adopting it ​

  1. Copy .spectral.yaml and functions/ to the repository root.

  2. Add the CI job: validate:openapi from aioz-ci-template when the repository's template version has it, otherwise openapi.gitlab-ci.yml. Set OPENAPI_SPEC if the spec is not doc/swagger.json.

  3. Annotate every GET with its cache policy, beside its other swaggo annotations:

    go
    // @x-cache-policy {"type":"revalidate"}
    // @x-cache-policy {"type":"public","max_age":300}
    // @x-cache-policy {"type":"no-store"}

    The type MUST match the Cache(...) the route registers.

  4. Fix the errors, or record each one you cannot fix yet in an overrides block with the Jira key that will. The job warns until the repository sets allow_failure: false; do that once the error count is zero.

Baseline (2026-10-08) ​

The ruleset run against the specs in use today, so adoption subtasks know their size:

SpecErrorsWarningsBiggest items
aioz-template doc/swagger.json0158 GETs without x-cache-policy, 3 camelCase fields (createdAt)
aioz-stream docs/swagger.json1348689 paths with no version (basePath is /api/), 40 operations without operationId, 5 verb paths
parser-service doc/swagger.json181185163 operations without operationId, 9 without a success response, 4 without an error response, 5 verb paths (/auth/remove-wallet)

aioz-stream's unversioned paths are a breaking change to fix: they move under /api/v1/ beside the current paths, and the old ones are deprecated for the standard three months.

Where the rule is a heuristic ​

list-paginated treats a GET on a path that does not end in a {param} as a list. A singleton such as /v1/me or /v1/stats trips it; that is a warning, and an overrides entry with a one-line reason silences it.