Files
pdf-ocr-hotfolder/AI_AGENT_BRIEFING.md
T
techadmin 985a33d3f9 feat: Multi-Instanz-Support via systemd Template-Unit (v0.2.0)
- pdf-ocr-hotfolder@<name>.service mit Config pro Instanz
- install.sh als Instanz-Manager: erkennt bestehende, fragt nach weiteren
- Optional eigener Service-User pro Instanz (systemd drop-in)
- update.sh stoppt/startet alle aktiven Instanzen automatisch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 14:31:58 +02:00

151 lines
6.0 KiB
Markdown

# 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/<instanz>.toml` | Config pro Instanz (mode 640, root:<service-group>) |
| `/etc/systemd/system/pdf-ocr-hotfolder@.service` | Template-Unit |
| `/etc/systemd/system/pdf-ocr-hotfolder@<instanz>.service.d/user.conf` | Drop-in für abweichenden User (optional) |
| `/var/lib/pdf-ocr-hotfolder/<instanz>/{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@<instanz>.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/<name>`), 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@<name>
rm /etc/pdf-ocr-hotfolder/<name>.toml
rm -rf /etc/systemd/system/pdf-ocr-hotfolder@<name>.service.d
systemctl daemon-reload
# Datenverzeichnis /var/lib/pdf-ocr-hotfolder/<name> 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_<originalname>.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 <error-file>`
- [ ] 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)