Commit graph

3 commits

Author SHA1 Message Date
mithral
0212d089ec Phase 6c: photo thumbnails and viewer
- photos: generates a downscaled JPEG thumbnail per image, because serving a
  folder of 12-megapixel originals to a grid is unusable on a TV box. Uses
  CatmullRom scaling via golang.org/x/image; decodes jpeg/png/gif/webp.
- an undecodable format returns no thumbnail rather than an error, so the grid
  falls back to a placeholder.
- images already smaller than the 512px ceiling are passed through untouched.
- library items endpoint now returns library_id, which the viewer needs to
  find its siblings for navigation.
- web: PhotoViewer with keyboard and button navigation within the library.

Verified: 900x1200 PNG thumbnailed to a 512-long-edge JPEG and served;
unit tests assert exact dimensions, aspect preservation, and that non-images
produce no thumbnail without erroring.
2026-10-09 21:22:30 -04:00
mithral
9772e55c73 Phase 1: accounts, sessions, per-library grants
Multi-user from the first migration, as planned.

- auth: argon2id password hashing (PHC encoded, parameters travel with the
  hash), opaque session tokens stored only as SHA-256, login rate limiting,
  and account enumeration resistance (unknown user hashes anyway)
- sessions: cookie or Bearer auth, HttpOnly + SameSite=Lax, revocation on
  password change
- grants: library_grants is the single access-control chokepoint. Admins see
  every library; everyone else sees exactly their can_read grants
- bootstrap: VELLUM_ADMIN_USER/PASSWORD create the first admin only on an
  empty database. No default password is ever invented.
- httpapi: mounts modules on a shared mux, session middleware innermost
- httpx: shared JSON helpers, strict body decoding

Gate: two users see different libraries. Tests cover that, plus session
expiry, token-at-rest, grant upsert, and the full login/me/logout flow.
2026-10-09 16:31:24 -04:00
mithral
eb1ad6d920 Phase 0: skeleton, config, migrations, health check, container
Bootstraps Vellum as a single Go binary with one SQLite database.

- core: env-driven config, slog logging, SQLite (WAL) with pooled pragmas,
  embedded migration runner keyed on PRAGMA user_version
- migrations/0001_core.sql: identity, media, user state, infra. Media items
  are global; all per-user state (progress, favorites, grants) is a join.
  One polymorphic progress table covers every media kind.
- httpapi: request-ID, structured request logging, panic recovery, JSON
  endpoints for /healthz and /api/v1/version
- multi-arch Dockerfile (pure-Go SQLite, CGO_ENABLED=0) with an entrypoint
  that honours PUID/PGID like the rest of the self-hosted stack
- tests for migration idempotency, FK enforcement, WAL, config, middleware

Media does not exist yet. Nothing is exposed beyond health and version.
2026-10-09 16:26:08 -04:00