# Architettura — CrossPoint Newsletter Server ## 1. Flusso End-to-End ```text ┌─────────────────────────────────────────────────────────────────────────────┐ │ CrossPoint Newsletter Server │ │ │ │ ┌──────────┐ ┌─────────────┐ ┌──────────────────┐ │ │ │ IMAP │ │ Transform │ │ Storage │ │ │ │ Ingest │───▶│ HTML→EPUB │───▶│ SQLite + Files │ │ │ │ │ │ + Images │ │ │ │ │ └──────────┘ └─────────────┘ └────────┬─────────┘ │ │ ▲ │ │ │ │ polling ┌─────────┼─────────┐ │ │ │ periodico │ │ │ │ │ ┌─────▼───┐ ┌───▼─────┐ ┌▼────────┐ │ │ ┌──────────┐ │ Calibre │ │ OPDS │ │ WebUI │ │ │ │ Casella │ │ Export │ │Standalone│ │ Gestione│ │ │ │ Email │ │ │ │ (FastAPI)│ │ │ │ │ │ Dedicata │ └────┬────┘ └────┬────┘ └─────────┘ │ │ └──────────┘ │ │ │ └───────────────────────────────────┼───────────┼────────────────────────────┘ │ │ ┌─────▼───┐ ┌────▼────┐ │ Calibre │ │ Feed │ │ -Web │ │ OPDS │ │ OPDS │ │ :8400 │ └────┬────┘ └────┬────┘ │ │ └─────┬─────┘ │ ┌────▼────┐ │CrossPoint│ │ Reader │ │ (Wi-Fi) │ └────┬────┘ │ ┌────▼────┐ │ microSD │ │ (lettura │ │ offline) │ └─────────┘ ``` ## 2. Contratto con il Firmware CrossPoint Il Newsletter Server comunica con il reader **esclusivamente** tramite il protocollo OPDS 1.2 standard. Non richiede modifiche al firmware. | Aspetto | Specifica | |:---|:---| | **Formato output** | EPUB 3.0 | | **Protocollo** | OPDS 1.2 Atom XML | | **Autenticazione** | HTTP Basic Auth | | **Metadati OPDS** | `title` = subject email, `author` = nome newsletter, `series` = nome newsletter, `series_index` = progressivo | | **Copertina** | `` — PNG 600×800 | | **Download** | `` | | **Resilienza offline** | EPUB scaricati sulla microSD restano leggibili con server spento | Questo contratto è stato **validato su hardware** nello Step firmware 08: - OPDS 1.2 Atom XML navigato con successo. - HTTP Basic Auth funzionante (testato con Calibre-Web su Tower). - EPUB scaricato, salvato su microSD, letto offline. ## 3. Componenti e Responsabilità ### 3.1 Ingest (`src/crosspoint_newsletter/ingest/`) | Responsabilità | Dettaglio | |:---|:---| | Polling IMAP | Connessione periodica alla casella email dedicata | | Matching | Associazione email → newsletter per `sender_email` + regole | | Deduplica | Verifica `Message-ID` contro il database | | Estrazione | Corpo HTML + immagini inline (CID) | | Output | Record `Issue` in stato `pending` | Non fa: conversione, storage permanente, distribuzione. ### 3.2 Transform (`src/crosspoint_newsletter/transform/`) | Responsabilità | Dettaglio | |:---|:---| | Pulizia HTML | Rimozione script, tracking pixel, link unsubscribe | | Generazione EPUB | EPUB 3.0 con metadati serie (Calibre tags) | | Ottimizzazione immagini | Grayscale 8-bit, resize ≤800px, compressione | | Generazione copertina | PNG 600×800 programmatica | | Quality gate | Validazione EPUB (dimensione, integrità, encoding) | | Output | File EPUB + Issue in stato `done` o `error` | Non fa: ingestione email, archiviazione, distribuzione. ### 3.3 Storage (`src/crosspoint_newsletter/storage/`) | Responsabilità | Dettaglio | |:---|:---| | Database | CRUD Newsletter + Issue, query per feed, migrazioni | | Filesystem | Organizzazione `data/epub/`, `data/raw/`, `data/covers/` | | Retention | Applicazione policy di cancellazione (max issues, max age) | | CLI | Comandi `cn` per gestione da terminale | Non fa: conversione, rete, distribuzione. ### 3.4 Serve (`src/crosspoint_newsletter/serve/`) | Responsabilità | Dettaglio | |:---|:---| | OPDS standalone | Feed OPDS 1.2 via FastAPI (canale primario: root, recenti, serie, download, cover) | | Calibre export | *(Deprecato/Disabilitato)* — Sostituito dal feed standalone per non sporcare la libreria Calibre | | WebUI | Dashboard, CRUD newsletter, libreria, impostazioni | | API REST | Endpoint JSON per WebUI e client esterni | | Autenticazione | HTTP Basic Auth su OPDS e WebUI | Non fa: ingestione, conversione, storage diretto. ## 4. Stack Tecnologico | Componente | Tecnologia | |:---|:---| | Linguaggio | Python ≥ 3.12 | | Web framework | FastAPI + Uvicorn | | Template engine | Jinja2 (WebUI) | | Database | SQLite 3 (con FTS5 opzionale) | | Generazione EPUB | ebooklib | | Parsing HTML | BeautifulSoup4 + lxml | | Immagini | Pillow | | Configurazione | python-dotenv + PyYAML | | Containerizzazione | Docker (python:3.12-slim) + Docker Compose | | Deploy target | Unraid Tower (your-unraid-ip) | ## 5. Confini Architetturali ```text ┌──────────────────────────────────────┐ │ Responsabilità SERVER │ │ │ │ • Ingestione email │ │ • Conversione HTML → EPUB │ │ • Catalogazione e storage │ │ • Feed OPDS + API + WebUI │ │ • Autenticazione │ │ • Backup e retention │ └──────────────────────────────────────┘ ▲ OPDS 1.2 (unico punto di contatto) │ ┌──────────┴───────────────────────────┐ │ Responsabilità FIRMWARE │ │ │ │ • Navigazione catalogo OPDS │ │ • Download EPUB su microSD │ │ • Rendering e lettura e-ink │ │ • Gestione Wi-Fi e credenziali │ │ • Funzionamento offline │ └──────────────────────────────────────┘ ``` - Il server **non contiene** codice ESP32, driver display o logica firmware. - Il firmware **non contiene** logica di ingestione, conversione o schedulazione. - L'unico accoppiamento è il **contratto OPDS 1.2** documentato nella sezione 2.