docz-api OpenAPI contract
openapi.yaml is the hand-authored, machine-readable contract for
docz-api's HTTP surface (OpenAPI 3.1). It is the single source of truth for the
wire shapes docz-api ships, and it is the artifact the docz-site vendors to
generate a typed client.
What is here
openapi.yaml — the OAS 3.1 contract: the /api/v1 read + search routes,
the site auth endpoints (/api/v1/auth/*, public /auth/login +
/auth/callback), and the GitHub webhook receiver (/webhooks/github).
spec.go — a one-line //go:embed openapi.yaml exposing
var Spec []byte, so the runtime server and the contract test consume the
exact same bytes.
vacuum-ruleset.yaml — the linter ruleset used by just lint-openapi.
How it stays honest
An in-process kin-openapi contract test
(internal/httpapi/openapi_contract_test.go) loads this file, drives the real
chi handler stack in-memory, and validates every request and response against it
on every go test ./... / CI run. Response schemas are
additionalProperties: false, so any added, renamed, or retyped wire field
fails the contract test — code and spec cannot silently drift.
just lint-openapi additionally runs vacuum (100/100) and yamlfmt so the
file stays standards-clean and canonical.
Versioning
info.version is SemVer, starting at 1.0.0 (independent of the binary's
release version). Bump it by hand on any change to a specced wire shape:
- patch — editorial only (descriptions, examples); no wire change.
- minor — additive, backward-compatible (a new endpoint, a new optional
field, a new enum value).
- major — breaking (a removed or renamed field, a changed type, a removed
endpoint, a newly required request field or header). "Required" is
request-side only: a response property moving into
required is a stronger
promise to the consumer, never a breaking one, so it is additive — 1.4.0
set that precedent by adding source and path as required on SearchHit.
The version is the signal consumers pin against, so a wire change without a bump
is a contract bug.
Current: 1.5.0 — every search hit carries created (the authored
YYYY-MM-DD, "" on pages) and updated_at (RFC 3339 UTC, the same
value the document endpoint serves), searchDocs accepts sort
(updated_at/created, each direction) and source (doc/page), and
the operation gains its first 400 for an unrecognized sort
(IMPL-0010). The sort is a total order over the matches, and a record
with no value for the key sorts last in either direction. 1.4.2 —
editorial: groups on the session response is documented as always
optional, since the OIDC scope that supplies it is now per-provider
configuration rather than a hardcoded request (PR #32).
1.4.1 — editorial: documents config_snapshot's key
spellings (docz v1.2.2's json-tagged config marshal serves the
.docz.yaml names — changelog.enabled, api.landing_page — with
omitempty keys absent when unset and unset list fields as null).
The wire type is unchanged; snapshot readers can pin this version for
the spelling guarantee. 1.4.0 — search hits carry source
(doc/page) and path,
and source joins the facet counts, so page results are distinguishable and
deep-linkable (IMPL-0007 Phase 6). 1.3.0 added the pages surface:
listRepoPages (GET /api/v1/repos/{owner}/{name}/pages) and getRepoPage
(GET .../pages/{path}), publishing the markdown a repository's .docz.yaml
api: block opts into (docz v1.2.0, DESIGN-0004). Enabling the block
publishes every .md under the docs dir — api.exclude is the guard rail
for drafts and internal notes; templates/ is always excluded. A repository
without the block serves an empty page list (200, not 404) and 404s every page
path. 1.2.0 added getRepoChangelog (opt-in via the changelog: block;
IMPL-0005). 1.1.0 added getRepoIndex.
Consuming it (the docz-site)
The docz-site vendors-and-generates, mirroring the rfc-site model:
- Vendor this
openapi.yaml into the site repo (pinning a known version),
or fetch it at runtime from GET /openapi.yaml (served verbatim from the
embed, public — no session required).
- Generate a typed client from the vendored spec with the site's toolchain
(e.g.
openapi-typescript or orval).
- Re-vendor when
info.version bumps; a major bump signals a breaking
change to reconcile before upgrading.
There is no bundled Swagger/Scalar UI in docz-api (IMPL-0002 OQ-3d) — the
served /openapi.yaml is the machine contract; human browsing is left to the
consumer's tooling or an optional docz mkdocs render.
References