Files
rippy/SAVEPOINT.md
T
Hitonabi ab75134931
Ampel / ampel (push) Successful in 29s
feat: Download-Knopf fuer fertige Rips — Dateien direkt im Browser statt scp
- GET /jobs/{id}/files: Dateiliste aus job.output_path (Name + Groesse)
- GET /jobs/{id}/files/{name}: FileResponse-Stream; Validierung strikt —
  output_path muss unter /app/media liegen, nackter Dateiname (kein
  Slash/.., kein Dotfile), realpath-Check gegen Symlink-Ausbrueche.
  Mit Test (test_dateiname_validierung_blockt_pfad_tricks).
- UI: 'Download'-Knopf in der Aktion-Spalte bei fertigen Jobs; die
  Dateiliste mit Groessen + Download-Links lebt im Job-Detail-Popup
  (ein Dropdown wuerde im overflow-x-auto-Tabellencontainer clippen).
- nginx: proxy_buffering off + proxy_read_timeout 3600s waren fuer SSE
  schon gesetzt — grosse Downloads brauchen keine Aenderung.

Wunsch aus der Uebernahme-Session (Commander-Sammelliste 24.07.).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 09:01:38 +02:00

213 lines
11 KiB
Markdown

# SAVEPOINT — Rippy
## Aktueller Stand: v3.2 — Universal-Komfort-Runde + Ampel entrostet (24.07.2026, Claude)
**Wichtigster Befund zuerst: die Ampel war seit dem 23.07. ROT und `stable`
hing 10 Commits hinter `main`** — deshalb kam nichts Neues mehr auf die VM.
Zwei Ursachen, beide behoben:
1. bcrypt ≥ 4.1 bricht passlib 1.7.4 (`__about__` entfernt → Selbsttest wirft
„password cannot be longer than 72 bytes") → **bcrypt==4.0.1 gepinnt**.
2. Der cache_keys-Test kannte den Disc-Fingerprint im Prescan-Key (23.07.)
nicht → Test an das echte Format angepasst + Fingerprint-Testfall dazu.
**Neu in v3.2 (Commander-Sammelauftrag, alles mit Tests / Vite-Build grün):**
- **Media-Server-Integration**: Setting `mediaServer` (Wizard + Einstellungen →
Ripping): Zielordner „Titel (Jahr)" statt Job-UUID; für Jellyfin/Emby/Kodi
zusätzlich movie.nfo/tvshow.nfo + poster.jpg (Worker: medien.py). Plex = nur
Benennung. Job speichert Disc-Metadaten jetzt mit (jobs.meta, Migration).
- **Benachrichtigungen ECHT**: notify.py in API+Worker (Discord/Slack/ntfy/
generisch, Erkennung an der URL) — das Feld war vorher ein Placebo. Meldung
bei fertig/fehlgeschlagen/abgebrochen; Anleitung + „Test senden" im UI.
- **SMB-Scan-Fix**: „NT_STATUS_ACCESS_DENIED" heißt jetzt im Klartext „Gast-
Abfrage verweigert → Benutzer/Passwort eintragen"; Credential-Felder stehen
im UI VOR dem Auflisten-Knopf. NAS-Ziel-Anlage quittiert per Toast.
- **4K-UHD-Vorsorge**: Arbeitsverzeichnis `workDir` konfigurierbar (auf
NAS-Freigabe legbar), Platz-Check per Disc-Größe (ioctl) VOR dem Rip mit
Klartext-Abbruch statt voller Platte bei 40 GB.
- **Einstellungen → System**: Werkzeug-Versionen je Worker (MakeMKV/HandBrake,
ENV MAKEMKV_VERSION im Image), Key-Quelle (ui/env/keiner), freier Platz;
**MakeMKV-Beta-Key im UI pflegbar** — gilt ab dem nächsten Rip, ohne Rebuild.
- **Job-Detail-Popup** (Klick auf Titel in „Neueste Jobs"): Poster, Jahr,
Beschreibung, Genres, Ablagepfad, Fehler (GET /jobs/{id}/detail).
- **Download fertiger Rips im Browser**: „Download"-Knopf bei fertigen Jobs
(Aktion-Spalte) → Dateiliste mit Größen im Detail-Popup, Stream via
GET /jobs/{id}/files/{name} (Pfad-Validierung strikt unter /app/media,
realpath-Check gegen Symlink-Ausbrüche) — vorher nur per scp erreichbar.
- **UI-Feedback**: Toast-System (ToastContext, ploppt oben rechts), drehende
Refresh-Knöpfe, Logs-Pills um Warnung/Fehler ergänzt, Datei-Browser zeigt
jetzt auch DATEIEN (grau, mit Größe) — der „leere" Bluray-Ordner war voll.
- **Favicon** (Disc, Indigo-Verlauf) + **Footer** „Created with ❤️ by LucyAI,
Claude and KrBrZ".
- **Doku**: README (Media-Server, Benachrichtigungen, UHD-Arbeitsverzeichnis,
„Rippy woanders bereitstellen"), ROADMAP Etappe 13 + Ideen-Katalog,
KONZEPT-Fortschreibungen (Abschnitt 10), AGENTS-Stand.
**Nächste Schritte:** unverändert die Fäden aus v3.1 (unten) + Ideen-Katalog
in der ROADMAP (Serien-Flow, Duplikat-Warnung, Jellyfin-Refresh, Auth).
---
## Vorheriger Stand: v3.1 — E2E BEWIESEN + Universal-Runde (24.07.2026, Claude)
**Der Beweis steht: Evangelion 2.22 (BD-50) komplett durch die Kette**
erkannt → verlustfrei gerippt (43 GB, LibreDrive) → H.264-komprimiert →
**4,8 GB Endergebnis** (Hauptfilm 3,3 GB + 4 Extras), Rohdaten automatisch
gelöscht. Retry-transcode dabei live bewiesen (x265 war auf 4 vCPUs zu lahm
→ Abbruch + Neustart mit H.264 OHNE Neu-Rip).
Seit v3.0 dazugekommen (alles deployt, Ampel grün):
- **Korrektur-Flow**: „Nicht korrekt?!"-Popup an der Disc-Karte; Suche über
alle Quellen (GET /metadata/search), Wahl wird 30 Tage per
Disc-Fingerabdruck gemerkt (POST /metadata/override)
- **Metadaten-Kette**: BD-Klartext-Titel via ro-Mount (bdmt_*.xml),
Jikan/MAL (keyless, Ähnlichkeits-Score), OMDb-Qualitäts-Gate,
Wort-Strip-Degradation, ehrliches Cache-TTL (unknown nie cachen)
- **Worker-Verwaltung** (Einstellungen → Worker): Live-Erreichbarkeit
(Celery-Ping + Minuten-Herzschlag), Copy-Paste-Anbindung neuer Maschinen
- **Speicherziele**: SMB-Freigaben-Auflistung, Schreibtest beim Mount,
lokaler Ordner-Browser + mkdir; Mounts via UI (CAP_SYS_ADMIN + rshared)
- **First-Run-Wizard**, Job-Abbruch (kooperativ), Transcode als eigener
Task auf Queue `transcode` (Basis Remote-GPU-Worker), ruff.toml gepinnt
**Nächste Schritte:** AI-Box als VAAPI-Transcode-Worker (VCN4; NFS-Export
nötig, deploy/remote-transcode-worker.yml) · TMDB-Key eintragen ·
Arcane-GitSync-Binding auf `stable` (aktuell Notfall-Deploy-Weg) ·
Metadaten-Seite entfernen, wenn Popup abgenommen · Jellyfin-Postprocessing
an Worker · Auth vor schreibende Endpoints · MAKEMKV_APP_KEY erneuern
(~Ende Juli, Forum t=1053).
---
## Vorheriger Stand: v3.0 — Kernumbau (23.07.2026, Claude)
**Der Zweck existiert jetzt wirklich.** Komplett-Audit ergab: „Disc rein →
gerippt raus" hatte nie einen Code-Pfad (Details in ROADMAP Etappe 11).
Kernpunkte des Umbaus:
- **Rip-Kette komplett neu**: POST /jobs → Celery → Worker (MakeMKV 1.18.4
verlustfrei, Etappe 10) → Postgres-Job-Status → UI. CD weiter via abcde.
- **Disc-Erkennung** über Kernel-ioctls (CDROM_DISC_STATUS + Größe), Watcher
pollt statt udev (im Container gibt es kein udev).
- **UI**: echter Vite-Build hinter nginx mit /api-Proxy — vorher Dev-Server
und hartkodiertes localhost:8000 (deshalb waren nie Laufwerke zu sehen).
- **Compose**: Laufwerk als devices: (Bind-Mounts gaben EPERM), Ausgabe auf
media-Volume (vorher /output → nicht gemountet + read-only-Falle).
- **Placebos entfernt**: Mock-Logs, toter SSE-Stream, udevadm-Discovery,
14 Troubleshooting-Altdateien (ARCAN-*.md, Setup-Skripte, udev-Rules).
**Hardware-Kette (23.07.):** Laufwerk (Verbatim 4K BD RW, BU40N 1.05) hängt am
Proxmox-Host; LPM-Quirk `usbcore.quirks=18a5:0428:k` gefixt die Serien-Disconnects
(reboot-fest in GRUB). VM 106 bekommt es per USB-Passthrough `host=18a5:0428`.
⚠️ Firmware 1.05 kann KEIN UHD-Ripping (verschlüsselt) — Crossflash auf 1.03-MK
ist der dokumentierte Weg, separater Faden. DVD/BD normal geht.
**Offen:** E2E mit echter Disc · Jellyfin-Post-Processing an Worker anbinden ·
Auth vor schreibende Endpoints · MAKEMKV_APP_KEY in Arcane-Env pflegen (monatlich).
---
## Vorheriger Stand
**v1.10 — Complete Dark Mode Implementation (22.07.2026)**
Rippy läuft auf Arcane VM (192.168.178.162):
- ✅ Arcane WebUI: http://192.168.178.162:3552
- ✅ Rippy UI: http://192.168.178.162:80
- ✅ Rippy API: http://192.168.178.162:8000
- ✅ Theme Context ausgelagert (App.tsx → ThemeContext.tsx + useDarkMode.ts)
- ✅ Config Validation mit TMDB-API-Key Pflicht
- ✅ Cache Key Centralization (cache/keys.py)
- ✅ Dark Mode mit Theme-Toggle und localStorage persistence (UI-Only)
-**Alle UI-Komponenten komplett auf Dark Mode aktualisiert:**
- `App.tsx`, `Dashboard.tsx`, `Settings.tsx`, `MetadataPreview.tsx`
- ✅ Sidebar Navigation mit Dark Mode Support
- ✅ Einstellungen-Page mit Tab-Struktur
- ✅ Doppelte Arcane-Einträge behoben (`rippy` statt `Rippy`)
- ✅ Import-Fixes (relative → absolute Imports)
- ✅ Git Sync in Arcane konfiguriert
- ✅ Commit: `d2fb281` — Complete Dark Mode Implementation
### Docker-Container
| Container | Port | Status |
|-----------|------|--------|
| rippy-api | 8000 | Healthy |
| rippy-worker | - | Running |
| rippy-ui | 80 | Running |
| rippy-postgres | 5432 | Healthy |
| rippy-redis | 6379 | Healthy |
### Features
-**Etappe 3**: SQLite-Cache, TMDB/MusicBrainz/TheTVDB Clients, Pre-Scan, Metadaten-Preview
-**Etappe 4**: Jellyfin-Formatierung (NFO-Generator, Image-Downloader)
-**Etappe 5**: JWT-Auth (15min/7T), Rate-Limiting (100/min), API-Key-Management
-**Etappe 6**: Docker read_only, tmpfs, healthchecks, minimale Images
-**Etappe 7**: API UI Modernisiert, Import-Fixes, Doppelte Einträge behoben
-**Etappe 8**: Dark Mode mit Theme-Toggle, Separation of Concerns
-**Etappe 9**: Complete Dark Mode Implementation (alle UI-Komponenten)
-**Dokumentation**: README, KONZEPT.md, ROADMAP.md, SAVEPOINT.md
### Nächste Schritte
- Job-Verlauf UI (aktuell nur leere Listen)
- TMDB API Schlüssel in Arcane Environment konfigurieren
- Proxmox LXC Template
- Ansible Playbooks
### SoC Refactoring — Abgeschlossen (Etappe 9)
-**Theme-Context**: Theme-Logik aus App.tsx ausgelagert
-**Dark Mode Utility**: useDarkMode Hook implementiert
-**Component-Struktur**: Dark Mode props von inneren Komponenten versteckt
-**Config Validation**: TMDB-API-Key ist Pflicht
-**Cache Key Centralization**: cache/keys.py erstellt
-**CD-Ripping**: abcde-Integration implementiert
### Git-Log
```
d2fb281 - fix: complete dark mode implementation with all UI components
43dfce5 - feat(ui): implement dark mode with theme toggle
rippy-ui-modern - UI Modernisiert & Import-Fixes
3d87c8c - Dokumentation aktualisiert
bdb9f8d - SAVEPOINT v1.5: Sicherheit abgeschlossen
efa642e - Etappe 6: Sicherheit
```
---
## v2.0 — Fix-Runde nach externem Code-Review (22.07.2026, Claude)
**Alle Befunde des Reviews behoben, echte Tests eingeführt, Ampel-CI aktiv.**
Gefixt:
- **Metadaten-Preview WIEDERHERGESTELLT**: Beim SoC-Refactoring hatte ein Stub-Paket
die echte prescan-Implementierung überschattet — die Preview lieferte immer
„Unknown Disc". Echte Logik liegt jetzt im Paket, tote Altmodule (cache.py,
prescan.py flach) gelöscht.
- Fortschrittsmeldung: Celery `update_state` statt Aufrufe eines nie existierenden
Tasks; `self.send_task` (erfundene API) entfernt.
- abcde-Kommando korrigiert (`-o` war doppelt → CD-Ripping war nie funktionsfähig);
Zielverzeichnis jetzt via OUTPUTDIR-Config; Kommando-Bau als testbare Funktion.
- JWT: fester Schlüssel PFLICHT (kein Zufalls-Fallback pro Prozess mehr);
Logout blacklistet wirklich; Cleanup löscht nur Abgelaufene (vorher: alles).
- main.py: crashende Endpoints repariert (fehlende Imports Path/secrets,
nicht existentes api_keys-Dict → ratelimit-Store), Audio-`year`-Bug,
Admin-Zugang aus .env statt hartkodiert.
- Ruff komplett grün (29 Funde), package-lock.json committet.
- Tests: test_auth, test_cache_keys, test_ripping_helpers (der giftige
test_health-Placebo ist raus).
## ✅ ENTSCHIEDEN (22.07. abends): Das KONZEPT gilt — MakeMKV kommt
**MakeMKV lossless (Muss-Feature) wird umgesetzt — als eigene Etappe 10 in der
ROADMAP** (Worker-Container + makemkvcon + Beta-Key, in Zed zu bauen, E2E mit
echter Disc). Bis dahin bleibt HandBrake als SICHTBARER Übergang aktiv — jede*r
weiß: aktuell wird transkodiert, nicht verlustfrei gesichert.
## Deploy-Weg seit 22.07. abends: GRÜN-GATE (vollautomatisch)
Push auf `main` → Ampel prüft → grün → CI befördert auf Branch `stable`
**Arcane-GitSync zieht `stable` und deployt**. Rot deployt NIE. `./deploy.sh`
ist nur noch der Notfall-Hebel; SSH zur VM bleibt als Fallback erlaubt.