docs(api): an OpenAPI spec, checked against the router

The brief asked for one. docs/api.md is complete and hand-written, and
there was nothing a tool could read.

Written by hand rather than generated from annotations, which would have
meant every handler carrying a second copy of itself in a comment. The
risk with a hand-written spec is that it goes stale, so it does not
depend on anybody remembering: openapi_test.go walks the chi router and
fails both on a route nothing describes and on a description with no
route behind it. CI separately checks it is a valid OpenAPI document.

The test reads the file with a forty-line scanner rather than pulling in
a YAML library. It needs two things — which paths are listed and which
methods each has — and both sit at fixed indentation in a document the
test also owns, which is worth more than a dependency in a project whose
whole shape is one static binary.

The CalDAV routes are excluded deliberately: PROPFIND and REPORT are
outside what OpenAPI can describe, and docs/caldav.md covers them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kristian Wind
2026-08-17 10:56:33 +02:00
committed by Kristian Wind
co-authored by Claude Opus 5
parent 1424f43a40
commit cb77990458
5 changed files with 2399 additions and 0 deletions
+10
View File
@@ -19,6 +19,16 @@ curl -H "Authorization: Bearer vrd_..." https://todo.example.dk/api/v1/tasks
Make one under **Settings → API tokens**. It carries your permissions exactly —
there is no separate service identity.
## The machine-readable spec
[`openapi.yaml`](openapi.yaml) describes the same API as an OpenAPI 3.1 document —
for generating a client, for importing into Bruno or Insomnia, or for reading in a
tool that renders it.
It is written by hand, and a test walks the router on every build and fails if an
endpoint is routed but not described, or described but no longer routed. So it is
as current as this page is, which is to say: as current as CI is green.
## Errors
Every failure has the same shape:
+2216
View File
File diff suppressed because it is too large Load Diff