- Review draft sync is a pure helper (format.ts): incoming values are
ignored while a save is in flight, and a failed save restores the
previous synced value, so the typed text is kept whichever of the
rollback and the error callback lands first. Tests cover both orders.
- A failed background refetch keeps showing the cached entry instead of
the error screen (it unmounted the review box mid-outage).
- History restore joins the entry-patch mutation scope.
- updatePreferences: read-modify-write in a transaction, row locked on
Postgres.
- Invalidate auth-status after register; out-of-range rating errors speak
in the user's scale.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
GET log (engagements and listens, keyset over at/kind/id), listChanges
title and intoTitle, listCopies workTitle, all via batched lookups.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Tags and custom fields update the cached entry optimistically and build
from the latest cache; one entry's PATCHes run in order (mutation scope).
- The review textarea follows server changes (Restore) unless edited.
- friendlyError() maps validation reasons and 413 to plain copy everywhere.
- Rating scale from me/preferences; /login and /register use auth/status;
Attachments lists from the API.
- Gelasio vendored (official OFL variable TTFs); minors from the review.
- Docs: DESIGN (AA on orange, faint labels), DECISIONS, TODO, ARCHITECTURE.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
GET auth/status ({ hasUsers }), GET attachments?entity=&entityId= (owner
scoped, 404 for foreign targets) and GET/PATCH me/preferences (ratingScale,
defaultVisibility in users.preferences).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
DESIGN.md tokens as CSS custom properties. Inter (OFL) is vendored so the
app makes no third-party font requests.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- API writes pass token:<name> for Bearer requests and "user" for sessions.
- X-Requested-With: sttracker on every non-Bearer write, login and register included.
- JSON-body routes reject non-JSON content types with 415.
- A malformed stt_session cookie counts as no cookie (401), not 500.
- DELETE me/tokens/:id is 404 for unknown or foreign ids; admin/invites is admin-only.
- Bun.serve development mode only with NODE_ENV=development or --hot.
- OpenAPI documents multipart fields.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Migration 0003 adds source_connections.deleted_at. deleteConnection sets it; listing, lookups,
updates, the scheduler and the sync handler ignore deleted connections, so a paused
credential-less connection stays visible and can be resumed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
createApp() serves /api/v1 from a typed route table (zod bodies and queries), with
session-cookie and Bearer app-token auth, a CSRF header for cookie writes, login/register
rate limiting, body caps, JSON error mapping, OpenAPI generation and a 404 /ingest mount.
Co-Authored-By: Claude Opus 5.5 <[email protected]>