Commit Graph
112 Commits
Author SHA1 Message Date
john-okeefe 924254689c feat(sync): add bulk book linking and auto-linking features
- BulkLinkBooks: manually link multiple unlinked books to media items
- AutoLinkBooks: automatically link books above confidence threshold
- GetUnlinkedBookSuggestions: get match suggestions for specific unlinked book
- Support batch operations with individual result tracking
- Configurable confidence thresholds and limits
2026-02-01 12:15:44 -05:00
john-okeefe c1b3f51380 feat(conflicts): add bulk resolve and dismiss operations
- BulkResolveConflicts: resolve multiple conflicts with configurable strategies
  - most_recent: choose most recently updated source
  - highest_progress: choose source with highest reading progress
  - manual: use specified winning source
- BulkDismissConflicts: dismiss multiple resolved conflicts at once
- ResolveHighestProgress: convenience endpoint for high-progress strategy
- Return detailed results for each operation
2026-02-01 12:15:42 -05:00
john-okeefe eb97a0ef4b feat(analytics): add reading statistics dashboard
- Add reading stats endpoint with daily/monthly history
- Add device usage statistics (sync count, time spent)
- Add popular books view with completion rates
- Server-side rendered analytics page with HTMX
- Date range filtering for reading history
2026-02-01 12:15:38 -05:00
john-okeefe f23b6d35e9 feat(database): add analytics and book matching queries
Add analytics queries:
- GetUserReadingHistory: detailed reading history with device info
- GetUserDeviceUsage: device usage statistics (sync count, time spent)
- GetPopularBooks: most read books with completion rates

Add book matching queries:
- GetUnlinkedBookByID: fetch single unlinked book
- DeleteUnlinkedBook: remove resolved unlinked book
- ListUnresolvedUnlinkedBooks: paginated list of unresolved books
2026-02-01 12:15:33 -05:00
john-okeefe ec5a961f6c feat(conversion): add EPUB to KEPUB conversion service with kepubify
- Install kepubify binary in Dockerfile for on-the-fly conversion
- Add conversion service with caching layer (24hr TTL)
- Support KEPUB downloads through OPDS endpoint
- Cache converted files to reduce processing overhead
- Add environment configuration for cache directory and tool path
2026-02-01 12:15:28 -05:00
john-okeefe 6e843c93d0 test(collections): add comprehensive rule evaluation test suite
Add extensive unit tests for collection rule matching logic:

Test Coverage (30+ tests):
1. Rule Evaluation Tests:
   - Equals operator (match and no match)
   - Not equals operator (match and no match)
   - Contains operator (case-insensitive)
   - Not contains operator
   - Starts with operator
   - Ends with operator
   - Greater than operator (numeric)
   - Less than operator (numeric)
   - NULL field handling

2. Comparison Function Tests:
   - Case-insensitive string matching
   - Empty string edge cases
   - Numeric edge cases (0, negative, large numbers)
   - Type conversion validation

3. Multi-Rule Tests:
   - Matches first rule
   - Matches second rule (first fails)
   - No matches across all rules
   - Empty rules array

4. Complex Rule Scenarios:
   - Multiple conditions on same book
   - Different field types (genre, author, year, series)
   - Various operators tested
   - Table-driven test for 8 scenarios

5. Edge Cases and Error Handling:
   - Invalid operator returns false
   - Non-existent field returns false
   - Invalid numeric strings handled
   - Type conversion failures

Test Structure:
- Clear test names explaining what's being tested
- Assertion messages explain expected vs actual
- Uses testify/assert for better error messages
- Table-driven tests for multiple scenarios
- Comprehensive edge case coverage

Code Coverage:
- evaluateRule() function
- compareValues() function
- checkRulesAgainstBook() function
- All operators: equals, not_equals, contains, not_contains,
  starts_with, ends_with, greater_than, less_than
- All field types: genre, author, series, copyright_year

Test Results:
- All 30+ tests passing
- Coverage of critical collection rule logic
- Prevents regressions in rule matching
- Validates edge case handling

This test suite ensures the collection auto-assignment
feature works correctly for all supported rule types and operators.
2026-02-01 01:02:42 -05:00
john-okeefe 40c732481a feat(collections): add real-time updates via WebSocket (Limitation #4)
Implement real-time collection updates when books are added/removed:

Backend Changes:
- Added connManager to CollectionHandler struct
- Updated constructor to accept ConnectionManager
- Updated all NewCollectionHandler() calls in ebook.go and main.go
- Added WebSocket broadcasts in AddBooks() handler
- Added WebSocket broadcasts in BulkRemoveBooks() handler
- Broadcasts collection_updated events with:
  - collection_id: Which collection changed
  - action: books_added or books_removed
  - book_ids: Array of affected book IDs
  - count: Number of books changed

Frontend Changes:
- Added WebSocket connection in collections UI
- connectWebSocket() establishes connection to /ws/sync
- Listens for collection_updated events
- Shows toast notification on collection change
- Auto-reloads page after 1 second to show updated book list
- Auto-reconnect on disconnect (5s delay)
- Error handling for WebSocket failures

WebSocket Event Format:
{
  "type": "collection_updated",
  "timestamp": "2026-02-01T12:00:00Z",
  "data": {
    "collection_id": "uuid",
    "action": "books_added",
    "book_ids": ["uuid1", "uuid2"],
    "count": 2
  }
}

User Experience:
- When another user adds books to a collection, all connected clients see:
  1. Toast notification: "Collection updated: books_added (2 books)"
  2. Page auto-refreshes after 1 second
  3. Updated book list displays
- Same for book removal
- Works across multiple browser tabs/devices
- No manual refresh needed

Technical Notes:
- Broadcasts to ALL connected WebSocket clients
- Client-side filtering by collection_id
- Existing progress/conflict broadcasts continue to work
- Connection manager handles broadcast distribution

Resolves Limitation #4: Real-time Collection Updates
2026-02-01 00:54:41 -05:00
john-okeefe 508bfb0387 feat(collections): implement bulk add and remove books (Limitations #2 & #5)
Complete bulk operations for collections management:

BULK ADD BOOKS:
- Implemented searchBooks() with real API integration
- Multi-select checkboxes for book selection
- SelectedBooks Set tracks chosen books
- AddSelectedBooks() sends array to existing endpoint
- Uses existing POST /api/collections/:id/books endpoint

BULK REMOVE BOOKS:
- New endpoint: POST /api/collections/:id/books/bulk-remove
- Checkboxes on each book card for selection
- BooksToRemove Set tracks selections
- Live counter showing selected count
- BulkRemoveBooks() handler removes all in one API call
- More efficient than N individual DELETE requests

Frontend Changes:
- Selected counter badge shows number selected
- Bulk remove button (enabled when books selected)
- Checkboxes on all books for multi-select
- Confirmation dialog for bulk operations
- Toast notifications with counts

Backend Changes:
- BulkRemoveBooks() handler in collections.go
- Accepts book_ids array, returns removed/total counts
- Iterates and removes, counting successes
- Route: POST /api/collections/:id/books/bulk-remove

API Request:
{
  "book_ids": ["uuid1", "uuid2", "uuid3"]
}

API Response:
{
  "removed": 3,
  "total": 3
}

Tests Added:
- TestCompareValues_* (existing)
- TestEvaluateRule_* (existing)

Resolves Limitations #2 (Bulk Operations) and #5 (Bulk Remove)
2026-02-01 00:52:09 -05:00
john-okeefe 592ccddf65 feat(collections): implement rule testing/preview functionality (Limitation #1)
Add ability to test collection rules before saving:
- New API endpoint: POST /api/collections/test-rules
- Evaluates rules against all media items
- Returns matching books with reasons
- Supports all operators: equals, contains, greater_than, etc.
- Works with all fields: genre, author, series, etc.

Backend Implementation:
- TestRules() handler in collections.go
- evaluateRule() matches book properties against rule criteria
- compareValues() handles string/numeric comparisons
- Case-insensitive matching for contains operator

Frontend Integration:
- Updated testRule() function in collection_rules.templ
- Displays matching books with covers and authors
- Shows match reason (which rule criteria matched)
- Limits preview to 20 results with count indicator

Tests Added:
- TestCompareValues_Equals: Exact match validation
- TestCompareValues_Contains: Substring matching
- TestCompareValues_GreaterThan: Numeric comparison
- TestCompareValues_NotEquals: Negation
- TestEvaluateRule_Genre: Genre field matching
- TestEvaluateRule_Author: Author field matching
- TestEvaluateRule_CopyrightYear: Year field matching

API Request Format:
{
  "rules": [{
    "field": "genre",
    "operator": "equals",
    "value": "Science Fiction"
  }]
}

API Response Format:
{
  "matches": [{
    "media_item_id": "uuid",
    "title": "Book Title",
    "author": "Author Name",
    "cover_image_path": "/path/to/cover.jpg",
    "match_reason": "Matched rule: genre equals Science Fiction"
  }],
  "total": 42
}

Resolves Limitation #1: Rule Testing Preview
2026-02-01 00:49:22 -05:00
john-okeefe ed31755a54 feat(api): add collections and device mapping API endpoints
Add comprehensive API support for Phase 9 features:

Collections API (/api/collections):
- GET /collections: List all user collections
- POST /collections: Create new collection
- GET /collections/🆔 Get collection details
- PUT /collections/🆔 Update collection
- DELETE /collections/🆔 Delete collection
- GET /collections/:id/books: Get books in collection
- POST /collections/:id/books: Add books to collection
- DELETE /collections/:id/books/:bookId: Remove book from collection

Device Shelf Mapping API (/api/devices/:id/collections):
- GET: Get all collection-to-shelf mappings for device
- POST: Create new mapping
- PUT /:collectionId: Update mapping
- DELETE /:collectionId: Delete mapping

Book Matching API:
- POST /sync/books/query: Query books by identifiers
- POST /devices/:deviceId/sync/link-book: Manual book linking
- GET /devices/:deviceId/sync/unlinked-books: List unmatched books
- GET /devices/:id/file-aliases: Get device file aliases
- POST /devices/:id/file-aliases: Create file alias
- PUT /devices/:id/file-aliases/:aliasId: Update alias
- DELETE /devices/:id/file-aliases/:aliasId: Delete alias
- GET /books/match: Search for book matches

All new endpoints - no existing APIs modified.
2026-02-01 00:26:27 -05:00
john-okeefe b1ca813ba4 feat(collections): add helper functions for template rendering
Add data retrieval helpers for SSR template rendering:
- GetDeviceMappingsData: Fetch device shelf mappings for device settings UI
- GetUserCollectionsList: Get all user collections for dropdowns and listings
- GetCollectionData: Get single collection with metadata
- GetCollectionBooksData: Get books in a collection

These functions support the Phase 9 frontend features by providing
efficient data access for template rendering without modifying
existing API endpoints.
2026-02-01 00:26:20 -05:00
john-okeefe 7828371c9c feat(progress): implement progress visualization page with sync source tracking (Phase 9-3)
Add progress list page showing reading progress across all devices:
- GetAllProgress API endpoint: Returns all user progress with media details
- GetAllProgressData helper: Fetches progress data for SSR rendering
- ProgressWithMedia struct: Combines progress with book metadata
- Progress page template: Displays progress bars, device icons, sync sources

Features:
- Visual progress bars with percentage
- Device-specific icons (Kobo, KOReader, Web, Mobile)
- Last sync timestamp and device attribution
- EPUB CFI location display
- Cover image support with fallback
- Responsive grid layout

This gives users a unified view of their reading progress across all synced devices.
2026-02-01 00:25:15 -05:00
john-okeefe b3c0c0c225 feat(handlers): Add GetDevicesData helper and update devices template for SSR
- Add GetDevicesData() to DeviceHandler (returns raw data, not JSON)
- Update devices template signature to accept pre-rendered data
- Add server-side rendering of devices and pending registrations
- Update JavaScript to use location.reload() after CRUD operations
- Remove getDeviceIcon dependency on JavaScript function
- Use templ if/else instead of ternary operators for device status

Preserves all API endpoints and backward compatibility
2026-01-31 22:42:21 -05:00
john-okeefe 86eaee5a25 lint(handlers): Use strings.EqualFold for case-insensitive comparison
Fix SA6005 staticcheck warning in OPDS handler
2026-01-31 22:34:48 -05:00
john-okeefe 3d20e802e6 feat(opds): Add OPDS feed generation library
- Add OPDS feed generation for Kobo compatibility
- Support device catalog, search, download, navigation
- Add format conversion support
2026-01-31 22:32:37 -05:00
john-okeefe 964a4583ab feat(services): Add book matching and collection services
- Add book matching service for intelligent book deduplication
- Add collection service for collection management
- Add test files for book matching and collections
2026-01-31 22:32:28 -05:00
john-okeefe 6495cc2c7c feat(handlers): Add OPDS, collections, book matching, and sync handlers
- Add OPDS handler for device catalog and book downloads
- Add collections handler for collection CRUD
- Add book matching service for cross-device book linking
- Add sidecar handler for Kobo metadata sync
- Add sync handler for device synchronization
2026-01-31 22:32:23 -05:00
john-okeefe d28002e4cb feat(sync): Add Kobo/Koreader sync and conflict handling
- Add Kobo markup/sync endpoints for bookshelves
- Add Koreader progress sync with SHA-256 support
- Add sync conflict detection and resolution
- Update ebook scanner for better file matching
2026-01-31 22:32:09 -05:00
john-okeefe 63008001c6 feat(db): Add kobo_shelves and device catalog tables
- Add kobo_shelves table for Kobo device shelves management
- Add device_shelf_mappings for collection<->device shelf mappings
- Update device_catalogs with better ContentId tracking
- Add indexes for performance
2026-01-31 22:32:04 -05:00
john-okeefe cd8f313b16 feat(handlers): Add helper methods for hybrid SSR
- Add GetPendingRegistrationsData() to DeviceHandler
- Add GetQueueData() to QueueHandler
- Add template types: DeviceData, PendingRegistrationData, ConflictData, QueueItemData
- Add collection types: CollectionData, CollectionDetailData, BookData

All changes are non-breaking and preserve API compatibility
2026-01-31 22:31:33 -05:00
john-okeefe a7f2b83bdd Integrate sync queue system and device cap API
- Start queue processor as background goroutine
- Initialize and register queue handler
- Add queue management routes (7 endpoints)
- Update KOReader handler to use checkpoint sync mode
- Add device cap management route (PUT /api/auth/users/:id/max-devices)
- Register all new endpoints with proper middleware
2026-01-31 13:06:56 -05:00
john-okeefe 50c632babf Update SSL/TLS handling for Docker reverse proxy deployments
- Disable HTTPSRedirectMiddleware (SSL handled by proxy)
- Keep SSLProxyMiddleware for X-Forwarded-* headers
- Add note about Docker deployment architecture
- Database connections use sslmode=disable
- No redirect needed for reverse proxy setup
2026-01-31 13:06:50 -05:00
john-okeefe 5039071ea3 Add admin-configurable device cap per user
- Add max_devices column to users table (default: 10)
- Add UpdateUserMaxDevices database query
- Add CountUserDevices database query
- Add UpdateUserMaxDevices handler with validation (1-100 devices)
- Add PUT /api/auth/users/:id/max-devices endpoint (admin only)
- Update UserList struct to include max_devices field
- Validate user ID format and max_devices range
- Return appropriate errors for invalid requests
2026-01-31 13:06:21 -05:00
john-okeefe 030d30a225 Add queue management API and database queries
- Add 7 new database queries for queue management
- GetStuckSyncQueueItems - Detect stuck items
- GetSyncQueueStats - Queue statistics
- GetNextRetryTime - Exponential backoff calc
- ListAllSyncQueueItems - Admin view
- IncrementSyncQueueAttempts - Retry counter
- Add queue handler with 7 REST endpoints
- GET /api/queue/devices/:id/stats - Queue statistics
- GET /api/queue/devices/:id/items - List device queue
- POST /api/queue/items/:id/retry - Retry failed item
- DELETE /api/queue/items/:id - Delete queue item
- DELETE /api/queue/devices/:id/clear - Clear device queue
- GET /api/queue/items - List all items (admin)
- Add full user/admin access control
2026-01-31 13:06:12 -05:00
john-okeefe 11ee4901a5 Add offline detection and recovery system (Phase 6)
- Implement OfflineDetector with 5-minute online threshold
- Add automatic device scanning (2-minute intervals)
- Add offline mode enforcement (disable sync)
- Add reconnection handling with priority item processing
- Add force reconnect API endpoint
- Add comprehensive offline detection tests
- Handle device offline/reconnected events
2026-01-31 13:06:05 -05:00
john-okeefe b9de7c48d5 Add sync queue system with exponential backoff retry logic (Phase 6)
- Implement SyncQueueProcessor with 5-second polling interval
- Add priority-based queuing (1-10 scale)
- Add exponential backoff retry logic (1m, 5m, 15m, 1h, 24h)
- Add stuck item detection (> 1 hour in processing state)
- Add batch processing (50 items per cycle)
- Add comprehensive test suite (15+ test cases)
- Test enqueue/dequeue, priority ordering, retry logic, concurrent operations
2026-01-31 13:06:00 -05:00
john-okeefe 2d2d643873 Add sync conflict detection and resolution system
Implement conflict detection for concurrent reading progress updates from different devices. Adds conflict management endpoints for listing, viewing, and resolving conflicts.

- Add ConflictHandler with CRUD endpoints for conflict management
- Implement automatic conflict detection in KOReader progress updates
- Add WebSocket broadcast for real-time conflict notifications
- Add database query for listing user conflicts by status
- Add integration tests and Bruno API test collection
2026-01-31 11:45:52 -05:00
john-okeefe d440e55f05 Update handlers to work with UUID refresh tokens
- Add parseTokenUUID() helper to convert string to pgtype.UUID
- Update RefreshAccessToken to parse token string to UUID before validation
- Update Logout to parse token string to UUID before revoking
- Update CreateRefreshToken to pass UUID directly to database
- Update auth.go: fix return value order from CreateRefreshToken
- Remove unnecessary comments for cleaner code
2026-01-31 11:44:35 -05:00
john-okeefe db5d51e77e Regenerate database code for UUID token support
- Update models: RefreshTokens.Token now pgtype.UUID
- Update querier: GetRefreshToken/RevokeRefreshToken accept pgtype.UUID
- Regenerate queries.sql.go via sqlc after schema change
2026-01-31 11:44:26 -05:00
john-okeefe 42c3168fcf feat: add server sync to Kobo endpoint and media routes 2026-01-31 00:29:39 -05:00
john-okeefe fef41dc168 feat: add media handler for book download and shelf management 2026-01-31 00:29:38 -05:00
john-okeefe cd240d3054 feat: add Kobo shelf and entitlement SQL queries 2026-01-31 00:29:38 -05:00
john-okeefe ed336c6c41 feat: add Kobo entitlements and shelves models 2026-01-31 00:29:37 -05:00
john-okeefe a3aa9f67ac feat: add Kobo device sync support and fix device route protection
- Add Kobo sync handler with markup, bookmark, analytics, and initialization endpoints
- Add Kobo integration tests and Bruno API test collection
- Move device approve/reject routes from public to protected routes
- Enhance test infrastructure with DATABASE_URL support and helper functions
- Fix device GetDevice handler nil pointer handling
- Clean up test reports and session files
2026-01-30 23:58:34 -05:00
john-okeefe 885cbd5d47 feat: broadcast progress updates from KOReader sync
Add WebSocket broadcast to KOReader progress sync:
- Integrate ConnectionManager into KOReaderHandler
- Broadcast progress updates on successful sync
- Include source device information (model, type)
- Real-time updates to all connected clients

When KOReader devices sync reading progress, all connected
WebSocket clients (web browsers, mobile apps, other devices)
receive instant updates.
2026-01-30 21:48:14 -05:00
john-okeefe 4681fb474e feat: integrate ConnectionManager into Handler struct
Add WebSocket ConnectionManager to Handler:
- Add connManager field to Handler struct
- Update NewHandler to accept ConnectionManager parameter
- Update SetupRoutes to pass ConnectionManager through
- Import sync package with alias to avoid conflicts

This enables progress handlers to broadcast updates via WebSocket.
2026-01-30 21:47:56 -05:00
john-okeefe c9ec222945 feat: add ValidateDeviceToken method to device auth middleware
Add device token validation method for WebSocket authentication:
- Validates device auth tokens against database
- Returns device information for valid tokens
- Used by WebSocket handler for device authentication

This enables devices to authenticate WebSocket connections
using their bearer tokens.
2026-01-30 21:47:30 -05:00
john-okeefe 317a4e82a0 feat: add WebSocket handler with dual authentication
Add WSHandler for WebSocket connection management:
- Upgrade HTTP to WebSocket connections
- Dual authentication support:
  - JWT token via query parameter (web clients)
  - Bearer token via Authorization header (devices)
- Client info extraction for users and devices
- Separate read and write pumps for concurrent I/O
- Ping/pong heartbeat mechanism (30s interval)
- Initial state delivery on connection
- Connection cleanup on disconnect

Implements Week 9 WebSocket endpoint functionality from
Universal Sync Implementation Guide.
2026-01-30 21:47:11 -05:00
john-okeefe 9bfe14bb38 feat: add WebSocket connection manager infrastructure
Add ConnectionManager for real-time WebSocket communication:
- Message types for progress updates, annotations, conflicts
- Broadcast message structure with source device tracking
- Device connection tracking with user and device metadata
- Automatic broadcast loop with concurrent message delivery
- Connection management (add, remove, get by ID/user)
- Stale connection cleanup (2-minute timeout)
- Connection statistics by device type
- Background cleanup task runs every minute

This implements the core WebSocket infrastructure needed for
Week 9 of the Universal Sync Implementation Guide.
2026-01-30 21:46:53 -05:00
john-okeefe f6124dc537 Phase 3 Week 7: Fix device auth middleware to set device object
- Update device auth middleware to set actual device object
- Change from DeviceContext to database.Devices
- Fix RequirePermission to use database.Devices
- Ensures handlers can access full device information
- Required for KOReader sync handlers to function properly
2026-01-30 20:55:13 -05:00
john-okeefe 7a5d38b886 Phase 3 Week 7: Implement KOReader sync protocol handlers
- Create SyncProgress for bidirectional progress synchronization
- Create GetMetadata for book progress and annotation retrieval
- Create GetLibrary for user library sync
- Create SyncBookmarks for annotation management
- Support device matching by UUID, file path, or title/author
- Implement immediate and checkpoint sync modes
- Handle bookmarks, highlights, and notes synchronization
- Part of Phase 3 KOReader Integration implementation
2026-01-30 20:55:04 -05:00
john-okeefe 4c01c0d12e Phase 3 Week 7: Add KOReader bulk sync function to database schema
- Add bulk_update_progress_from_koreader() function for batch processing
- Handles progress, annotations, and conflict detection
- Returns success/failure status for each book
- Supports device matching by UUID, file path, or title/author
- Implements automatic conflict detection for concurrent syncs
- Part of Phase 3 KOReader Integration implementation
2026-01-30 20:54:51 -05:00
john-okeefe 6432d4cb00 Fix BaseURL construction to use consistent port
- Use SERVER_PORT for both port and BaseURL construction
- Ensures BaseURL matches the actual server port
2026-01-30 20:16:25 -05:00
john-okeefe a9fdd44471 Add library-based scanning and media item endpoints
- Add POST /api/libraries/:id/scan endpoint for admin library scanning
- Add GET /api/libraries/:id/media-items endpoint for library media items
- Move /api/libraries/types to public endpoint (no auth required)
- Update ScanEbooks handler to support library_id parameter
2026-01-30 20:16:22 -05:00
john-okeefe 1a769783dc Phase 2 Week 6: Device Authentication & Rate Limiting
Implement per-device authentication with rate limiting and permissions.

Device Rate Limiter (device_rate_limiter.go):
- DeviceRateLimiter: Track requests per device and request type
- CheckRateLimit: Verify device hasn't exceeded limits
- GetRemainingRequests: Return remaining request quota
- Reset: Clear rate limit data for specific device
- cleanupOldEntries: Remove stale entries automatically
- Request Types: sync, progress, metadata
- Rate Limits:
  * Sync requests: 60/minute
  * Progress updates: 120/minute (page turns)
  * Metadata requests: 30/minute

Device Auth Middleware Updates:
- Add rateLimiter to DeviceAuthMiddleware
- Check rate limits during authentication
- Return 429 Too Many Requests when limits exceeded
- Set rate limit headers:
  * X-RateLimit-Limit: Request limit
  * X-RateLimit-Remaining: Quota remaining
  * X-RateLimit-Reset: Reset time
- getRequestType: Determine request type from URL path

Request Type Detection:
- /progress endpoints → progress type (120/min)
- /metadata, /library endpoints → metadata type (30/min)
- All other sync endpoints → sync type (60/min)

Benefits:
- Prevent device abuse and DoS attacks
- Fair resource allocation across devices
- Higher limits for frequent operations (page turns)
- Lower limits for expensive operations (metadata)
- Automatic cleanup of stale data
- Per-device isolation (one device can't affect others)

Integration with Device Auth:
- Rate limit check happens after token validation
- Before processing actual sync request
- Returns standard HTTP 429 with retry info
- Works seamlessly with existing device middleware

Device revocation still available via:
- DELETE /api/devices/:id endpoint
- Sets auth_token to NULL
- Disables sync_enabled flag
2026-01-30 16:47:29 -05:00
john-okeefe 23ad70158c Phase 2 Week 5: Device Registration & Management
Implement device registration and management system for universal sync.

Database Changes:
- Add device queries to queries.sql (CRUD operations, registration, auth)
- Add sync queue management queries
- Add conflict resolution queries
- Regenerate sqlc models with new device-related types

Device Handler (devices.go):
- InitiateRegistration: Start device registration with auth URL and QR code
- CheckRegistrationStatus: Poll for registration approval
- ListDevices: Get all devices for current user
- GetDevice: Get specific device details
- UpdateDevice: Update device settings (name, sync settings, frequency)
- DeleteDevice: Remove device from account
- ApproveDevice: User approves device registration via web
- RejectDevice: Reject pending device registration
- ListPendingRegistrations: Show all pending registrations
- generateDeviceToken: Generate secure Bearer token for devices

Device Authentication Middleware (device_auth.go):
- Authenticate: Validate device Bearer tokens
- RequirePermission: Check device permissions by type
- hasPermission: Define permissions per device type
- UpdateLastSeen: Auto-update device last_seen timestamp

Configuration:
- Add BaseURL field to Config for device setup URLs

API Endpoints:
POST /api/devices/register - Initiate device registration
POST /api/devices/register/status - Check registration status
GET /api/devices/approve/:id - Approve device (web UI)
POST /api/devices/reject/:id - Reject device
GET /api/devices - List user's devices
GET /api/devices/:id - Get device details
PUT /api/devices/:id - Update device settings
DELETE /api/devices/:id - Delete device
GET /api/devices/pending - List pending registrations

Bruno API Collection:
- Initiate Device Registration
- Check Registration Status
- List Devices
- Get Device
- Update Device
- Delete Device

Dependencies:
- github.com/skip2/go-qrcode for QR code generation

Device Types Supported:
- koreader: Calibre-compatible sync
- kobo: Kobo sync protocol
- web: Web interface
- mobile: Mobile apps

Device Permissions:
- sync:progress
- sync:annotations
- sync:metadata
- device:manage (web only)
2026-01-30 16:45:10 -05:00
john-okeefe a2424bcf74 Phase 1 Week 4: Testing & Validation
- Create comprehensive unit tests for sync package
- format_test.go: 60+ tests for format detection
  - EPUB format detection (mimetype, extension, uppercase)
  - MOBI/AZW3/FB2/TXT reflowable formats
  - PDF/DJVU fixed layout formats
  - CBZ/CBR/CB7/CBT comic archive formats
  - Unknown format handling
  - MimeType lookup tests
  - IsReflowable/HasFixedLayout/IsComicArchive helpers
- progress_test.go: 45+ tests for progress conversion
  - PageToPercentage/PercentageToPage (with clamping)
  - CharacterToPercentage/PercentageToCharacter
  - ConvertProgress between format groups
  - MergeProgress with 'max progress wins' strategy
  - FormatProgressForDisplay for UI rendering
  - Round-trip conversion tests
  - Edge cases (very small/large values, floating point precision)
- All tests pass successfully
- Test coverage: format detection, progress conversion, display formatting
- Validates Phase 1 implementation quality
2026-01-30 16:13:10 -05:00
john-okeefe 6ddc551d64 Phase 1 Week 3: Core Progress APIs
- Create internal/handlers/progress.go with universal progress endpoints
- GET /api/progress/:id - Get progress with all location references
- POST /api/progress/:id - Update progress with automatic conversion
- GET /api/progress/:id/history - Get reading session history
- Progress response includes:
  - format_group (reflowable, fixed_layout, comic_archive)
  - percentage (0.0-1.0)
  - location_references (page, epubcfi, chapter, character)
  - device_sync information
- UpdateUniversalProgress accepts multiple input formats:
  - percentage directly
  - page/total_pages (auto-converts to percentage)
  - epubcfi for EPUBs
  - chapter/chapter_progress
- Uses sync package for format conversion
- Backward compatible with existing progress endpoints
- Add routes to SetupRoutes in ebook.go
- Fixes pgtype wrapper type access (.Float64, .Int32, .Int64)
2026-01-30 16:11:11 -05:00
john-okeefe bb3c32c59f Phase 1 Week 2: Format detection and progress conversion engine
- Add internal/sync package with format detection
- FormatGroup types: reflowable, fixed_layout, comic_archive
- DetectFormatGroup() function based on mimetype and file extension
- MimeType mappings for common ebook formats
- Progress conversion engine with:
  - ConvertProgress() between format groups
  - Extract percentage from various progress formats
  - PageToPercentage / PercentageToPage helpers
  - CharacterToPercentage / PercentageToCharacter helpers
  - MergeProgress() with 'max progress wins' strategy
  - FormatProgressForDisplay() for UI rendering
- Add sqlc queries for format detection and progress updates
- BulkUpdateFormatGroups query for auto-format detection
- GetUniversalProgress query with all location references
- UpdateUniversalProgress query with device sync metadata
- ReadingHistory queries for session tracking
2026-01-30 16:07:00 -05:00
john-okeefe fa4a9c35bb Phase 1 Week 1: Database schema for universal sync system
- Add format_group columns to media_items table
- Add universal progress tracking to reading_progress (percentage, epubcfi, chapter, etc.)
- Add device sync metadata (last_sync_device, conflict tracking)
- Add location enhancements to media_notes and media_highlights
- Create devices table for device registry
- Create sync_queue table for offline support
- Create sync_conflicts table for conflict resolution
- Create reading_history table for session tracking
- Add 15 new indexes for performance
- Create update_updated_at_column trigger function
- Add SQL helper functions: detect_format_group, convert_progress, detect_conflict, merge_progress

Schema grew from 272 to 598 lines (+326 lines)
Verified with sqlc generate
2026-01-30 16:04:06 -05:00