Sync-Ausbau: Löschpfad gefixt — Spec + Plan entblockt

Hermes hat den irreversiblen Löschpfad in melo_cloud.py behoben: Der
Dedup-Zweig von upload() stellt die Datei jetzt aus den hochgeladenen
Bytes wieder her, wenn registry_pfad(sid) leer ist, statt sie zu
verwerfen.

End-to-end verifiziert (eigene Testdatei, Fake-Nutzer, Testdaten danach
restlos entfernt — Registry vor und nach dem Test bei 325 Titeln):
Upload → beide Kopien da · Löschung → beide weg, Download 404 (Bug
reproduziert) · erneuter Upload → beide Kopien zurück, Download
bitgenau identisch mit dem Original.

Damit ist die letzte offene Frage der Spec (A6) beantwortet und keine
Stufe mehr blockiert. Tasks 5-7 des Plans sind entblockt; Tasks 10-12
hängen nur noch an der Produktfrage "wird Feature 2 überhaupt gebaut?"
(0 Playlisten am Server).

Nebenbefund aus dem Test, als Backlog-Notiz festgehalten: _link_user()
legt im Dedup-Zweig einen dritten Hardlink unter users/<user>/ an, den
_entferne_datei_wenn_verwaist() nicht abräumt. Server-Hygiene für
Hermes, kein Datenverlust.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcDiyJdVRqh1TtJk5JiabX
This commit is contained in:
Hermes (Server)
2026-08-27 10:31:49 +02:00
co-authored by Claude Sonnet 5
parent 2a1cf9cdc2
commit 1940e2b790
2 changed files with 116 additions and 68 deletions
@@ -94,10 +94,11 @@ Tests, SharedPreferences, Provider. **Keine neue Dependency.**
- Ponytail-Prinzip: minimale, robuste Lösungen. Drei Nutzer, ~325 Songs,
0 Favoriten und 0 Playlisten auf dem Server — nichts überbauen.
- **Reihenfolge ist bindend.** Tasks 14 (Favoriten-Fix) hängen an nichts und
kommen zuerst. Tasks 57 sind **blockiert bis Dustin A6 beantwortet hat**
(irreversibler Löschpfad). Tasks 1012 sind **blockiert bis der Server-Fix
`melo_cloud.py:505` steht** bzw. bis Dustin entscheidet, ob Feature 2
überhaupt gebaut wird.
kommen zuerst. **Tasks 57 sind seit dem 2026-08-27 ENTBLOCKT** — der
Löschpfad ist serverseitig behoben und end-to-end verifiziert (siehe Spec,
§ERLEDIGT). Tasks 1012 bleiben blockiert, aber nur noch durch die
Produktfrage „wird Feature 2 überhaupt gebaut?" (0 Playlisten am Server) —
Details bei Task 10.
---
@@ -1207,13 +1208,13 @@ git commit -m "Herz-Tipp meldet den Favoriten sofort deterministisch an die Clou
### Task 5: `ladeAusgewaehlteHoch` + `abbrechen()` im `SyncService`
> **BLOCKIERT bis Dustin A6 beantwortet hat.**
> A6 = „Ist der irreversible Löschpfad gewollt?" (Spec, §OFFENE ENTSCHEIDUNG).
> Dieser Task gibt mehr Titeln eine cloudId und vergrößert damit genau die
> Angriffsfläche des Löschpfads. Lautet die Antwort **„nein"**, gehört der
> Server-Auftrag „Datei-Wiederherstellung im Dedup-Zweig von `upload()`"
> **davor**. Lautet sie **„ja"**, darf sofort begonnen werden.
> **Nicht ohne Antwort anfangen.**
> ✅ **ENTBLOCKT seit 2026-08-27.** Die frühere Blockade lautete: dieser Task
> gibt mehr Titeln eine cloudId und vergrößert damit die Angriffsfläche des
> irreversiblen Löschpfads. Dustins Antwort auf A6 war „nein, nicht gewollt";
> Hermes hat den Fix am selben Tag eingebaut (Datei-Wiederherstellung im
> Dedup-Zweig von `upload()`), end-to-end verifiziert. Ein versehentlicher
> Löschvorgang ist jetzt durch erneutes Hochladen reparabel.
> **Darf gebaut werden.**
**Dateien:**
- Ändern: `lib/services/sync_service.dart:143-155` (Feld `_abbruchGewuenscht`)
@@ -1555,8 +1556,9 @@ git commit -m "Gezielter Upload mit Abbrechen aus dem Auswahl-Modus"
### Task 6: Auswahl-Modus-Aktion „Auf den Server laden"
> **BLOCKIERT bis Dustin A6 beantwortet hat** — dieselbe Begründung wie
> Task 5: die Aktion ist die Oberfläche zu `ladeAusgewaehlteHoch`.
> ✅ **ENTBLOCKT seit 2026-08-27** — dieselbe Begründung wie Task 5 (die
> Aktion ist die Oberfläche zu `ladeAusgewaehlteHoch`), und dieselbe
> Auflösung: Löschpfad serverseitig behoben. **Darf gebaut werden.**
**Dateien:**
- Ändern: `lib/shared/auswahl_leiste.dart:18-66` (`AuswahlLeiste` bekommt
@@ -1875,14 +1877,11 @@ git commit -m "Auswahl-Modus: Auf den Server laden (nur in Meine Musik)"
### Task 7: Einzel-Song-Offline
> **BLOCKIERT bis Dustin A6 beantwortet hat** — nur, weil die Spec Stufe 2
> (Feature 3 **und** 4) als Ganzes hinter die A6-Antwort stellt.
> **Ehrlicher Hinweis für Dustin:** Die inhaltliche Begründung der Spec
> („vergrößert die Angriffsfläche des Löschpfads, weil mehr Titel eine cloudId
> bekommen") trifft auf **Feature 4 nicht zu** — ein Download vergibt keine
> cloudId und meldet nichts zum Server. Dieser Task könnte also gefahrlos
> vorgezogen werden. Das zu entscheiden ist Dustins Sache, nicht die des
> Umsetzenden — bis dahin bleibt der Task blockiert.
> ✅ **ENTBLOCKT seit 2026-08-27** (Löschpfad serverseitig behoben). Der Task
> war ohnehin nur mitblockiert, weil die Spec Stufe 2 als Ganzes hinter die
> A6-Antwort stellte — die inhaltliche Begründung traf auf Feature 4 nie zu:
> ein Download vergibt keine cloudId und meldet nichts zum Server.
> **Darf gebaut werden.**
**Dateien:**
- Ändern: `lib/services/download_service.dart:70-111` (neue Methode
@@ -3989,11 +3988,15 @@ git push -u origin feature/sync-ausbau
## Offene Punkte, die vor bzw. während der Umsetzung an Dustin gehen
1. **A6 — irreversibler Löschpfad** (blockiert Tasks 57).
„Verschwindet eine lokale Datei, löscht der Abgleich sie am Server und aus
der Navidrome-Bibliothek; erneutes Hochladen repariert das nicht. Gewollt?"
*Nebenfrage:* Task 7 (Einzel-Song-Offline) vergibt keine cloudId und ist
von der Begründung sachlich nicht betroffen — darf er vorgezogen werden?
1. ~~**A6 — irreversibler Löschpfad**~~ ✅ **ERLEDIGT 2026-08-27.** Dustins
Antwort: nicht gewollt. Hermes hat die Datei-Wiederherstellung im
Dedup-Zweig von `upload()` eingebaut, end-to-end verifiziert (Upload →
Löschung → erneuter Upload stellt beide Kopien bitgenau wieder her).
Tasks 57 sind damit entblockt.
*Offen geblieben, aber kein Blocker:* Die App tombstoned weiterhin
großzügig (nicht eingehängte SD-Karte genügt) und die Lösch-Bremse greift
erst ab 109 von 325 Titeln — der Schaden ist jetzt nur reparabel, nicht
verhindert. Ob die App vorsichtiger werden soll, ist eine eigene Frage.
2. **Feature 2 (Playlist-Sicherung, Tasks 1012).** Bauen oder streichen?
Heute 0 Playlisten am Server. Empfehlung: vertagen.
Falls bauen: hängt der Server-Fix `melo_cloud.py:505` wirklich davor,