feat(sync): position history + one-click restore#137
Closed
bndct-devops wants to merge 1 commit into
Closed
Conversation
New position_history table (additive, created by the startup create_all
like every other table): upsert_position — the single choke point all
position writers go through — appends an entry whenever the position moves
meaningfully (>=0.2% or locator change; the idle heartbeat can't spam it),
pruned to the newest 40 per user+book.
GET /books/{id}/position-history lists the log + live position;
POST .../{hid}/restore sets the live position back. Restore is an explicit
override of the sticky-completion rule: recovering from a false 100% also
un-finishes the book (status/finished_at), or the position would come back
while the book stayed "read". The restore itself is logged, so it can be
undone the same way. Devices converge on their next pull.
UI: history button on the book page's Reading Stats header opens the log
with per-entry Restore; refreshes stats + status pill after.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overnight run PR 6/12 — stacked on #136; merge in order. The one DB change in the stack (additive table).
What
The safety net under position sync:
TomeSyncPositionis a single overwritten row, so one bad write — a device falsely jumping a book to 100%, a mis-tap that propagated — was unrecoverable. Now:position_historytable (additive; created on startup bycreate_all, same as every other table — no Alembic migration needed, nothing destructive). Written insideupsert_position, the one choke point every position writer already goes through (device PUT, web autosave, admin flows), only when the position moves ≥0.2% or the locator changes — the ten-page idle heartbeat can't spam it. Pruned to the newest 40 per user+book.GET /books/{id}/position-history— the log plus the live position;POST /books/{id}/position-history/{hid}/restore— sets the live position back to that entry.finished_atcleared). Without this the position would come back but the book would stay "read" — the exact scenario the feature exists for. Restores are themselves logged, so a restore can be undone.Verification