Files
HealthLog/src/app
Marc-André Bombeck b6efc6cb5a Register the sixteen auth, settings and discovery routes the spec never had
`pnpm openapi:check` compares the registry against the committed YAML and
never the routes against the registry, so a route that was simply never
registered stayed invisible to the gate. Sixteen of them are called by the
native client and describe nothing: sign-out, the three per-user preference
scalars, the two pre-session discovery reads, passkey login options, the
passkey rename and delete, registration status, the consent latest-receipt
reader and its revoke, account deletion, the instance service switches, the
API-token list and revoke, the threshold overrides, the version read, and the
assistant feature matrix.

Each contract is derived from the handler rather than from its docblock, so
the published statuses are the ones the code can actually produce — the 413 on
a 1 KB body cap, the 400 the consent family answers where the rest of the API
answers 422, the 403 an instance-wide API switch produces on a token READ, the
last-admin and last-Guardian refusals on account deletion, and the fresh-factor
arm that a Bearer transport cannot clear at any scope.

Four request bodies moved to the validation modules the handlers now parse
with, so the published wire cannot drift from the runtime one: the three
`/api/auth/me` preference scalars into a new `user-prefs` module, and the
passkey rename beside the login schemas. Behaviour is unchanged.

The generated YAML is left out; it is regenerated once the remaining groups
land.
2026-08-22 12:24:52 +02:00
..
2026-03-10 20:14:33 +01:00
2026-03-10 20:14:33 +01:00

src/app/

The Next.js App Router tree: the page surfaces a logged-in user sees and the REST API under api/. Server components are the default; "use client" is added only where a hook, state, or browser API needs it. Routing is file-based — a page.tsx is a page, a route.ts is an API endpoint.

API routes (api/)

Every endpoint wraps its handler in apiHandler (@/lib/api-handler), parses any body with Zod safeParse, narrows userId from the session or Bearer token (never from the body), and returns the { data, error, meta? } envelope. requireAdmin() is cookie-only, so api/admin/ is unreachable by Bearer token. Notable groups:

  • auth/ — login, register, password, passkey (WebAuthn), refresh, Codex device-OAuth.
  • measurements/, mood-entries/, medications/, sleep/ — the core health-data CRUD + batch/bulk ingest.
  • ingest/ — external Bearer-token ingest surfaces.
  • insights/, analytics/, dashboard/ — AI insights, the Coach SSE stream, trend summaries, the first-paint dashboard snapshot.
  • withings/, whoop/, fitbit/, integrations/, sync/ — OAuth connect/sync/webhook surfaces and the offline delta feed.
  • fhir/, share-links/, doctor-report/, export/, import/ — clinician-facing FHIR R4 read API, shareable records, report + data export.
  • notifications/, devices/, send/, telegram/ — channel registration, device tokens, dispatch, webhook intake.
  • admin/ — operator panel APIs (cookie-only).
  • health/, version/, meta/, internal/ — health check, build-version probe, runtime metadata, worker-internal routes.

Page surfaces

measurements/, medications/, mood/, insights/, achievements/, notifications/, settings/, onboarding/, admin/, plus the public about/, privacy/, bugreport/, the share-record route c/, and the root dashboard (page.tsx). Shared shell + chrome lives in layout.tsx; error.tsx / global-error.tsx / not-found.tsx / loading.tsx cover the framework boundaries. layout.tsx holds the one nonce-bound dangerouslySetInnerHTML (theme bootstrap).

Conventions

See ../../CLAUDE.md. The request-flow walk in .planning/codebase/arch.md annotates each layer with file:line citations. Related dirs: handlers compose ../lib/; pages render ../components/.