# AI Agent Briefing — PDF OCR Hotfolder **Zuletzt aktualisiert:** 2026-04-08 **Version:** 0.2.0 **Status:** Multi-Instanz-Support, nicht produktiv getestet ## 🎯 Projektziel Eingehende gescannte PDFs werden automatisch durch OCR (ocrmypdf + Tesseract) in durchsuchbare PDFs (optional PDF/A) umgewandelt und nach Wahl in einen Ordner / Nextcloud / per SFTP weitergegeben. Ersetzt das alte Bash-Tool `pdf-tool` (im Workspace). ## 📁 Projekt-Struktur ``` pdf-ocr-hotfolder/ ├── pdf_ocr_hotfolder/ │ ├── __init__.py # Versionsstring │ ├── __main__.py # CLI-Entrypoint (argparse, --once, --config) │ ├── config.py # TOML-Loader, Dataclasses │ ├── service.py # Hauptservice (watchdog + ThreadPool) │ ├── processor.py # ocrmypdf + veraPDF │ └── uploaders.py # folder, nextcloud (WebDAV), sftp, email ├── systemd/ │ └── pdf-ocr-hotfolder@.service # systemd Template-Unit (Instanz = %i) ├── config.example.toml ├── install.sh # Interaktiver Installer ├── update.sh # Update aus Repo ├── requirements.txt ├── VERSION ├── CHANGELOG.md └── README.md ``` ## 🔧 Stack | Komponente | Technologie | |------------|-------------| | Sprache | Python 3.11+ (für `tomllib` aus stdlib) | | OCR | `ocrmypdf` (als Library, nicht via Subprozess) | | Engine | Tesseract | | Watcher | `watchdog` | | HTTP | `requests` (Nextcloud WebDAV) | | SFTP | `paramiko` | | Email | `smtplib` (stdlib) | | Service | systemd | ## 🖥️ Installations-Layout (Multi-Instanz) | Pfad | Inhalt | |------|--------| | `/opt/pdf-ocr-hotfolder/` | Code + venv (für alle Instanzen gemeinsam) | | `/etc/pdf-ocr-hotfolder/.toml` | Config pro Instanz (mode 640, root:) | | `/etc/systemd/system/pdf-ocr-hotfolder@.service` | Template-Unit | | `/etc/systemd/system/pdf-ocr-hotfolder@.service.d/user.conf` | Drop-in für abweichenden User (optional) | | `/var/lib/pdf-ocr-hotfolder//{incoming,working,outgoing,error}/` | Daten pro Instanz | | `/var/log/pdf-ocr-hotfolder/` | Logs | | `/var/backups/pdf-ocr-hotfolder/` | Update-Backups | ## 👤 Service-User - Basis-Install legt Default-User `pdfocr` an (als System-User, falls nicht schon vorhanden) - Beim Anlegen einer Instanz fragt der Installer nach dem Service-User (default `pdfocr`) - Wird ein **abweichender** User gewählt, wird ein systemd-Drop-in erstellt (`pdf-ocr-hotfolder@.service.d/user.conf`) mit `User=/Group=` Override - Existierende User (lokal oder AD via SSSD/Winbind) werden übernommen, primäre Gruppe via `id -gn` ermittelt - Bei AD-Usern mit lokaler UID werden Datei-Berechtigungen über die UID gesetzt — transparent ## 🗂️ Instanz-Management `install.sh` ist gleichzeitig **Installer und Instanz-Manager**: - Erster Lauf: Basis-Install + erste Instanz anlegen (Pflicht) - Folgender Lauf: Basis-Install wird übersprungen, bestehende Instanzen werden gelistet, weitere Instanzen können ergänzt werden - Eingaben pro Instanz: Name (`[a-z0-9-]+`), Basis-Pfad (default `/var/lib/pdf-ocr-hotfolder/`), Service-User - `config.toml` wird aus `config.example.toml` mit sed-substituierten Pfaden generiert - Instanz wird sofort `enable --now` gestartet Manuelles Löschen einer Instanz: ```bash systemctl disable --now pdf-ocr-hotfolder@ rm /etc/pdf-ocr-hotfolder/.toml rm -rf /etc/systemd/system/pdf-ocr-hotfolder@.service.d systemctl daemon-reload # Datenverzeichnis /var/lib/pdf-ocr-hotfolder/ manuell aufräumen ``` ## 🔄 Update-Verhalten `update.sh`: 1. Ermittelt alle aktiven `pdf-ocr-hotfolder@*.service` Units 2. Stoppt diese 3. Backup nach `/var/backups/pdf-ocr-hotfolder/` 4. Kopiert Code + requirements + VERSION + config.example aus dem Repo 5. `pip install --upgrade` im venv 6. Aktualisiert Template-Unit + `daemon-reload` 7. Startet alle zuvor aktiven Instanzen wieder 8. Exit 1 wenn eine Instanz nicht mehr hochkommt Config-Dateien werden **nie** überschrieben. ## 🔄 Verarbeitungs-Flow 1. `watchdog` triggert auf Datei-Event in `incoming/` 2. `_wait_until_stable()` wartet, bis Datei nicht mehr wächst (Scanner schreibt mehrmals) 3. Move nach `working/` 4. `ocrmypdf.ocr()` als **Library-Call** (kein Subprozess-Start pro PDF — schneller) 5. Optional: veraPDF-Validierung (CLI-Subprozess) 6. Move nach `outgoing/` als `OCR_.pdf` 7. Aktive Upload-Targets ausführen (folder/nextcloud/sftp) 8. Optional E-Mail-Notify Fehler → Move nach `error/`, Service läuft weiter (kein `exit 1` wie im alten Bash-Tool). ## 🧠 Performance-Entscheidungen - **ocrmypdf als Library** statt `subprocess`: spart Python-Interpreter-Start pro PDF - **ThreadPool** mit `max_workers` (default 2) — selbst wenn selten >1 PDF gleichzeitig kommt, blockiert ein langsamer Scan keinen schnellen - **`--jobs` an ocrmypdf**: Tesseract parallelisiert Seiten innerhalb eines PDFs - **`skip_text=True`**: bereits OCR-haltige Seiten werden nicht neu verarbeitet - **Stabilitäts-Check** statt magic-file `new` (alte Bash-Krücke) - veraPDF nur wenn `enabled=true` (JVM-Start ist teuer) ## 🛠️ Entwicklung Lokaler Test ohne Installation: ```bash cd ~/dev/gitea.sonith.de/pdf-ocr-hotfolder python3 -m venv venv && source venv/bin/activate pip install -r requirements.txt cp config.example.toml /tmp/config.toml # Pfade in /tmp/config.toml auf Test-Verzeichnisse anpassen python -m pdf_ocr_hotfolder --config /tmp/config.toml ``` ## 📋 Roadmap / TODO - [ ] Tests (`pytest`) für `processor` und `uploaders` - [ ] Prometheus-Metriken (verarbeitete PDFs, Fehlerquote, Laufzeit) - [ ] CLI-Subkommandos: `pdf-ocr-hotfolder reprocess ` - [ ] Optional: S3/MinIO Upload-Target - [ ] Docker-Image für Setups ohne systemd ## 🔑 Repo - **Repo:** https://gitea.sonith.de/sonith_ug/pdf-ocr-hotfolder - **Owner:** sonith_ug - **Versionierung:** Semver (PATCH bei jedem Build, MINOR bei Features, MAJOR manuell) - **Tags:** `v{VERSION}`, automatischer Push nach Commit ## 📞 Kontakt **Maintainer:** Dominik Höfling (Sonith GmbH)