Releases: serabi/pagekeeper
v0.1.9
v0.1.8
Bug fixes
- Storyteller: Handle DNS failures cleanly — connection backoff prevents log spam and repeated failed requests when Storyteller is unreachable
- KoSync: Use
datetime.mininstead of0forlast_updatedfallback - Sync manager: Treat
check_connection()returningFalseas a failure (previously only caught exceptions)
v0.1.7
Security, KoSync refactor, suggestions & Grimmory rename
Security
- Non-root Docker container — app now runs as
appuser(uid 1000) instead of root - Rate limiter for KoSync auth endpoints — token bucket throttling prevents brute-force attempts
- XML security — added
defusedxmlfor safe XML parsing - Secret redaction expanded from 3 to 12 environment variables in error logs
- Session hardening —
SameSite=Lax,HttpOnlycookies,X-Frame-OptionsandX-Content-Type-Optionsheaders - Path traversal guards on file-serving endpoints
- XSS fixes on KoSync API endpoints (Snyk SAST findings)
KoSync Refactor
- Monolith decomposition —
kosync_server.py(1000+ lines) split into 5 focused modules: protocol routes, auth, admin dashboard, business logic service, and debounce manager - KoSync Document Management page — new dedicated UI for triaging documents (healthy, needs attention, stale 30+ days) with search, linking, and deletion
- Debounce manager — batches rapid KoReader PUT events before triggering sync cycles
- Auto-discovery resilience — better error handling, misleading log fixes, correct UTC timestamps
Suggestions
- Decoupled from Audiobookshelf — suggestions now work for KoReader-only, Storyteller, and Grimmory users without ABS configured
- Cross-ebook pairings — match KoReader documents to Grimmory/Storyteller ebooks for position sync
- Dashboard suggestion banner — high-confidence suggestions surface on the home page with one-click mapping
- Suggestion count badge in navbar
- Match scoring fix — no longer penalizes ebook sources missing author metadata
Hardcover
- Increased API timeouts (10s → 20s)
distinct_ondedup prevents duplicate user book entries- Format label mapping for edition types
- Read ID caching to reduce API calls during sync
Booklore → Grimmory Rename (closes #49)
- Full rename across codebase, database, and UI
- Alembic migration handles table, column, constraint, settings, and data renames
- Legacy
booklore_cache.jsonfiles are auto-migrated on upgrade
Code Quality
- Ebook utils decomposition —
ebook_utils.pysplit intokoreader_xpath.pyandlocator_search.pywith facade pattern - Shared constants module — magic strings extracted to
src/utils/constants.py - Test suite expanded to 805 tests — 7 new test files covering debounce, rate limiter, KoSync service, KoReader XPath, locator search, and Grimmory client
- Dead code cleanup, unused import removal, and null-safety fixes across 196 files
Bug Fixes
- Fixed
NOT INwith nullable column silently skipping stale suggestion cleanup - Fixed cached Hardcover read_id overwriting actual start/finish dates
- Fixed JSON
nullbecoming literal string"None"in BookFusion uploads - Fixed BookFusion highlight unlink silently succeeding when book not found
- Fixed XPath offset calculation when falling back to parent text nodes
- Fixed BS4/LXML text ordering divergence in hybrid anchor mapping
- Fixed
datetime.utcnow().timestamp()using local timezone instead of UTC
v0.1.6
Frontend overhaul, testing expansion & UX improvements
This release focuses on frontend code quality, test coverage, and UX polish across the app.
Frontend
- Extracted frontend from 5 templates into 7 external files, making the codebase easier to maintain and debug
- Shared utility library (
utils.js) put in place to replace 6+ duplicated implementations
Testing
- Test suite expanded from 461 to 719 tests (+258 new tests across 17 files)
- New coverage for: BookFusion routes, logs routes, dashboard errors, matching errors, reading blueprint errors, API errors, BackgroundJobService, ReadingDateService, BookMetadataService, ReadingService, ClientPoller, settings hot-reload, sync concurrency, and more
- Canonical
MockContainer, shared pytest fixtures, andmake_test_book/make_test_statehelpers for consistent test authoring
UX Improvements
- Smart mode defaults — auto-detect which services are configured and default to available options
- Service logo placeholders — when book covers are unavailable, show the service logo instead of a broken image
- Portrait covers — ebook cards now display portrait-oriented covers instead of square
- Book metadata caching — author and subtitle are cached locally for faster page loads
- Suggestions page — inline refresh, modal errors, hidden when ABS is not configured
- Batch match — ebook-only support, de-centered from ABS
- Storyteller UI hidden when unconfigured
- Cover proxy — fixed streaming and N+1 query, added fallback for missing covers
Bugs Fixed
- Dashboard auto-refresh pausing permanently after closing a modal via button click
- BookFusion covers not loading due to broken
onerrorfallback - Offset/pagination bug with missing null guards
- Silent error handling in multiple catch blocks (now surfaces actual error messages)
- Dead code cleanup (
lastLogTimestamp, unusedgetattrcalls) - Live log fetch failures now display inline errors instead of failing silently
- Log filter state detection replaced fragile DOM text matching with proper boolean flag
Upgrading from v0.1.5
No database migrations in this release. Standard container update:
docker compose pull && docker compose up -dv0.1.5
Decouple data model from Audiobookshelf ID (#20)
PageKeeper no longer requires Audiobookshelf. Technical tldr: Books now use an internal integer primary key (book.id) instead of the ABS library item ID (abs_id). This enables better standalone ebook tracking, setups that only use something like BookFusion, KoSync/KoReader, and Hardcover, and other various configurations without ABS. As apps like Grimmory progress this will also allow using something like Grimmory as your main audiobook driver instead of ABS.
What changed (the details)
- New integer primary key on the
bookstable - all 11 child tables (states, jobs, kosync_documents, hardcover_details, etc.) now referencebook.idvia foreign key abs_idis now no longer needed - books can exist without an Audiobookshelf counterpartabs_titlerenamed totitle- the column name no longer implies ABS ownership- Backward compatible - existing ABS-linked books keep their
abs_idand all external integrations (KoSync, Hardcover, Storyteller, Booklore) continue to work unchanged - Write-suppression and debounce keyed by
book.id- fixes a bug where ebook-only books (withabs_id=None) would collide into a single cache/debounce entry - KoSync document linking now correctly sets both
linked_book_idandlinked_abs_id, fixing an issue where freshly linked documents were invisible in the admin UI get_book_by_abs_id(None)guarded - returnsNoneimmediately instead of matching NULL rows- Schema creation gated on migration success -
Base.metadata.create_all()no longer runs after a failed Alembic migration, preventing half-built schemas
Upgrading from v0.1.4
⚠️ Back up your database before upgrading.This release runs 7 schema migrations that restructure the primary key and foreign keys across the entire database. The migrations are designed for production SQLite and include re-run safety, but a backup is strongly recommended.
cp /path/to/pagekeeper/data/database.db /path/to/pagekeeper/data/database.db.v0.1.4.bak
Migrations run automatically on container startup. No manual steps required after the backup. Please report any bugs you run into when updating.
Other Bugs Fixed
- Reading detail page: all action buttons broken due to undefined
_rdAbsIdJS variable - KoSync debounce: ebook-only books collapsed into single debounce entry
- Client poller: poll cache and write-suppression collisions for ebook-only books
- KoSync admin: freshly linked documents not appearing in linked list
- Database startup:
create_all()could mask migration failures
v0.1.4
v0.1.3
v0.1.2
What's New in 0.1.2
Continued forking and updating PageKeeper including:
- Hardcover sync overhaul - Bidirectional status/progress sync, journal push, reading date pull/push, sync log, edition selection
- Reading tracker - Reading detail pages with journal, manual progress, ratings, and dates
- TBR list - To Be Read list with Open Library enrichment, Hardcover import, detail pages, and mark-as-read flow
- BookFusion integration - Highlight sync and shelf sync
- Dual Booklore servers - Multi-instance support
- Storyteller improvements - Direct submission from match page, force mode, status badges, and native word-level alignment
- UI/UX rework - Redesigned match page, settings, cover picker, and suggestions page
- Architecture fixes - Extracted services (Suggestion, BackgroundJob, ProgressReset, Reading, HardcoverService, StatusMachine) from monolithic files
- Security hardening - Sanitized exception logging, path traversal protection, XSS escaping, CVE-2025-43859 fix
- Infrastructure - Docker distribution prep with ARM64 docs, CI linting, fast test runner, 429 tests
v0.1.1
v0.1.1 — Security, Integrations, Reading Tracker, and TBR
- Hardcover bidirectional sync — Reading status and progress now syncs both directions with Hardcover
- Hardcover journal push — Journal notes are pushed to Hardcover as user journal entries
- Hardcover reading dates — Historical
started_at/finished_atdates tracked and synced - Hardcover sync log — New sync log tab showing all operations with status, direction, and timestamps
- BookFusion integration — Upload books, sync highlights via Obsidian plugin API, save highlights to reading journals
- Reading tracker — Reading detail page with journal entries, manual progress, ratings, read counts, and yearly reading goals
- TBR (To Be Read) list — Want to Read tab with search, manual add, Hardcover import, enrichment, and detail pages
- Storyteller submission service — Submit books directly to Storyteller for narrated EPUB3 creation
- Suggestions system — Dedicated page with card grid, socket-driven discovery, and Dismiss/Link/Never Ask actions
- Cover management — Cover picker modal, custom cover URL support, Hardcover cover search
- Architecture decomposition — Extracted SuggestionService, BackgroundJobService, ProgressResetService, ReadingService, BookMetadataService, and database repositories
- Dashboard UX rework — Processing section with progress bars, status filters, and live polling
Full Changelog: v0.1.0...v0.1.1