From 30325dc1b606ae7bd395b9242ca072420e8f803e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesko=20Ansch=C3=BCtz?= Date: Thu, 26 Mar 2026 22:18:19 +0100 Subject: [PATCH] =?UTF-8?q?docs:=20Design-Spec=20f=C3=BCr=20Reorder-Validi?= =?UTF-8?q?erung=20im=20PlaylistStore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- .../2026-03-26-reorder-validation-design.md | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 docs/superpowers/specs/2026-03-26-reorder-validation-design.md diff --git a/docs/superpowers/specs/2026-03-26-reorder-validation-design.md b/docs/superpowers/specs/2026-03-26-reorder-validation-design.md new file mode 100644 index 0000000..d85e1db --- /dev/null +++ b/docs/superpowers/specs/2026-03-26-reorder-validation-design.md @@ -0,0 +1,50 @@ +# Design: Reorder-Validierung im PlaylistStore + +**Datum:** 2026-03-26 +**Scope:** `store.go` (Reorder), `manage/ui.go` (HandleReorderUI), `manage/playlist.go` (HandleReorder) + +## Problem + +`PlaylistStore.Reorder` akzeptiert beliebige ID-Listen ohne Prüfung: + +- Unbekannte oder fremde IDs werden stillschweigend ignoriert (0 Rows affected, kein Fehler) +- Eine Teilliste korrumpiert die Sortierung: nicht geschickte Items behalten ihren alten `order_index` +- Beide Fehlerszenarien sind für den Client unsichtbar — der Response ist trotzdem 204 + +## Lösung + +### 1. Sentinel-Fehler in `store.go` + +```go +var ErrReorderMismatch = errors.New("reorder: item list does not match playlist") +``` + +### 2. Vollständigkeitsprüfung in `Reorder` + +Vor den Updates: `COUNT(*)` der Items in der Playlist innerhalb der Transaktion. +Wenn `len(itemIDs) != count` → `ErrReorderMismatch` zurückgeben. + +### 3. RowsAffected-Check pro Update + +Nach jedem `tx.Exec`: wenn `RowsAffected() != 1` → `ErrReorderMismatch` zurückgeben. +(Fängt fremde IDs, die die `AND playlist_id=`-Bedingung passiert hätten.) + +### 4. Handler-Anpassung (400 statt 500) + +Beide Handler prüfen `errors.Is(err, store.ErrReorderMismatch)`: +- Match → `http.StatusBadRequest` (400) +- Sonst → `http.StatusInternalServerError` (500) + +## Verhalten nach Fix + +| Szenario | Vorher | Nachher | +|---|---|---| +| Vollständige, korrekte Liste | 204 ✓ | 204 ✓ | +| Teilliste | 204 (stille Korruption) | 400 → UI reloaded | +| Fremde/unbekannte ID | 204 (still ignoriert) | 400 → UI reloaded | +| DB-Fehler | 500 | 500 | + +## Nicht im Scope + +- Änderung des Drag&Drop-Frontends (schickt bereits die vollständige Liste) +- Neue Tests (werden im Implementierungsplan ergänzt falls vorhanden)