Vellum/internal/core
mithral df740d3e1a Phase 5: job queue and metadata providers
- jobs: a table-backed queue in the same SQLite file. No Redis, no second
  process, included in the same backup. claim() is a single UPDATE...RETURNING
  so a job cannot run twice even with several workers. Failures back off
  exponentially; a missing handler fails permanently rather than retrying a
  bug.
- metadata: Provider interface plus Open Library and Google Books (both
  keyless). The enricher tries providers in registration order, falls back on
  empty, and continues past a provider error.
- migration 0004: metadata_fetch records the attempt, not just the match, so a
  rescan does not re-hammer a rate-limited API for an item that will never
  match. Errors are always retried; ok/notfound are cached for 30 days.
- enrichment writes provider_ids, updates title/year, links authors through
  people/item_people, and downloads the cover as an asset. The cover download
  runs outside the transaction: a slow image host must not hold a write lock.
- endpoints: queue enrichment per library, and inspect an item's matches.
- web: Enrich button per library.

Verified live against Open Library: "The Hobbit" matched /works/OL27482W,
title and year 1937 written, a 301x500 JPEG cover downloaded and served.
2026-10-09 21:16:07 -04:00
..
config.go Phase 1: accounts, sessions, per-library grants 2026-10-09 16:31:24 -04:00
config_test.go Phase 0: skeleton, config, migrations, health check, container 2026-10-09 16:26:08 -04:00
db.go Phase 0: skeleton, config, migrations, health check, container 2026-10-09 16:26:08 -04:00
logging.go Phase 0: skeleton, config, migrations, health check, container 2026-10-09 16:26:08 -04:00
migrate.go Phase 2b: FTS5 search 2026-10-09 21:10:44 -04:00
migrate_test.go Phase 5: job queue and metadata providers 2026-10-09 21:16:07 -04:00