# Novela 2.0 - Technical Status (Develop) ## Scope Dit document beschrijft de actuele technische status van de `develop` codebase. Dit document is de primaire technische documentatie voor de huidige codebase. ## Architecture - Stack: FastAPI, Jinja2 templates, plain JS, PostgreSQL 16, Docker. - Startup lifecycle (`main.py`): 1. `init_pool()` 2. `run_migrations()` 3. `start_backup_scheduler()` 4. routers mounten - Shutdown lifecycle: 1. `stop_backup_scheduler()` 2. `close_pool()` - Source-of-truth regel: bestand op schijf leidend, database als index/cache. ## Router Status ### `routers/library.py` - `GET /library` - `GET /api/library` - `POST /library/rescan` - `POST /library/import` (EPUB/PDF/CBR/CBZ) - `DELETE /library/file/{filename}` - `GET /library/cover/{filename}` - `GET /library/cover-cached/{filename}` - `POST /library/cover/{filename}` (EPUB) - `POST /library/want-to-read/{filename}` - `POST /library/archive/{filename}` - `POST /library/new/mark-reviewed` (bulk `needs_review=false`) - `GET /home` - `GET /api/home` - `GET /stats` - `GET /api/stats` - `GET /library/list` (compat) `GET /api/library` draait standaard in fast-path (DB-only, geen full disk rescan). Voor geforceerde sync: `GET /api/library?rescan=true` of `POST /library/rescan`. `include_file_info=true` is optioneel voor bestandsgrootte/mtime verrijking. `/api/home` levert: - `continue_reading` - `shorts_unread` - `novels_unread` - `shorts_read` - `novels_read` `/api/stats` levert naast totals ook chart- en history-data voor `stats.html`: - `reads_by_month`, `reads_by_dow`, `reads_by_hour` - `genre_counts`, `publisher_counts`, `fav_genre`, `fav_publisher` - `top_books`, `history` Home-secties filteren series uit met: - `COALESCE(series, '') = ''` - `filename NOT LIKE '%/Series/%'` Read-secties op Home zijn gesorteerd op oudste eerst: - `shorts_read`: `ORDER BY MAX(read_at) ASC` - `novels_read`: `ORDER BY MAX(read_at) ASC` ### `routers/reader.py` - Epub serving/chapters/images - Reader pagina + book detail - Metadata patch (`PATCH /library/book/{filename}`) - Progress read/write/delete - Mark-as-read - PDF render endpoint - CBR/CBZ page endpoint - Genres endpoint ### `routers/editor.py` - Editor pagina - Chapter get/save - Chapter add - Chapter delete ### `routers/grabber.py` - Grabber pagina + convert/debug flows - SSE events - Credentials beheer voor scraper-sites - Credentials manager UI (`/credentials-manager`) ### `routers/backup.py` - `GET /backup` - `GET/POST/DELETE /api/backup/credentials` - `GET /api/backup/health` - `GET /api/backup/status` - `GET /api/backup/history` - `POST /api/backup/run` ## Backup & Security - Dropbox token encrypted-at-rest in `credentials` (`site='dropbox'`). - Dropbox backup root encrypted opgeslagen in `credentials` (`site='dropbox_backup_root'`). - Retentie (`snapshots to keep`) encrypted opgeslagen in `credentials` (`site='dropbox_backup_retention'`). - Backup schedule (`enabled` + `interval_hours`) encrypted opgeslagen in `credentials` (`site='dropbox_backup_schedule'`). - Encryptie via `NOVELA_MASTER_KEY` (Fernet). Implementatie: - Versie-gebaseerde backups met deduplicatie: - bestandsobjecten in Dropbox: `library_objects/{sha256_prefix}/{sha256}` - snapshots in Dropbox: `library_snapshots/snapshot-YYYYMMDD-HHMMSS.json` - Elke run maakt een nieuwe snapshot (versie) en uploadt alleen ontbrekende objecten. - Retentie verwijdert oude snapshots boven de ingestelde limiet. - Orphan object-prune verwijdert objecten die niet meer door retained snapshots worden gerefereerd. - Lokale manifestcache (`config/backup_manifest.json`) versnelt changeddetectie. - Database backup via `pg_dump` naar Dropbox `postgres/`. - `POST /api/backup/run` start altijd als background task en geeft direct status terug. - Scheduler draait in achtergrond (`start_backup_scheduler`) en triggert op interval als backup aanstaat. - Concurrentierestrictie: slechts 1 backup tegelijk. - Bij container restart/crash worden stale `running` logs automatisch gemarkeerd als interrupted/error. ## Environment `stack/novela.env` bevat nu minimaal: - `POSTGRES_DB` - `POSTGRES_USER` - `POSTGRES_PASSWORD` - `NOVELA_MASTER_KEY` - `CONFIG_DIR` Dropbox settings verlopen via webinterface op `/backup`. ## UI Notes - Library import accepteert: EPUB/PDF/CBR/CBZ. - Home heeft dezelfde importmogelijkheden. - Home heeft zoekfunctionaliteit. - Home header/dropzone uitlijning gelijkgetrokken met Library (zoek rechtsboven, dropzone eronder). - `New` view ondersteunt `Grid` en `List` mode. - Bulk selectie + `Remove from New` werkt alleen in `List` mode. - `List` mode heeft kolomfilter (aan/uit) met kolommen: - Publisher - Author - Series - Volume - Title - Has cover - Updated - Genres - Sub-genres - Tags - Status - `List` mode ondersteunt multi-select met `Shift+klik` range-select op checkboxes. - `Grid` mode toont geen selectie-checkboxes of bulkacties. - Backup pagina ondersteunt: - handmatige run en dry-run - instellingen voor Dropbox root - retentie-aantal snapshots - geplande backup (aan/uit + interval in uren) - status + history overzicht ## Known Conventions - Verwijderen boek: bestand verwijderen, lege mappen prunen, daarna `DELETE FROM library` (cascade op child-tabellen). - Cover strategie: - EPUB: cover uit bestand + cache - PDF/CBR: thumbnail via cover cache ## Performance Notes - Library-load geoptimaliseerd voor grote datasets: - `list_library_json()` gebruikt pre-aggregatie voor `reading_sessions`. - `has_cached_cover` komt direct uit SQL join i.p.v. losse volledige cache-fetch. - Nieuwe migrations-indexen: - `idx_library_sort_coalesce` - `idx_library_needs_review` - `idx_library_archived` - `idx_reading_sessions_filename_readat` - `idx_book_tags_filename_tag`