Files
bookhoard/cmd/server
John O'Keefe 208fc2c4d6 fix(server): kobo markup panic — wire LibraryService into the test harness, guard typed-nil resolver
TestProgressWeb_KoboIntegration 500s'd on every markup with a
last-read-place bookmark: the panic-recovered stack was a nil pointer
dereference in LibraryService.ResolveMediaPath (s.db deref), reached
from KoboHandler.convertKoboCFIToStandard during kepub CFI conversion.

Two-layer bug:

1. Test harness (root cause): the router.Config built in
   test_helpers_test.go omitted LibraryService, so router/sync.go's
   SetLibraryService(cfg.LibraryService) stored a nil
   *services.LibraryService in the interface field. Production wiring
   (main.go:246) was always correct.
2. Latent trap (hardening): `h.libraryService != nil` at the
   convertKoboCFIToStandard call site can never catch a typed nil —
   an interface holding a nil *LibraryService is non-nil. ResolveMediaPath
   now degrades with a "library service not configured" error instead
   of panicking on a nil receiver; callers already handle the error
   by skipping CFI conversion.

Harness-only fix, zero production behavior change: the endpoint now
returns a clean 200 with the position saved wherever kepub conversion
is unavailable instead of a panic-recovered 500.

Verified: TestProgressWeb_KoboIntegration passes all three subtests
(401 unauthenticated, ReadingSync→last-read-place percentage
preservation, last-read-place without prior ReadingSync) and on
immediate rerun — previously it failed every run.
2026-10-09 14:53:48 -04:00
..