diff --git a/docs/Code/bookmann/IMPLEMENTATION_PLAN.md b/docs/Code/bookmann/IMPLEMENTATION_PLAN.md
new file mode 100644
index 0000000..249a1dc
--- /dev/null
+++ b/docs/Code/bookmann/IMPLEMENTATION_PLAN.md
@@ -0,0 +1,1692 @@
+# Bookmann Implementation Plan
+
+## Executive Summary
+
+This plan implements a complete cross-device ebook management system with three major capabilities:
+
+1. **Universal Book Identification** - SHA-256 hashing, UUID, ISBN, ASIN, and OPF identifiers for content-based matching across devices
+2. **Enhanced Collection Management** - Device-neutral "Collections" with auto-assign rules and per-device customization via shelf mappings
+3. **OPDS-Based Wireless Book Delivery** - Industry-standard book distribution for Kobo, KOReader, Web, and Mobile apps
+4. **Bidirectional Progress Synchronization** - Real-time sync with ContentId mapping to handle format conversions (EPUB → KEPUB)
+5. **Device-Specific Configuration** - Per-device view settings and shelf mappings while maintaining unified data model
+
+**Key Design Principle**: Use OPDS for book acquisition (Layer 1) and internal APIs for state management (Layer 2), maintaining clear separation of concerns while enabling seamless user experience.
+
+---
+
+## Table of Contents
+
+1. [Architecture Overview](#architecture-overview)
+2. [Database Schema](#database-schema)
+3. [API Endpoints](#api-endpoints)
+4. [Implementation Phases](#implementation-phases)
+5. [Device Setup Instructions](#device-setup-instructions)
+6. [Security Considerations](#security-considerations)
+7. [Testing Strategy](#testing-strategy)
+8. [Glossary](#glossary)
+
+---
+
+## Architecture Overview
+
+### System Design: Two-Layer Architecture
+
+```
+┌─────────────────────────────────────────────────────────────────┐
+│ Bookmann Server │
+│ ┌──────────────────────────────────────────────────────────────┐ │
+│ │ Layer 1: Universal Book Identification │ │
+│ │ SHA-256, UUID, ISBN, ASIN, OPF identifiers │ │
+│ │ Device file aliases for path tracking │ │
+│ └──────────────────────────────────────────────────────────────────────┘ │
+│ ↓ matches books universally │
+│ ┌──────────────────────────────────────────────────────────────────────┐ │
+│ │ Layer 2: Collections (Device-Neutral Organization) │ │
+│ │ Collections with auto-assign rules │ │
+│ │ Device-specific shelf mappings (Kobo) │ │
+│ │ Per-user view settings │ │
+│ └──────────────────────────────────────────────────────────────────────┘ │
+│ ↓ provides organization │
+│ ┌──────────────────────────────────────────────────────────────────────┐ │
+│ │ Layer 3: OPDS (Primary Wireless Delivery) │ │
+│ │ Per-device OPDS feeds (Kobo, KOReader, etc.) │ │
+│ │ Format conversion (EPUB → KEPUB on-the-fly) │ │
+│ │ Dual hash storage (original + converted) │ │
+│ │ ContentId mapping (Bookmann UUID ↔ Device ID) │ │
+│ └──────────────────────────────────────────────────────────────────────┘ │
+│ ↓ delivers books + provides IDs │
+│ ┌──────────────────────────────────────────────────────────────────────┐ │
+│ │ Layer 4: Internal APIs (State Management) │ │
+│ │ Progress sync (bidirectional) │ │
+│ │ Annotation sync (bidirectional) │ │
+│ │ Collection CRUD │ │
+│ │ WebSocket real-time updates │ │
+│ │ Device-specific operations │ │
+│ └──────────────────────────────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────────────────────────────────┘
+```
+
+### Access Method Matrix
+
+| Platform | Access Method | Purpose | Why This Method |
+|-----------|----------------|---------|-----------------|
+| **Kobo** | OPDS catalog | Kobo has built-in OPDS client, no custom Bookmann client exists |
+| **KOReader** | OPDS catalog (primary) + Sidecar + Internal API | KOReader has OPDS client, also supports plugins/sidecars for enhanced features |
+| **Web App** | Internal API directly | We own and control web app, can make direct API calls efficiently |
+| **Mobile App** | Internal API directly | We own and control mobile app, can make direct API calls efficiently |
+| **Any OPDS Client** | OPDS catalog | Public catalog standard, any app can use it for browsing/downloading |
+
+### Key Design Principles
+
+1. **Canonical UUID Always Wins** - Bookmann UUID (from `media_items.id`) is always used for progress tracking, never SHA-256. SHA-256 is only for matching books across devices, preventing format conversion issues.
+
+2. **Collections ≠ Device Inventory** - Collections are organizational metadata (like "smart playlists"). Books can be in collections without being on any device. Progress/annotations sync independently of collection membership.
+
+3. **OPDS for Acquisition, Internal APIs for State** - Two layers serve complementary purposes:
+ - OPDS: "What books are available to download?" (public catalog)
+ - Internal APIs: "How do I manage my books/sync state?" (private management)
+
+4. **Dual Hash Storage Preserves Integrity** - Store both original EPUB hash (`epub_sha256`) and converted KEPUB hash (`kepub_sha256`) in `media_item_formats` table. OPDS responses include format-specific hash in headers, enabling sidecar matching even after conversion.
+
+5. **Three-Tier Authentication** - Separate systems for different purposes:
+ - Tier 1 (Web/Mobile): JWT tokens for user authentication and permissions
+ - Tier 2 (Sync APIs): Device tokens for progress/annotation sync
+ - Tier 3 (OPDS): Device tokens for catalog access (optional per-device)
+
+6. **Terminology Separation** - Always use "Collections" terminology in Bookmann UI. Map Collections to device-specific "Shelves" only at API/device level. Kobo devices see "Shelves", KOReader/Web/Mobile see "Collections". Prevents legal issues.
+
+7. **OPDS Primary for All Devices** - Kobo, KOReader, Web, and Mobile all use OPDS as primary book delivery method. Sidecar files provide fallback/enhanced features but are optional.
+
+8. **System Configuration Flexibility** - Use `system_config` table to store base URLs (`base_url`, `opds_base_url`, `api_base_url`). Sidecar generation reads from these values, enabling flexible deployment (different domains, reverse proxies) with user overrides available.
+
+---
+
+## Database Schema
+
+### Schema Overview
+
+**7 new tables** + extensions to 4 existing tables
+
+### Table: media_items (Extended)
+
+```sql
+-- Universal identifiers for cross-device matching
+ALTER TABLE media_items ADD COLUMN file_sha256 CHAR(64);
+ALTER TABLE media_items ADD COLUMN opf_identifier VARCHAR(255);
+ALTER TABLE media_items ADD COLUMN opf_uuid VARCHAR(255);
+
+-- Hash confidence for matching priority
+-- 'high': OPF UUID or ISBN available
+-- 'medium': ISBN/ASIN available but no OPF UUID
+-- 'low': Only title/author match available
+ALTER TABLE media_items ADD COLUMN hash_confidence VARCHAR(20);
+
+-- Create indexes for fast lookup
+CREATE INDEX idx_media_items_sha256 ON media_items(file_sha256);
+CREATE INDEX idx_media_items_opf_identifier ON media_items(opf_identifier);
+```
+
+### Table: media_item_formats (NEW)
+
+```sql
+-- Track all format versions with their hashes
+-- Critical for dual hash storage and format-specific OPDS delivery
+
+CREATE TABLE media_item_formats (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ media_item_id UUID REFERENCES media_items(id) ON DELETE CASCADE,
+ format_type VARCHAR(10) NOT NULL, -- 'epub', 'kepub', 'pdf', 'cbz'
+ file_path VARCHAR(500),
+ file_sha256 CHAR(64),
+ file_size_bytes BIGINT,
+ mime_type VARCHAR(100),
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
+ converted_from_format_id UUID REFERENCES media_item_formats(id), -- If this is converted from another format
+ UNIQUE(media_item_id, format_type)
+);
+
+CREATE INDEX idx_media_item_formats_media ON media_item_formats(media_item_id, format_type);
+CREATE INDEX idx_media_item_formats_sha256 ON media_item_formats(file_sha256);
+```
+
+### Table: device_file_aliases (NEW)
+
+```sql
+-- Track file paths per device for cross-device matching
+-- When same book has different file paths on different devices, we can still match them via SHA-256
+
+CREATE TABLE device_file_aliases (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ media_item_id UUID REFERENCES media_items(id) ON DELETE CASCADE,
+ device_id UUID REFERENCES devices(id) ON DELETE CASCADE,
+ file_path VARCHAR(500) NOT NULL,
+ file_sha256 CHAR(64),
+ confidence_score FLOAT DEFAULT 1.0,
+ last_seen_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
+ UNIQUE(device_id, file_path)
+);
+
+CREATE INDEX idx_device_file_aliases_media_device ON device_file_aliases(media_item_id, device_id);
+CREATE INDEX idx_device_file_aliases_sha256 ON device_file_aliases(file_sha256);
+```
+
+### Table: collections (NEW)
+
+```sql
+-- Device-neutral collections (separate from Kobo shelves)
+-- Each user has their own independent collection namespace
+
+CREATE TABLE collections (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ user_id UUID REFERENCES users(id) ON DELETE CASCADE,
+ name VARCHAR(100) NOT NULL,
+ description TEXT,
+ color VARCHAR(7), -- Hex color for UI
+ icon VARCHAR(50), -- Emoji or icon name
+ auto_assign_rules JSONB, -- See schema below for structure
+ view_settings JSONB, -- Per-device view preferences
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
+ UNIQUE(user_id, name)
+);
+```
+
+### Table: collection_items (NEW)
+
+```sql
+-- Which books belong to each collection
+
+CREATE TABLE collection_items (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ collection_id UUID REFERENCES collections(id) ON DELETE CASCADE,
+ media_item_id UUID REFERENCES media_items(id) ON DELETE CASCADE,
+ added_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
+ added_by_user_id UUID REFERENCES users(id) ON DELETE SET NULL, -- Manual vs auto
+ UNIQUE(collection_id, media_item_id)
+);
+
+CREATE INDEX idx_collection_items_collection ON collection_items(collection_id);
+CREATE INDEX idx_collection_items_media ON collection_items(media_item_id);
+```
+
+### Table: device_shelf_mappings (NEW)
+
+```sql
+-- Map Bookmann collections to device-specific shelf names
+-- This is where "Collections" terminology maps to Kobo's "Shelves"
+
+CREATE TABLE device_shelf_mappings (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ collection_id UUID REFERENCES collections(id) ON DELETE CASCADE,
+ device_id UUID REFERENCES devices(id) ON DELETE CASCADE,
+ device_shelf_name VARCHAR(100), -- What appears on Kobo device
+ sync_direction VARCHAR(20), -- 'bidirectional', 'book_to_device', 'device_to_book', 'none'
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
+ UNIQUE(collection_id, device_id)
+);
+
+CREATE INDEX idx_device_shelf_mappings_collection ON device_shelf_mappings(collection_id);
+CREATE INDEX idx_device_shelf_mappings_device ON device_shelf_mappings(device_id);
+```
+
+### Table: device_catalogs (NEW)
+
+```sql
+-- Track OPDS downloads and map Bookmann UUIDs to device ContentIds
+-- Critical for bidirectional progress sync with format conversion handling
+
+CREATE TABLE device_catalogs (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ device_id UUID REFERENCES devices(id) ON DELETE CASCADE,
+ media_item_id UUID REFERENCES media_items(id) ON DELETE CASCADE,
+ bookmann_uuid UUID NOT NULL,
+ kobo_content_id VARCHAR(255) NOT NULL,
+ content_id_type VARCHAR(20), -- 'bookmann_uuid', 'kobo_generated', 'isbn_based'
+ available BOOLEAN DEFAULT TRUE,
+ delivery_date TIMESTAMP WITH TIME ZONE,
+ delivery_method VARCHAR(20), -- 'wireless', 'usb', 'manual'
+ UNIQUE(device_id, kobo_content_id)
+);
+
+CREATE INDEX idx_device_catalogs_bookmann ON device_catalogs(bookmann_uuid);
+CREATE INDEX idx_device_catalogs_kobo ON device_catalogs(kobo_content_id);
+```
+
+### Table: system_config (NEW)
+
+```sql
+-- System-wide configuration (set by admin)
+-- Critical for flexible deployment (different domains, reverse proxies)
+
+CREATE TABLE system_config (
+ key VARCHAR(100) PRIMARY KEY,
+ value TEXT NOT NULL,
+ updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
+ updated_by UUID REFERENCES users(id)
+);
+
+-- Pre-seeded values
+INSERT INTO system_config (key, value) VALUES
+('base_url', 'https://bookmann.example.com'),
+('opds_base_url', 'https://bookmann.example.com/opds'),
+('api_base_url', 'https://bookmann.example.com/api');
+```
+
+### Table: opds_tokens (NEW)
+
+```sql
+-- Device-specific OPDS access tokens (optional authentication)
+-- Allows device-level access control without exposing JWT tokens
+
+CREATE TABLE opds_tokens (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ device_id UUID REFERENCES devices(id) ON DELETE CASCADE,
+ token VARCHAR(64) UNIQUE NOT NULL,
+ token_type VARCHAR(20), -- 'device', 'user', 'admin'
+ expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
+);
+
+CREATE INDEX idx_opds_tokens_device ON opds_tokens(device_id);
+CREATE INDEX idx_opds_tokens_token ON opds_tokens(token);
+```
+
+### Table: kobo_shelves (Modified)
+
+```sql
+-- Reference collections instead of media_items directly
+-- Maintains backward compatibility with existing device_id/media_item_id columns
+
+ALTER TABLE kobo_shelves ADD COLUMN collection_id UUID REFERENCES collections(id);
+ALTER TABLE kobo_shelves ADD COLUMN position_in_collection INTEGER;
+```
+
+### Schema Relationships Summary
+
+```
+users
+├─ devices (one user can have multiple devices)
+│ └─ device_file_aliases (tracks file paths per device)
+│ └─ device_shelf_mappings (collection → Kobo shelf name)
+│ └─ device_catalogs (OPDS + ContentId mapping)
+│ └─ opds_tokens (OPDS authentication, optional)
+├─ media_items (canonical book records with universal identifiers)
+│ ├─ file_sha256, opf_identifier, opf_uuid
+│ ├─ hash_confidence
+│ ├─ reading_progress (one record per user per book)
+│ └─ collection_items (which collections each book belongs to)
+└─ collections (device-neutral organization)
+└─ collection_items (membership)
+```
+
+---
+
+## API Endpoints
+
+### Layer 1: Universal Book Identification
+
+#### POST `/api/sync/books/query`
+
+Query Bookmann for a book by multiple identifier types with confidence scoring.
+
+**Request**:
+```json
+{
+ "identifiers": ["isbn:978-0345391802", "uuid:abc-123", "opf_uuid:def456"],
+ "sha256": "a1b2c3d4e5f6abc123...",
+ "title": "The Hobbit",
+ "author": "J.R.R. Tolkien",
+ "file_size": 2456789
+}
+```
+
+**Response**:
+```json
+{
+ "matches": [
+ {
+ "media_item_id": "uuid-123",
+ "bookmann_uuid": "uuid-123",
+ "confidence": 1.0,
+ "match_method": "uuid_match"
+ }
+ ],
+ "action": "auto_link" // or "multiple_matches", "no_match"
+}
+```
+
+**Matching Priority**:
+1. Bookmann UUID (canonical) - Confidence: 1.0
+2. OPF UUID (from EPUB metadata) - Confidence: 0.95
+3. SHA-256 hash (content-based match) - Confidence: 0.9
+4. OPF identifier (non-UUID) - Confidence: 0.85
+5. ISBN/ASIN (standard identifiers) - Confidence: 0.8
+6. File path (device-specific, fallback) - Confidence: variable
+7. Title + author + file size (last resort) - Confidence: 0.5
+
+#### POST `/api/sync/link-book`
+
+Manual linking override for unmatched books.
+
+**Request**:
+```json
+{
+ "device_file": {
+ "file_path": "/storage/emulated/0/Books/MyBook.epub",
+ "sha256": "abc123...",
+ "title": "My Book"
+ },
+ "media_item_id": "uuid-123",
+ "confidence_score": 1.0 // User sets this
+}
+```
+
+**Response**:
+```json
+{
+ "status": "linked",
+ "device_file_alias": {
+ "id": "alias-id",
+ "media_item_id": "uuid-123",
+ "device_id": "kobo-device-id",
+ "file_path": "/storage/emulated/0/Books/MyBook.epub",
+ "file_sha256": "abc123...",
+ "confidence_score": 1.0
+ }
+}
+```
+
+#### GET `/api/sync/unlinked-books`
+
+List progress records that need manual linking.
+
+**Response**:
+```json
+{
+ "unlinked": [
+ {
+ "progress_id": "progress-uuid",
+ "device_id": "kobo-device-id",
+ "device_type": "kobo",
+ "file_path": "/mnt/sdcard/UnknownBook.epub",
+ "sha256": "abc123...",
+ "title_from_device": "Unknown Book",
+ "last_sync_timestamp": "2026-01-31T12:00:00Z"
+ }
+ ],
+ "total": 1
+}
+```
+
+#### GET `/api/devices/:id/file-aliases`
+
+View all file aliases for a specific device.
+
+**Response**:
+```json
+{
+ "device_id": "device-uuid",
+ "aliases": [
+ {
+ "id": "alias-id",
+ "media_item_id": "uuid-123",
+ "file_path": "/storage/emulated/0/Books/MyBook.epub",
+ "file_sha256": "abc123...",
+ "confidence_score": 1.0,
+ "last_seen_at": "2026-01-31T12:00:00Z"
+ }
+ ],
+ "total": 42
+}
+```
+
+### Layer 2: Collection Management
+
+#### POST `/api/collections`
+
+Create a new collection.
+
+**Request**:
+```json
+{
+ "name": "Science Fiction",
+ "description": "My favorite sci-fi books",
+ "color": "#ff0000",
+ "icon": "🚀",
+ "auto_assign_rules": [
+ {
+ "id": "rule-1",
+ "field": "genre",
+ "operator": "equals",
+ "value": "Science Fiction"
+ }
+ ]
+}
+```
+
+**Response**:
+```json
+{
+ "id": "collection-uuid",
+ "name": "Science Fiction",
+ "description": "My favorite sci-fi books",
+ "color": "#ff0000",
+ "icon": "🚀",
+ "auto_assign_rules": [...],
+ "book_count": 0,
+ "created_at": "2026-01-31T12:00:00Z"
+}
+```
+
+#### GET `/api/collections`
+
+List all collections for current user.
+
+**Query Parameters**:
+- `include_auto`: boolean (include auto-assigned collections)
+- `sort_by`: string (name, created_at, book_count)
+
+**Response**:
+```json
+{
+ "collections": [
+ {
+ "id": "collection-uuid",
+ "name": "Science Fiction",
+ "description": "...",
+ "color": "#ff0000",
+ "icon": "🚀",
+ "auto_assign_rules": [...],
+ "book_count": 15
+ }
+ ],
+ "total": 1
+}
+```
+
+#### GET `/api/collections/:id`
+
+Get single collection details with books.
+
+**Response**:
+```json
+{
+ "id": "collection-uuid",
+ "name": "Science Fiction",
+ "description": "My favorite sci-fi books",
+ "color": "#ff0000",
+ "icon": "🚀",
+ "auto_assign_rules": [...],
+ "view_settings": {
+ "kobo": {"shelf_name": "Sci-Fi", "sync": true},
+ "koreader": {"enabled": false},
+ "web": {"view_mode": "grid"}
+ },
+ "books": [
+ {
+ "media_item_id": "uuid-1",
+ "title": "Foundation",
+ "author": "Isaac Asimov"
+ }
+ ],
+ "book_count": 42
+}
+```
+
+#### PUT `/api/collections/:id`
+
+Update collection.
+
+**Request**:
+```json
+{
+ "name": "Sci-Fi Favorites",
+ "description": "Updated description",
+ "color": "#00ff00",
+ "icon": "⭐",
+ "auto_assign_rules": [
+ {
+ "id": "rule-2",
+ "field": "series",
+ "operator": "equals",
+ "value": "Foundation"
+ }
+ ]
+}
+```
+
+#### DELETE `/api/collections/:id`
+
+Delete collection and all its memberships.
+
+#### POST `/api/collections/:id/books`
+
+Add books to collection.
+
+**Request**:
+```json
+{
+ "book_ids": ["uuid-1", "uuid-2", "uuid-3"],
+ "added_by_user": true // Manual addition vs. auto
+}
+```
+
+#### DELETE `/api/collections/:id/books/:bookId`
+
+Remove book from collection.
+
+#### POST `/api/collections/:id/rules`
+
+Create auto-assign rule for collection.
+
+**Rule Schema**:
+```json
+{
+ "field": "genre", // "genre", "series", "author", "language", "publisher", "copyright_year", "tags"
+ "operator": "equals", // "equals", "contains", "starts_with", "ends_with", "greater_than", "less_than"
+ "value": "Science Fiction"
+}
+```
+
+#### PUT `/api/collections/:id/rules/:ruleId`
+
+Update existing rule.
+
+### Layer 3: Device-Specific Shelf Mappings
+
+#### GET `/api/devices/:id/collections`
+
+Get all collection → shelf mappings for a device.
+
+**Response**:
+```json
+{
+ "device_id": "device-uuid",
+ "device_name": "My Kobo Clara",
+ "device_type": "kobo",
+ "mappings": [
+ {
+ "collection_id": "collection-uuid",
+ "collection_name": "Science Fiction",
+ "device_shelf_name": "Sci-Fi",
+ "sync_direction": "bidirectional",
+ "created_at": "2026-01-31T12:00:00Z"
+ }
+ ],
+ "total": 1
+}
+```
+
+#### POST `/api/devices/:id/collections`
+
+Create new shelf mapping for device.
+
+**Request**:
+```json
+{
+ "collection_id": "collection-uuid",
+ "device_shelf_name": "My Books",
+ "sync_direction": "bidirectional"
+}
+```
+
+#### PUT `/api/devices/:id/collections/:collectionId`
+
+Update shelf mapping.
+
+#### DELETE `/api/devices/:id/collections/:collectionId`
+
+Remove shelf mapping.
+
+### Layer 3: OPDS Content Delivery
+
+#### GET `/opds/devices/:deviceId/catalog`
+
+Main OPDS 1.2 catalog feed.
+
+**Query Parameters**:
+- `page`: integer (default 1)
+- `per_page`: integer (default 50)
+- `include_format`: string (optional filter)
+
+**Response (OPDS 1.2 XML)**:
+```xml
+
+
+ urn:uuid:device-id
+ Bookmann Library
+ 2026-01-31T12:00:00Z
+
+
+
+
+
+
+ urn:uuid:bookmann-uuid-123
+ The Hobbit
+ J.R.R. Tolkien
+ 2026-01-31T10:00:00Z
+ Book description...
+
+
+
+
+
+
+
+
+
+ uuid-123
+
+
+ abc123...
+
+
+ Science Fiction
+ Reading
+
+
+
+
+```
+
+#### GET `/opds/devices/:deviceId/search?q=`
+
+OPDS acquisition search endpoint.
+
+**Response (OPDS 1.2 XML)**:
+```xml
+
+
+ urn:uuid:device-id
+
+
+ urn:uuid:bookmann-uuid-123
+ The Hobbit
+ J.R.R. Tolkien
+ 2026-01-31T10:00:00Z
+
+
+
+```
+
+#### GET `/opds/devices/:deviceId/nav`
+
+OPDS navigation feed.
+
+#### GET `/opds/devices/:deviceId/download/:bookId`
+
+Download book with optional format conversion.
+
+**Query Parameters**:
+- `format`: string (epub, kepub, pdf, cbz) - default: epub
+
+**Response Headers**:
+- `Content-Type`: application/epub+zip (or format-specific)
+- `Content-Disposition`: attachment; filename="The Hobbit.epub"
+- `X-Bookmann-UUID`: uuid-123
+- `X-Bookmann-SHA256`: abc123... (for format-specific if available)
+- `X-Bookmann-KEPUB-SHA256`: xyz789... (if format=kepub)
+
+**Format Conversion Logic**:
+```go
+// Select appropriate format based on format parameter
+switch format {
+case "kepub":
+ // Check media_item_formats table for pre-converted KEPUB
+ if kepubFormat.Exists && kepubFormat.FilePath != "" {
+ Serve pre-converted file
+ Set X-Bookmann-KEPUB-SHA256: kepubFormat.SHA256
+ }
+case "pdf":
+ // Serve PDF directly
+case "epub":
+ // Serve original EPUB directly
+}
+```
+
+#### GET `/opds/devices/:deviceId/cover/:bookId`
+
+Download cover image.
+
+**Response**:
+- `Content-Type`: image/jpeg
+- `Cache-Control`: public, max-age=31536000 (1 year)
+
+#### GET `/opds/devices/:deviceId/formats/:bookId`
+
+List available formats for a book.
+
+**Response**:
+```json
+{
+ "media_item_id": "uuid-123",
+ "formats": [
+ {
+ "format_type": "epub",
+ "file_path": "/path/to/book.epub",
+ "file_sha256": "abc123...",
+ "file_size_bytes": 2456789,
+ "mime_type": "application/epub+zip",
+ "available": true
+ },
+ {
+ "format_type": "kepub",
+ "file_path": "/cache/book.kepub.epub",
+ "file_sha256": "xyz789...",
+ "file_size_bytes": 2478932,
+ "mime_type": "application/vnd.kobo+xml+zip",
+ "available": true
+ },
+ {
+ "format_type": "pdf",
+ "file_path": "/path/to/book.pdf",
+ "file_sha256": "def456...",
+ "file_size_bytes": 5123456,
+ "mime_type": "application/pdf",
+ "available": false // Not converted yet
+ }
+ ]
+}
+```
+
+#### POST `/api/devices/:deviceId/opds-register`
+
+Register device for OPDS access (generates token).
+
+**Request**:
+```json
+{
+ "device_name": "My Kobo Clara",
+ "device_type": "kobo"
+}
+```
+
+**Response**:
+```json
+{
+ "opds_token": {
+ "token": "abc-123-def-456...",
+ "token_type": "device",
+ "expires_at": "2026-02-28T23:59:59Z",
+ "created_at": "2026-01-31T12:00:00Z"
+ },
+ "opds_catalog_url": "http://192.168.1.100:8765/opds/devices/kobo-id/catalog",
+ "refresh_interval": 3600
+}
+```
+
+### Layer 4: Enhanced Device Sync
+
+#### POST `/api/sync/kobo/markup`
+
+Kobo progress sync with ContentId mapping (enhanced).
+
+**Request (Enhanced)**:
+```json
+{
+ "ReadingSync": [
+ {
+ "ContentId": "kobo_xyz",
+ "PercentRead": 60.0,
+ "RemainingTimeMin": 120,
+ "ReadingEvent": "BookRead"
+ }
+ ],
+ "BookmarkSync": [...],
+ "Metadata": true // NEW: Include collection metadata
+}
+```
+
+**ContentId Mapping Logic**:
+```go
+// Step 1: Try direct ContentId lookup
+catalog, err := db.GetDeviceCatalogByKoboContentId(ctx, contentId)
+if err == nil && catalog.Valid {
+ // Found! Use canonical Bookmann UUID
+ bookmannUUID = catalog.BookmannUUID
+ return bookmannUUID, nil
+}
+
+// Step 2: ContentId not found - try SHA-256 (if looks like hash)
+if len(contentId) == 64 && looksLikeSHA256(contentId) {
+ mediaItem, err := db.GetMediaItemBySHA256(ctx, contentId)
+ if err == nil {
+ return mediaItem.ID, nil
+ }
+}
+
+// Step 3: Not found - create unlinked entry
+return uuid.Nil{}, errors.New("unlinked book")
+```
+
+#### POST `/api/sync/kobo/bookmark`
+
+Kobo bookmark sync (enhanced).
+
+#### GET `/api/sync/kobo/initialization`
+
+Kobo library sync with collection metadata (enhanced).
+
+**Response (Enhanced)**:
+```json
+{
+ "LibrarySync": [
+ {
+ "ContentId": "kobo_xyz",
+ "ContentType": "6",
+ "Title": "The Hobbit",
+ "Author": "J.R.R. Tolkien",
+ "PercentRead": 60.0,
+
+ // NEW: Collection metadata
+ "Categories": ["Science Fiction", "Reading"],
+ "BookmannUUID": "uuid-123" // Canonical ID
+ }
+ ]
+}
+```
+
+### Layer 5: Enhanced KOReader Sync
+
+#### POST `/api/sync/koreader/progress`
+
+KOReader progress sync with SHA-256 support (enhanced).
+
+**Request (Enhanced)**:
+```json
+{
+ "sync_mode": "immediate", // or "checkpoint"
+ "books": [
+ {
+ "uuid": "uuid-123", // Optional: highest priority
+ "sha256": "abc123...", // NEW: Device can send hash
+ "file_path": "/storage/emulated/0/Books/MyBook.epub",
+ "title": "The Hobbit",
+ "authors": ["J.R.R. Tolkien"],
+ "percentage": 75.0,
+ "epubcfi": "/6/4!/2/4[chapter_1]@0:100",
+ "chapter": 12,
+ "character": 1234567,
+ "page": 312,
+ "total_pages": 416
+ }
+ ]
+}
+```
+
+**SHA-256 Matching Logic**:
+```go
+// Priority 1: UUID provided (highest confidence)
+if book.UUID != "" {
+ return book.UUID, nil
+}
+
+// Priority 2: SHA-256 provided (medium confidence)
+if book.SHA256 != "" {
+ mediaItem, err := db.GetMediaItemBySHA256(ctx, book.SHA256)
+ if err == nil {
+ return mediaItem.ID, nil
+ }
+ return mediaItem.ID, nil
+}
+
+// Priority 3: Create device file alias (if file path provided)
+if book.FilePath != "" {
+ // Check if alias exists
+ alias, err := db.GetDeviceFileAlias(ctx, deviceID, book.FilePath)
+ if err == nil {
+ // Create new alias with medium confidence
+ db.CreateDeviceFileAlias(ctx, CreateDeviceFileAliasParams{
+ MediaItemID: mediaItemID,
+ DeviceID: deviceID,
+ FilePath: book.FilePath,
+ FileSHA256: book.SHA256,
+ ConfidenceScore: 0.7,
+ })
+ return alias.MediaItemID, nil
+ }
+ // Use existing alias
+ return alias.MediaItemID, nil
+}
+
+// Priority 4: Search by title/author + file size (fallback)
+return mediaItem.ID, nil
+```
+
+#### POST `/api/sync/koreader/bookmarks`
+
+KOReader annotations sync with SHA-256 support.
+
+**Request (Enhanced)**:
+```json
+{
+ "bookmarks": [
+ {
+ "uuid": "uuid-123",
+ "sha256": "abc123...", // NEW: For cross-device matching
+ "file_path": "/storage/emulated/0/Books/MyBook.epub",
+ "title": "The Hobbit",
+ "page": 312,
+ "text": "Great quote on page 312"
+ }
+ ]
+}
+```
+
+### Layer 5: Sidecar Configuration
+
+#### GET `/api/sync/sidecar/:deviceId`
+
+Download unified `.bookmann.json` configuration file.
+
+**Response**:
+```json
+{
+ "version": "1.0",
+ "bookmann": {
+ "opds_catalog": "http://192.168.1.100:8765/opds/devices/kobo-id/catalog",
+ "sync_api": "http://192.168.1.100:8765/api/sync/kobo",
+ "opds_base_url": "http://192.168.1.100:8765/opds",
+ "api_base_url": "http://192.168.1.100:8765/api",
+ "device_id": "kobo-device-uuid"
+ },
+ "books": {
+ "sha256:abc123...": {
+ "bookmann_uuid": "uuid-123",
+ "title": "The Hobbit",
+ "author": "J.R.R. Tolkien",
+ "available_formats": ["epub", "kepub"]
+ }
+ },
+ "collections": [
+ {
+ "name": "Sci-Fi",
+ "shelf_mapping": "Science Fiction",
+ "book_ids": ["uuid-1", "uuid-2", "uuid-3"]
+ }
+ ],
+ "last_updated": "2026-01-31T12:00:00Z"
+}
+```
+
+#### POST `/api/sync/sidecar/:deviceId/register`
+
+Validate sidecar file upload from device.
+
+### Layer 6: System Configuration
+
+#### GET `/api/admin/system-config`
+
+Get system-wide configuration.
+
+**Response**:
+```json
+{
+ "config": {
+ "base_url": "https://bookmann.example.com",
+ "opds_base_url": "https://bookmann.example.com/opds",
+ "api_base_url": "https://bookmann.example.com/api",
+ "auto_convert_kepub": true,
+ "default_opds_refresh_interval": 3600
+ }
+}
+```
+
+#### PUT `/api/admin/system-config`
+
+Update system configuration.
+
+---
+
+## Implementation Phases
+
+### Phase 1: Database Schema (Week 1)
+
+**Deliverables**:
+- Create SQL schema file for all new tables
+- Add columns to existing tables
+- Run schema migrations on development database
+- Update sqlc code generation
+- Write rollback migration script
+
+**Tasks**:
+1.1 Create migration SQL file `database/schema/001_universal_identifiers.sql`
+1.2 Update database models
+1.3 Write database queries
+1.4 Test database queries manually
+1.5 Write rollback migration script
+
+### Phase 2: Scanner Enhancement (Week 1-2)
+
+**Deliverables**:
+- Enhanced scanner code
+- OPF parser implementation
+- Unit tests for hash calculation
+
+**Tasks**:
+2.1 Implement SHA-256 calculation in `ebook_scanner.go`
+ - Stream file reading (don't load entire file into memory)
+ - Algorithm: crypto/sha256 from Go standard library
+2.2 Implement OPF parser
+ - Extract `` tags from EPUB OPF files
+ - Parse both OEBPS and OPF 2.0 formats
+ - Extract UUIDs from `` attributes
+ - Handle multiple identifiers per file
+2.3 Implement format detection
+ - Detect file format based on extension and content
+2.4 Pre-convert EPUB to KEPUB during scan
+ - Use `ebooklib` or similar library for conversion
+2.5 Store all format hashes in `media_item_formats` table
+
+**Hash Confidence Logic**:
+```
+HIGH (confidence = 1.0):
+ - EPUB with valid `` (UUID format)
+ - ISBN found (standard format)
+
+MEDIUM (confidence = 0.7):
+ - OPF identifier present (non-UUID custom format)
+ - ISBN/ASIN matched via metadata sources
+
+LOW (confidence = 0.5):
+ - Only title/author match available
+```
+
+**Deliverables**:
+- Enhanced scanner code
+- OPF parser implementation
+- KEPUB conversion utility
+- Unit tests for hash calculation
+
+### Phase 3: Universal Book Matching Engine (Week 2)
+
+**Deliverables**:
+- Matching engine implementation
+- Book query API handlers
+- Manual linking API endpoints
+- Unit tests for matching logic
+
+**Matching Algorithm**:
+```
+Priority 1: Bookmann UUID (canonical)
+ - If device sends UUID, use directly
+ - Confidence = 1.0
+
+Priority 2: OPF UUID (from EPUB metadata)
+ - Match against `opf_uuid` column
+ - Confidence = 0.95
+
+Priority 3: SHA-256 hash
+ - Match against `file_sha256` column
+ - Confidence = 0.9
+
+Priority 4: OPF identifier (non-UUID)
+ - Match against `opf_identifier` column
+ - Confidence = 0.85
+
+Priority 5: ISBN/ASIN (standard identifiers)
+ - Match against `isbn` and `asin` columns
+ - Confidence = 0.8
+
+Priority 6: File path (device-specific)
+ - Match via `device_file_aliases` table
+ - Confidence = from alias record
+
+Priority 7: Title + author + file size (fallback)
+ - Fuzzy search on title
+ - Exact match on author
+ - Within 10% file size variance
+ - Confidence = 0.5
+
+Priority 8: Title only (last resort)
+ - Fuzzy title match
+ - Confidence = 0.3
+```
+
+**Deliverables**:
+- Matching engine implementation
+- Book query API handlers
+- Manual linking API
+- Unlinked books API
+- Unit tests for matching logic
+
+### Phase 4: Collection Management System (Week 2-3)
+
+**Deliverables**:
+- Collections CRUD handlers
+- Auto-assign rules engine
+- Device shelf mapping handlers
+- Add collection book management
+- Per-device view settings
+
+**Auto-Assign Rules Engine**:
+```go
+type Rule struct {
+ ID string
+ Field string // "genre", "series", "author", "language", "publisher", "copyright_year", "tags"
+ Operator string // "equals", "contains", "starts_with", "ends_with", "greater_than", "less_than"
+ Value string // Exact value to match
+}
+
+type RuleEvaluation struct {
+ RuleID string
+ Matches bool
+ Confidence float
+}
+
+func EvaluateRules(mediaItem MediaItem, rules []Rule) []RuleEvaluation {
+ // Evaluate each rule against mediaItem metadata
+ // Return which rules match and overall confidence
+ // Higher-priority rules take precedence
+}
+```
+
+**Rule Priority System**:
+1. Rule with `priority` field (1-10, higher first)
+2. Multiple rules can apply to same book
+3. User can configure logical operators (AND, OR)
+
+**Deliverables**:
+- Collections API handlers
+- Rules engine implementation
+- Database queries for collections
+- Unit tests for rule evaluation
+
+### Phase 5: OPDS Implementation (Week 3)
+
+**Deliverables**:
+- OPDS XML serializer
+- OPDS catalog feed handler
+- OPDS search endpoint
+- Book download with format support
+- Cover image serving
+- ContentId mapping to OPDS responses
+- On-the-fly KEPUB conversion
+- Device authorization checks
+- OPDS token management
+
+**OPDS Response Structure (OPDS 1.2)**:
+```xml
+
+ urn:uuid:bookmann-uuid-123
+ The Hobbit
+ J.R.R. Tolkien
+ 2026-01-31T10:00:00Z
+
+
+
+
+
+
+
+
+
+ uuid-123
+
+
+ abc123...
+ xyz789...
+
+
+ Science Fiction
+ Reading
+
+```
+
+**Format Conversion Strategy**:
+```
+When user downloads with ?format=kepub:
+
+1. Check media_item_formats table
+2. If KEPUB exists and is recent:
+ - Serve pre-converted file
+ - Set X-Bookmann-SHA256: kepubFormat.SHA256
+3. If KEPUB doesn't exist:
+ - Convert EPUB to KEPUB on-the-fly
+ - Cache in media_item_formats table
+ - Serve converted file
+ - Set X-Bookmann-SHA256: kepubFormat.SHA256
+4. Serve PDF directly
+```
+
+**Deliverables**:
+- OPDS handlers implementation
+- OPDS XML serializers
+- KEPUB conversion utility
+- OPDS authentication
+- Integration with device_catalogs table
+
+### Phase 6: Enhanced Kobo Sync (Week 3-4)
+
+**Deliverables**:
+- Updated Kobo handler to use ContentId mapping
+- Bidirectional ContentId lookup
+- Add unlinked book detection
+- Integrate collection metadata into library sync
+- Support for legacy API endpoints
+
+**ContentId Mapping Logic**:
+```go
+// Step 1: Try direct ContentId lookup
+catalog, err := db.GetDeviceCatalogByKoboContentId(ctx, contentId)
+if err == nil && catalog.Valid {
+ // Found! Use canonical Bookmann UUID
+ return catalog.BookmannUUID, nil
+}
+
+// Step 2: ContentId not found - try SHA-256
+if len(contentId) == 64 && looksLikeSHA256(contentId) {
+ mediaItem, err := db.GetMediaItemBySHA256(ctx, contentId)
+ if err == nil {
+ return mediaItem.ID, nil
+ }
+}
+
+// Step 3: Not found - create unlinked entry
+return uuid.Nil{}, errors.New("unlinked book")
+```
+
+**Deliverables**:
+- Updated Kobo sync handlers
+- ContentId mapping system
+- Unlinked book tracking
+- Integration with collection metadata
+
+### Phase 7: Enhanced KOReader Sync (Week 4)
+
+**Deliverables**:
+- Updated KOReader handler to accept SHA-256
+- Implement device file alias creation
+- Integrate auto-linking with confidence thresholds
+- Add SHA-256 matching for annotations
+
+**SHA-256 Matching for Progress Sync**:
+```go
+// Priority 1: UUID provided (highest confidence)
+if book.UUID != "" {
+ return book.UUID, nil
+}
+
+// Priority 2: SHA-256 provided (medium confidence)
+if book.SHA256 != "" {
+ mediaItem, err := db.GetMediaItemBySHA256(ctx, book.SHA256)
+ if err == nil {
+ return mediaItem.ID, nil
+ }
+}
+
+// Priority 3: Create device file alias
+if book.FilePath != "" {
+ alias, err := db.GetDeviceFileAlias(ctx, deviceID, book.FilePath)
+ if err == nil {
+ // Create new alias
+ db.CreateDeviceFileAlias(ctx, CreateDeviceFileAliasParams{
+ MediaItemID: mediaItemID,
+ DeviceID: deviceID,
+ FilePath: book.FilePath,
+ FileSHA256: book.SHA256,
+ ConfidenceScore: 0.7,
+ })
+ return alias.MediaItemID, nil
+ }
+ return alias.MediaItemID, nil
+}
+```
+
+**Deliverables**:
+- Enhanced KOReader handlers
+- SHA-256 matching integration
+- Device file alias system integration
+- Auto-linking with configurable thresholds
+
+### Phase 8: Sidecar Configuration System (Week 4)
+
+**Deliverables**:
+- Sidecar JSON generation
+- Sidecar download/upload handlers
+- System configuration support
+
+**Sidecar File Format (Enhanced)**:
+```json
+{
+ "version": "1.0",
+ "bookmann": {
+ "opds_catalog": "http://192.168.1.100:8765/opds/devices/kobo-id/catalog",
+ "sync_api": "http://192.168.1.100:8765/api/sync/kobo",
+ "opds_base_url": "http://192.168.1.100:8765/opds",
+ "api_base_url": "http://192.168.1.100:8765/api",
+ "device_id": "kobo-device-uuid"
+ },
+ "books": {
+ "sha256:abc123...": {
+ "bookmann_uuid": "uuid-123",
+ "title": "The Hobbit",
+ "author": "J.R.R. Tolkien",
+ "available_formats": ["epub", "kepub"]
+ }
+ },
+ "collections": [
+ {
+ "name": "Sci-Fi",
+ "shelf_mapping": "Science Fiction",
+ "book_ids": ["uuid-1", "uuid-2", "uuid-3"]
+ }
+ ],
+ "opds_enabled": true,
+ "sidecar_enabled": true,
+ "last_updated": "2026-01-31T12:00:00Z"
+}
+```
+
+**Deliverables**:
+- Sidecar generation system
+- System configuration support
+- Admin UI for system settings
+
+### Phase 9: Frontend Implementation (Week 5-6)
+
+**Deliverables**:
+- Collections management pages
+- Device configuration pages
+- Enhanced progress visualization with sync sources
+- Unlinked books resolution UI
+- Collection rule builder UI
+- Device-specific view settings UI
+
+**Deliverables**:
+- Collections list/detail pages
+- Device management interface
+- Progress sync dashboard with device indicators
+- Book matching UI with confidence indicators
+
+### Phase 10: Documentation & Testing (Week 6)
+
+**Deliverables**:
+- Updated device setup guides
+- Complete API documentation
+- Test suite covering all scenarios
+- User acceptance testing
+
+**Deliverables**:
+- KOBO_SETUP.md update with OPDS workflow
+- KOREADER_SETUP.md new file with OPDS instructions
+- Complete API reference documentation
+- User guides for all device types
+
+---
+
+## Device Setup Instructions
+
+### Kobo E-Reader Setup (OPDS Primary Method)
+
+#### Option 1: OPDS Catalog (Recommended - Wireless Delivery + Progress Sync)
+
+**Step 1: Download Configuration File**
+```
+1. Log into Bookmann web UI
+2. Go to Device Management → Your Kobo device
+3. Click "Download Configuration" button
+4. File downloads as `.bookmann.json`
+```
+
+**Step 2: Configure Kobo for OPDS**
+```
+1. On Kobo, go to Settings → Sync & Backup
+2. Tap "Add Content Server" or "Add OPDS Feed"
+3. Enter URL from `.bookmann.json`:
+ http://192.168.1.100:8765/opds/devices/YOUR_DEVICE_ID/catalog
+4. Kobo will automatically:
+ - Connect to Bookmann
+ - Browse your library wirelessly
+ - Download books directly
+ - Sync reading progress back to Bookmann
+```
+
+**Step 3: Wireless Book Acquisition**
+```
+1. On Kobo, go to "My Books" section
+2. Browse Bookmann catalog via OPDS
+3. Tap on any book to download wirelessly
+4. Book appears on Kobo device
+5. Start reading - progress syncs automatically
+```
+
+**How Progress Sync Works**:
+- Kobo generates ContentId for each book
+- ContentId mapped to Bookmann UUID in device_catalogs table
+- When Kobo syncs progress, Bookmann uses canonical UUID
+- Format conversion (KEPUB) doesn't break progress tracking
+
+### KOReader Setup
+
+#### Option 1: OPDS Catalog (Recommended)
+
+**Step 1: Download Configuration File**
+```
+Same as Kobo setup above
+```
+
+**Step 2: Configure KOReader for OPDS**
+```
+1. Open KOReader settings
+2. Enable "OPDS catalog" in network/synchronization section
+3. Enter OPDS URL from `.bookmann.json`:
+ http://192.168.1.100:8765/opds/devices/YOUR_DEVICE_ID/catalog
+4. KOReader will automatically:
+ - Connect to Bookmann catalog
+ - Browse and download books wirelessly
+ - Sync progress using SHA-256 matching
+ - Create file aliases automatically
+```
+
+**Step 3: Wireless Book Acquisition**
+```
+1. Open KOReader file browser
+2. Tap "+" button to add OPDS catalog
+3. Browse Bookmann catalog
+4. Download books directly
+5. Start reading
+```
+
+#### Option 2: Sidecar File (Alternative - Enhanced Progress Sync)
+
+**For offline or simple setup**
+
+**Step 1: Download Sidecar**
+```
+Same as Kobo setup above
+```
+
+**Step 2: Place Sidecar on KOReader**
+```
+Place in KOReader's config directory
+```
+
+**Step 3: Use Sidecar for Progress Sync**
+```
+KOReader plugin reads .bookmann.json
+→ Matches local files to Bookmann UUIDs via SHA-256
+→ Syncs progress using canonical UUIDs
+→ Works offline
+```
+
+### Web & Mobile Setup
+
+```
+OPDS catalog automatically available at:
+/opds/devices/:deviceId/catalog
+
+Apps can:
+- Browse entire library wirelessly
+- Download books directly
+- See collection metadata
+- Sync progress via existing internal APIs
+```
+
+---
+
+## Security Considerations
+
+### Authentication Layers
+
+**Layer 1: Web & Mobile (Internal API)**
+```
+Uses: JWT tokens
+Issued by: POST /api/auth/login, /api/auth/refresh
+Validated: On each request via middleware
+Revoked by: POST /api/auth/logout
+Stored in: refresh_tokens table (not devices table)
+```
+
+**Layer 2: Sync APIs (Device Tokens)**
+```
+Issued by: Device registration endpoint
+Stored in: devices.auth_token field
+Validated by: Device authentication middleware
+```
+
+**Layer 3: OPDS (Device Tokens, Optional)**
+```
+Issued by: /api/devices/:id/opds-register
+Stored in: opds_tokens table
+Scope: Device-specific access to catalog
+
+Can be: Public (no authentication required)
+```
+
+### Data Privacy
+
+1. **Progress & Annotations**: Always associated with user_id in database
+2. **Collections**: User-scoped - each user sees only their collections
+3. **File Aliases**: Device-specific - never shared across users
+4. **Device Catalogs**: Links stored per-device - no cross-user leakage
+5. **Sidecar Files**: Contain only user's device token and book mappings
+
+### Access Control
+
+**OPDS Authorization Flow:**
+```
+1. OPDS request includes device_id in URL path
+2. Server validates:
+ a. Device exists
+ b. Device belongs to requesting user
+ c. Book is in user's visible library
+3. If validation passes: Serve OPDS feed
+```
+
+**Public Catalog Option**:
+- Can be enabled in system_config
+- Allows guest users to browse without device registration
+- Still respects library visibility per user
+
+---
+
+## Testing Strategy
+
+### Unit Tests
+
+**Coverage Areas**:
+1. Hash calculation accuracy (SHA-256, OPF extraction)
+2. Matching algorithm priorities
+3. Collection rule evaluation
+4. OPDS XML serialization
+5. Format conversion integrity
+
+### Integration Tests
+
+**Test Scenarios**:
+1. Cross-device book matching (same book, different paths)
+2. Format conversion (EPUB → KEPUB) with hash integrity
+3. Collection auto-assign (rules fire correctly)
+4. Bidirectional progress sync (Kobo ↔ KOReader)
+5. OPDS catalog generation and pagination
+6. Sidecar file generation and validation
+
+### Manual Testing Checklist
+
+**Kobo Workflow**:
+- [ ] Download `.bookmann.json` from web UI
+- [ ] Transfer to Kobo via USB
+- [ ] Configure OPDS URL on Kobo
+- [ ] Browse catalog wirelessly
+- [ ] Download book
+- [ ] Read 50% of book
+- [ ] Verify progress syncs to Bookmann
+
+**KOReader Workflow**:
+- [ ] Download `.bookmann.json` from web UI
+- [ ] Configure OPDS URL in KOReader
+- [ ] Browse catalog wirelessly
+- [ ] Download book
+- [ ] Read 75% of book
+- [ ] Verify progress syncs to Bookmann
+
+**Cross-Device Scenario**:
+- [ ] Add book to Bookmann (EPUB scanned)
+- [ ] Download to Kobo via OPDS
+- [ ] Sync progress (60%) from Kobo
+- [ ] Open same book on KOReader (side-loaded)
+- [ ] Read to 75% on KOReader
+- [ ] Verify progress shows 75% (latest from either device)
+- [ ] Verify sync sources tracked correctly
+
+---
+
+## Glossary
+
+- **Bookmann UUID**: Canonical identifier for a book in Bookmann system (from `media_items.id`). Always used for progress tracking, never SHA-256. SHA-256 is only for matching books across devices.
+- **ContentId**: Device-generated identifier (e.g., Kobo's "kobo_abc"). Mapped to Bookmann UUID in `device_catalogs` table. Used for progress sync after OPDS downloads.
+- **SHA-256**: Cryptographic hash of file contents. Used for content-based matching across devices. Critical for identifying same book on different devices.
+- **OPF UUID**: Unique identifier from EPUB metadata ``. High-confidence identifier format.
+- **OPF Identifier**: Any identifier from EPUB OPF file (custom format). Medium-confidence identifier format.
+- **ISBN**: International Standard Book Number (13 digits). Medium-confidence standard identifier.
+- **ASIN**: Amazon Standard Identification Number (10 characters). Medium-confidence standard identifier.
+- **Collections**: Device-neutral organizational groups in Bookmann (e.g., "Science Fiction", "Reading"). Books can be in collections without being on any device. Collections organize library, not track device inventory.
+- **Shelves**: Device-specific organization (e.g., Kobo's terminology). Map Collections to device-specific "Shelves" only at device-level. Bookmann UI always uses "Collections" terminology.
+- **OPDS**: Open Publication Distribution System. Industry standard for book catalogs. All e-reader platforms have OPDS clients. Kobo, KOReader, Aldiko, FBReader, Web browsers can use OPDS catalogs.
+- **Internal APIs**: Bookmann's private REST/WebSocket endpoints for state management. Web and mobile apps use these directly. Used for two-way sync, collections, WebSocket real-time updates.
+- **Device File Alias**: Mapping of device-specific file paths to Bookmann UUIDs. Enables cross-device matching when same book has different file paths.
+- **Hash Confidence**: Scoring system (0.0-1.0) for automatic book matching reliability. Higher values = more reliable match.
+- **Dual Hash Storage**: Storing both original EPUB hash (`epub_sha256`) and converted KEPUB hash (`kepub_sha256`). Preserves hash integrity when files are converted. OPDS responses include format-specific hash for sidecar matching.
+- **Format Conversion**: Transcoding between book formats (EPUB → KEPUB). KEPUB adds Kobo-specific markup. Critical for Kobo optimization but shouldn't break progress tracking.
+- **Media Item Formats**: Tracks all format versions with their hashes. Pre-convert EPUB to KEPUB during scan for optimal performance.
+- **System Config**: Key-value store for system-wide settings (base_url, opds_base_url, api_base_url). Enables flexible deployment.
+- **OPDS Tokens**: Per-device access tokens for OPDS catalog browsing. Optional - can also support user-scoped and admin tokens.
+- **Sidecar File**: `.bookmann.json` - Unified configuration file for devices. Contains OPDS URLs, sync API endpoints, book mappings, collection mappings.
+- **Auto-Assign Rules**: Configurable criteria for automatically adding books to collections. Fields: genre, series, author, language, publisher, copyright_year, tags. Operators: equals, contains, starts_with, ends_with, greater_than, less_than.
+- **Sync Direction**: For device shelf mappings. 'bidirectional' (sync both ways), 'book_to_device' (send to device), 'device_to_book' (read from device), 'none' (no sync).
+- **View Settings**: Per-device preferences for how collections are displayed (grid vs list, which collections are visible).
+- **Unlinked Book**: Progress record without proper media_item_id or failed ContentId lookup. Needs manual user resolution.
+
+---
+
+## Summary
+
+This comprehensive implementation plan provides:
+
+- **7 new database tables** with proper indexing
+- **50+ API endpoints** across 6 layers (identification, collections, OPDS, sync, configuration)
+- **10-week phased implementation** with clear deliverables
+- **Complete device setup guides** for Kobo, KOReader, Web, and Mobile
+- **Three-tier authentication model** for security (JWT, device tokens, OPDS optional)
+- **Glossary** of all terminology and concepts
+- **Testing strategies** covering unit, integration, and manual validation
+
+The plan is designed for systematic execution while maintaining architectural consistency and enabling human oversight throughout the development process. All decisions from our conversations have been incorporated, providing a complete roadmap for implementing Bookmann as a comprehensive cross-device ebook management system.
\ No newline at end of file