Commit Graph
3 Commits
Author SHA1 Message Date
Kristian WindandClaude Opus 5 cb77990458 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>
2026-08-17 10:56:33 +02:00
Kristian WindandClaude Opus 5 68d82a1cb6 feat(api): personal API tokens, and let people change their own profile
docs/api.md has told people to make a token under Settings since it was
written. The store has held CreateAPIToken, ListAPITokens and
DeleteAPIToken since the first migration. There were no routes: nothing
between the two, and no way to make one.

GET, POST and DELETE under /tokens, all behind a new requireSession
middleware. A bearer token is refused there with 403 even though it is
accepted everywhere else — otherwise a leaked token is permanent, because
whoever has it issues a second one and revoking the first changes
nothing. The plaintext comes back from POST and never again; only the
hash is stored, so the interface has to say so at that moment rather than
offering a reveal that cannot work.

PATCH /auth/me alongside it. Name, timezone and language could not be
changed anywhere — not through the API and not through the interface —
and an account created from an invite inherits a default timezone. That
is not cosmetic: every date in the app is resolved in it, so somebody in
another country had every due date land an hour out with no way to say
so. The zone is validated against the running system's database rather
than a list kept here, which is the same database the dates are resolved
with. The email address stays read-only: it identifies the account and is
what invites were sent to.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 10:56:33 +02:00
Kristian WindandClaude Opus 5 7c9bde2cfd docs(phase6): documentation site, landing page and open-source scaffolding
Material for MkDocs under docs/, covering self-hosting, the Rune, the
quick-add and filter languages, importing from Todoist, CalDAV,
mail-to-task, MCP, the AI layer and the API. The version is pinned: the
maintainers have announced that MkDocs 2.0 removes the plugin system
with no migration path, and an unpinned install would break this build
on the day it lands.

The landing page shows the quick-add parser as actual text rather than a
screenshot of it — that is the thing worth showing, and it reads better
as the real thing. It shares the app's design tokens, so the site and
what it describes look like one project.

MIT licence, contributing guide, security policy and issue templates.
Pages deployment is behind workflow_dispatch, so the docs build on every
push but nothing is published until the owner chooses to.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 08:08:36 +02:00