Add migration columns to media_highlights, media_notes, and media_bookmarks
for cross-device annotation sync:
- dedup_key: SHA-1 of normalized selection text + bucketed position, used
as the stable cross-device identity for annotations
- last_modified_at / last_modified_source: edit clock for LWW resolution
and cross-source conflict detection
- deleted / deleted_at: sticky tombstone columns for delete-wins semantics
with a 30-day TTL before rows are physically purged
- note_text on highlights: stores attached notes from KOReader entries that
have both selected text and a user note
- Location columns on bookmarks (cfi_position, percentage_location,
epubcfi_location, chapter_reference, paragraph_reference)
- device_sync_data JSONB on all three tables: stores per-device native
identifiers (e.g. KOReader pos0/datetime, Kobo bookmark_id) so each
device can locate and manipulate its own copy of an annotation
Add partial unique indexes on (user_id, media_item_id, dedup_key) where
deleted = FALSE to enforce one active annotation per dedup key.
Add tombstone purge indexes on (deleted, deleted_at) for efficient GC.
New queries:
- GetByDedupKey for all three tables (returns active or most-recent tombstone)
- CreateFull / UpdateForSync for all three tables (populate sync columns)
- TombstoneByDedupKey / TombstoneByID for all three tables
- PurgeExpired* for all three tables (GC past TTL)
- GetActiveAnnotationsForBook (filtered union of highlights + notes)
- GetTombstonedAnnotationsForBook (union of all 3 deleted within TTL)
- GetMediaBookmarks with deleted filter
- GetMediaBookmark (singular) with deleted filter
- Added deleted=FALSE filter to GetMediaHighlights, GetAnnotationsForBook
- CreateAutoResolvedSyncConflict (INSERT with resolution_status='auto_resolved')
Regenerated database code after sqlc version upgrade from v1.30.0 to
v1.31.1. No functional changes — only the version header in generated
files was updated.
Files: db.go, models.go, querier.go, queries.sql.go
This major update implements a complete user annotation system:
## 🎯 New Features
- User notes with position tracking for media items
- Text highlighting with customizable colors
- Highlight-note associations for detailed annotations
- Full CRUD API for both notes and highlights
- Backward compatibility with existing ebook endpoints
## 📊 Database Changes
- Add media_notes table (id, media_item_id, user_id, content, position, timestamps)
- Add media_highlights table (id, media_item_id, user_id, selection_text, start/end_position, color, optional note_id)
- Add foreign key relationships with CASCADE deletes
- Add proper indexes for performance
- Add database schema views for ebook backward compatibility
## 🔧 API Implementation
- Complete REST API endpoints for notes and highlights
- JWT authentication with proper middleware bypass
- Request validation with meaningful error responses
- UUID validation and type safety
- Support for hex color codes in highlights
## 🧪 Testing & Documentation
- Comprehensive test suite covering authentication scenarios
- Bruno API collection for manual testing
- Detailed testing guide with troubleshooting
- Updated documentation in README and TESTING.md
## 📁 Backward Compatibility
- Existing ebook endpoints continue working
- Database views maintain API contracts
- No breaking changes for existing integrations
The annotation system is now fully functional and ready for production use.
- Add MediaNotes and MediaHighlights model structs with pgx v5 types
- Add EbookNotes and EbookHighlights for backward compatibility
- Add complete CRUD SQL queries for notes and highlights
- Add database connection pool function using pgx v5
- Generate sqlc code for new annotation functionality
- Rename project from 'bookmann' to 'shelf'
- Move all backend/ contents to root level (flatten structure)
- Update Go module name from 'bookmann' to 'shelf'
- Update all import paths to use new 'shelf' module
- Update Dockerfile to work without backend/ subdirectory
- Update docker-compose.yml to use new structure and rename containers
- Update .gitignore for new file paths
- Update README.md with new project name and structure
- Regenerate database code with new module imports