Commit graph

7 commits

Author SHA1 Message Date
mithral
051169a18a Documentation, and make a fresh clone actually work
Docs
- docs/ARCHITECTURE.md: how the pieces fit and why. The request path, the six
  enforced layers, the data model, the scanner, the job queue, direct-play
  playback, and the three protocol surfaces over one application.
- docs/decisions/: seven ADRs with the alternatives that were rejected —
  SQLite-with-a-seam, direct-play-only, mark-missing-never-delete, the modular
  monolith, the one item-access chokepoint, the table-backed queue, and
  fixed-width timestamps.
- README: the layout section was stale (it predated catalog, home, scanner,
  providers, engine, probe, playback, apitoken, arch and the dto packages) and
  now lists what exists, plus links to the new docs.

Two real bugs, both found by verifying the docs instead of trusting them

1. The CLI could not run on a fresh install. `Config.Validate` created the data
   and config directories, but the CLI never called it, so `vellum user add` —
   the recovery path when you are locked out — failed with "unable to open
   database file" until the server had booted at least once. Split the directory
   creation into `Config.EnsureDirs`, call it from the CLI, and keep the media
   root check out of it: an admin command must not fail because a library is
   unmounted. The CLI tests now point DBPath inside DataDir, exactly as
   LoadConfig derives it, so they exercise the fresh-install path; removing
   EnsureDirs fails three of them.

2. A fresh clone could not build at all. `//go:embed all:dist` fails to compile
   when web/dist is absent, and web/.gitignore expected a `dist/.gitkeep` that
   was never created. Added it, so a clone builds and the server logs
   "web UI not embedded; run the frontend build to include it" — the intended
   behaviour for someone who only wants the API.

Also: the httpapi tests depended on a built frontend and FAILED rather than
skipping, so the suite was red on any fresh clone. findAsset and readAsset now
skip with a message naming the missing step. They still RUN when a bundle is
present (verified: zero skips here), so they have not been quietly disabled.

Verified from a simulated clone of tracked files only: go build exit 0, 25
packages pass, the server boots and applies all 12 migrations, and the CLI
creates a user and takes a backup. gofmt clean, vet exit 0, svelte-check 0/0.
2026-10-12 00:18:11 -04:00
mithral
7754b0f504 dev: fix the Vite proxy and add a one-command dev runner
Running `pnpm dev` alone gave ECONNREFUSED on every request, because nothing
was listening on :7788. Two separate causes:

- the backend simply was not running, and
- Vite bound [::1]:5173 while the proxy target was "localhost", which Node
  resolves to ::1 first. The Go server binds IPv4, so even with the backend up
  the proxy could fail before falling back.

- vite.config.ts: proxy target is now 127.0.0.1 explicitly and overridable via
  VELLUM_API; server.host is true so both stacks are served.
- scripts/dev.sh + `make dev`: builds the backend, waits for /healthz, starts
  Vite, and stops the backend on exit. Ctrl-C tears down both.
- README documents that running Vite alone needs the backend already up.
2026-10-10 16:32:32 -04:00
mithral
1d7831ac10 docs: six media types complete; game detail says Play
- README status: PDF, music metadata, comic metadata, and games are done.
  Six media types work; video remains deferred by design. The stack now covers
  Stump, Kavita, Audiobookshelf, Navidrome, and RomM — only Jellyfin is left.
- IGDB environment variables documented.
- Item detail labels the primary action "Play" for games, not "Read".
2026-10-09 21:57:40 -04:00
mithral
5a2c3fa090 Comic metadata via ComicVine
- comicvine provider for comics. ComicVine has no keyless tier, so the
  provider is only registered when VELLUM_COMICVINE_API_KEY is set; without it
  the server logs a note and comic enrichment completes as a no-op rather than
  erroring.
- BaseURL is injectable so the response parsing is covered by a test against a
  local server: candidate mapping, the required User-Agent, and the
  status_code=100 invalid-key case (ComicVine returns HTTP 200 for that).
- descriptions are stripped of ComicVine's embedded HTML before storage.

Verified against a fake ComicVine server, and live that a comics library
enriches cleanly with no key configured.
2026-10-09 21:47:51 -04:00
mithral
b0151fce00 docs: update status through phase 6c
README status table, package layout, and plan progress log now reflect what is
actually built: search, comics, metadata, audiobooks, and photos. Gaps listed
honestly: no PDF/CBR, no games, no video, no music or comic metadata, no
grants UI.
2026-10-09 21:23:12 -04:00
mithral
7a5584a83f docs: record phase 0-3 build progress and status
README status table, full env var reference including admin bootstrap and
cookie security, package layout, and build commands. Plan doc updated with a
progress log, the deviations from plan and why, and the gaps carried forward.
2026-10-09 16:42:53 -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