# SAVEPOINT — Rippy ## Aktueller Stand: v3.3 — Praxis-Feedback-Runde (24.07.2026, Claude) **Zwei echte Bugs mit Beweis gefixt:** 1. **SMB-Mount „Unable to apply new capability set"**: mount.cifs hebt CAP_DAC_READ_SEARCH an — die fehlt in Dockers Default-Caps. Auf der VM reproduziert (Bounding-Set a82425fb, Bit 2 fehlt) und mit `cap_add: DAC_READ_SEARCH` bewiesen behoben (docker-compose.yml). 2. **TMDB fiel still aus**: Der Client konnte nur v4-Bearer-Tokens — der eingetragene übliche v3-Key (32 Hex) bekam still 401, Suche lieferte nur OMDb. Jetzt beide Key-Arten (ist_v4_token, mit Tests); Einstellungen → APIs hat „Verbindung prüfen" mit Live-Status je Quelle (am Cache vorbei). **Neu in v3.3:** - **4K UHD als eigener Disc-Typ** (classify ≥ 55 GiB, beide detection.py, Tests): eigene Badge-Farbe überall, Prescan-Label „4K UHD". Der UHD-Rip-Fehler „Failed to open disc" (Code 11) bekommt Klartext: Laufwerk kann UHD nicht entschlüsseln → LibreDrive-Firmware-Hinweis (BU40N-Crossflash-Faden bleibt Hardware-Aufgabe des Commanders). - **Vollautomatik** (Einstellungen → Ripping): Disc erkannt → Rip startet ohne Popup in den passenden Schnellwahl-Ordner (Serie/Film/Musik). - **Job-Verwaltung**: „Neu komprimieren" nur noch, wenn Rohdaten wirklich daliegen (can_retry); Jobs einzeln löschbar (Papierkorb) + „Erledigte aufräumen" mit Bestätigungs-Dialog — Dateien bleiben immer liegen. - **„Alle herunterladen"** im Job-Detail (gestaffelte Einzel-Downloads — bewusst kein Server-seitiges 40-GB-Zip). - **Worker zuordenbar**: WORKER_NAME-Env als stabiler Anzeigename (compose: rippy-hauptworker; Remote-Worker: frei wählbar) — fixt zugleich die Offline-Leichen nach Rebuilds; IP + Container-ID werden mit angezeigt, verwaiste Einträge sind löschbar (DELETE /workers/{name}). Online-Abgleich läuft jetzt über info.hostname. - **Disc-Karte**: „Quelle: TMDB/OMDb/MyAnimeList · xx % sicher" statt des nackten „Übereinstimmung xx %"; TMDB-Metadaten sind Deutsch (language= de-DE war schon überall dran — sie kamen nur nie an, siehe Key-Bug). - **Ripping-Tab nach Medium** gegliedert (Video / Audio-CD / Allgemein) + Klartext: alle Tonspuren & Untertitel bleiben erhalten (--all-audio/ --all-subtitles) — wichtig für Anime. - **Ordner-Verwaltung** (Ex-„Dateibrowser") ist jetzt beschriftet, erklärt und standardmäßig eingeklappt. - **Docker-Pflicht beim Worker**: ehrlich im UI beantwortet; nativer Windows-Dienst steht als Ausbaustufe in der ROADMAP (Ideen-Katalog). --- ## Vorheriger 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.