Releases: jwapps-app/bibliocapsa
Release list
v1.18.1
Security hardening
A full security audit (auth/tenant-isolation, injection/SSRF, web/crypto/config) found no critical or high issues — genre isolation, parameterized SQL, shell-free subprocess calls, the SSRF guard, and the sandboxed reader all held up. This release hardens the medium/low findings:
- Password-spray protection on all endpoints. The login rate-limiter now also covers HTTP Basic auth (used by OPDS/API clients), which previously let credential-guessing skip the limiter. It counts failures only, so real KOReader/OPDS devices are never locked out.
- First-run safety. The first admin account can only be created from your local network unless you set
SETUP_TOKEN— so a freshly-exposed instance can't be claimed by a stranger before you register. Rate limits now also use your real client IP behind Cloudflare. - Tighter access checks. A few metadata endpoints (read-status, ownership/rating, publisher list) now respect per-member genre restrictions, and login response timing no longer reveals whether a username exists.
- Proxied cover images are served with a safe content type; a couple of error messages no longer echo internal detail.
No user-facing behavior changes. Multi-arch images (amd64 + arm64) on GHCR; :latest == :1.18.1.
v1.18.0
Code quality + CI publishing
A full-codebase cleanup pass, plus a move to CI-based image publishing.
Code quality
- Dead code removed (unused functions, components, API methods, CSS, and two dependencies); duplicated logic consolidated (one pooled DB helper, one admin gate, shared cover-badge/format helpers).
- Typography now actually loads: the app's fonts were pulled from Google Fonts, which the app's own Content-Security-Policy blocked behind the proxy, so production silently fell back to system fonts. Fonts are now self-hosted (bundled at build, no external calls).
- Hardening: dev compose no longer defaults CORS to
*with credentials; the login?next=redirect only accepts same-origin paths. - Stale comments/config corrected; silent failure paths now log.
CI / publishing
- Images are now built and published by GitHub Actions (backend, web, proxy — multi-arch amd64 + arm64) on every push, with test gates first. Releases no longer depend on a local machine's registry login.
Multi-arch images on GHCR; :latest == :1.18.0.
v1.17.1
Fix
- Sync to Calibre works again. The v1.17.0 image slimming removed calibre's localization data, which
calibredbneeds at startup — every sync failed withFileNotFoundError. That directory is restored (the ~220 MB scipy/sympy/docs strip remains). Queued edits were never lost; they apply on the first sync after updating.
Verified end-to-end on the test stack: a queued edit synced cleanly via calibredb (synced=1, failed=0). Multi-arch images (amd64 + arm64) on GHCR.
v1.17.0
Performance
A full efficiency pass across the stack, measured before/after on a ~7,000-book library:
- Snappier everywhere. A shared PostgreSQL connection pool (requests used to open 7-12 fresh connections each), sidebar shelf counts computed with COUNT queries instead of building every smart shelf's full book list per page, batched lookups in Currently Reading / shelf pages / stats, and settings + auth caches. Sidebar endpoint: ~40ms → ~4ms; book list: ~30ms → ~7ms; home page render: ~115ms → ~38ms.
- Much lighter over the network. Grid covers are served as cached thumbnails (a 48-book page drops from ~11 MB of images to ~1.5 MB), and API/OPDS responses are gzip/zstd compressed (~8× smaller). Ideal for phones and remote access.
- App-like navigation. Clicking filters, sorts, shelves, and books now transitions client-side instead of reloading the whole page.
- OPDS devices (KOReader) no longer pay the full password-hashing cost on every request — catalog browsing is noticeably faster.
- Fixes: the service worker no longer caches visited (authenticated) pages as the offline shell; a leaked reader event listener and an over-eager import poll are fixed; the backend image is ~240 MB smaller.
Multi-arch images (amd64 + arm64) on GHCR.
v1.16.3
Library
- 'Read' checkmark on book covers. Books you've finished now show a small checkmark in the top-right corner of their cover — in the main library grid and on shelf pages (smart + manual, e.g. Highly Rated). The check uses your active theme's accent color. On a Digital + Physical book the format dots sit just to its left so nothing overlaps.
Multi-arch images (amd64 + arm64) on GHCR.
v1.16.2
Reading workflow
- Finishing a book removes it from Currently Reading on its own. Marking a book Read (manually, or via KOReader at ≥99%) now drops it out of Currently Reading while keeping its progress, reading stats, and read-history date — no more 'Mark as unread / reset' just to clear a finished book.
- Manual 'Read' now records today's date and queues it to Calibre's mapped date column (previously only the KOReader path supplied a date).
- One-step sync. 'Sync to Calibre' now folds in your latest KOReader reading first — finish a book at ≥99% and hit Sync, and its read status + finish date push to Calibre in a single step (no separate 'Queue reading updates').
Multi-arch images (amd64 + arm64) on GHCR.
v1.16.1
Smart shelves
- Genre restrictions now apply correctly for restricted users. Smart-shelf counts and contents agree: the restriction is applied inside the query before the row limit. 'Most Recent' shows a restricted user's N most-recent allowed books (instead of the allowed subset of the global N, which left it nearly empty), and 'Highly Rated' no longer reports a count while showing nothing. Native/physical books are excluded for genre-restricted users. Admin and unrestricted behavior is unchanged.
Multi-arch images (amd64 + arm64) on GHCR.
v1.16.0
Search
- Relevance-ranked full-text search (BM25). Searching inside book content now ranks by relevance (rare-word weighting + stemming, so "running" also finds "runs/ran") instead of arbitrary order. Backed by a private, contentless FTS5 index (~0.6 GB — no duplicate of Calibre's text) that builds in the background and stays in sync automatically; falls back to a simple match while building.
- Quoted exact-phrase search. Wrap a phrase in "quotes" to match those words exactly, in order; otherwise all your words are matched, best first. A tip in the search UI explains it.
- Access-scoped. For genre-restricted users, ranking, counts, and excerpts are all confined to their allowed books.
Multi-arch images (amd64 + arm64) on GHCR.
v1.15.0
Library
- Remove a physical copy from the web. A Calibre book flagged as Digital + Physical now shows a "remove physical" link next to the badge (admin-only, with a confirm). It drops the physical flag while keeping the digital book — the web counterpart to flagging a book physical from the iOS app (v1.14.0).
Multi-arch images (amd64 + arm64) on GHCR.
v1.14.0
Library
- Flag a Calibre book as physically owned. New
PUT /api/goodreads/ownership/{book_id}(admin-only) marks a Calibre (digital) book as also owned in print, so it shows as Digital + Physical everywhere — no duplicate native entry needed. It upsertsbook_ownershipthe same way the Goodreads CSV import does, and the iOS delta sync + web pick it up automatically.
Multi-arch images (amd64 + arm64) on GHCR.