Library and shelf — opt-in Kobo sync subset #3

Merged
arne merged 8 commits from shelf into main 2026-04-11 08:29:29 +02:00
Owner

Plan 2.5 of 4. Introduces the library/shelf distinction so the user can be deliberate about what's on the Kobo.

What's in here

  • Schema: books.shelved_at INTEGER (nullable). Non-null = on the shelf. Edited into 001_initial.sql directly since nothing's deployed.
  • Store: ShelveBook, UnshelveBook, ShelvedBooks. All other SELECTs updated to include the new column.
  • /kobo page renamed to /shelf; the page now lists shelved books first, then the Kobo register/regenerate UI below.
  • Library list (/) shows every book and marks shelved ones with a small italic 'shelf' tag in oxblood.
  • Book detail page gains a 'Shelve →' (or 'Remove from shelf →') action.
  • Page-nav: library / shelf / errata.
  • New routes: POST /book/{uuid}/shelve, POST /book/{uuid}/unshelve. Both gated by RequireSession + RequireOrigin.
  • Spec updated.

Out of scope

  • Plan 3: the Kobo sync API. The shelf is currently a flag that nothing reads — plan 3's snapshot algorithm will filter on `WHERE shelved_at IS NOT NULL`.

Test plan

  • go test ./... -race clean across all 8 packages
  • Hands-off bootstrap: bogus OIDC issuer fails at discovery, shelved_at migration applied cleanly
  • Full smoke (you, after merge): drop a book, confirm it lands in / but not /shelf, click into book detail, hit Shelve, confirm it now shows on /shelf and the library list marks it

Notes

  • Internal API paths keep /api/kobo/... (it's the Kobo's protocol, not ours). Only user-facing chrome talks about shelves.
  • Default for new imports: off the shelf. You drop a file, it lands in the library, you decide whether to shelve it.
  • Shelving doesn't bump updated_at — plan 3's snapshot diffing is presence-driven.

Plan: docs/superpowers/plans/2026-04-11-shelf.md

Plan 2.5 of 4. Introduces the library/shelf distinction so the user can be deliberate about what's on the Kobo. ## What's in here - Schema: `books.shelved_at INTEGER` (nullable). Non-null = on the shelf. Edited into 001_initial.sql directly since nothing's deployed. - Store: `ShelveBook`, `UnshelveBook`, `ShelvedBooks`. All other SELECTs updated to include the new column. - /kobo page renamed to /shelf; the page now lists shelved books first, then the Kobo register/regenerate UI below. - Library list (/) shows every book and marks shelved ones with a small italic 'shelf' tag in oxblood. - Book detail page gains a 'Shelve →' (or 'Remove from shelf →') action. - Page-nav: library / shelf / errata. - New routes: POST /book/{uuid}/shelve, POST /book/{uuid}/unshelve. Both gated by RequireSession + RequireOrigin. - Spec updated. ## Out of scope - Plan 3: the Kobo sync API. The shelf is currently a flag that nothing reads — plan 3's snapshot algorithm will filter on \`WHERE shelved_at IS NOT NULL\`. ## Test plan - [x] go test ./... -race clean across all 8 packages - [x] Hands-off bootstrap: bogus OIDC issuer fails at discovery, shelved_at migration applied cleanly - [ ] Full smoke (you, after merge): drop a book, confirm it lands in / but not /shelf, click into book detail, hit Shelve, confirm it now shows on /shelf and the library list marks it ## Notes - Internal API paths keep /api/kobo/... (it's the Kobo's protocol, not ours). Only user-facing chrome talks about shelves. - Default for new imports: off the shelf. You drop a file, it lands in the library, you decide whether to shelve it. - Shelving doesn't bump updated_at — plan 3's snapshot diffing is presence-driven. Plan: docs/superpowers/plans/2026-04-11-shelf.md
arne merged commit 67a5e28a0a into main 2026-04-11 08:29:29 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
arne/books!3
No description provided.