#121 — "Liste verlassen" — Self-Service für Mitglieder (alle Listentypen) #124

Closed
opened 2026-08-18 13:14:17 +02:00 by lena · 2 comments
lena commented 2026-08-18 13:14:17 +02:00 (Migrated from git.butzei.de)

Story: "Liste verlassen" — Self-Service für Mitglieder (alle Listentypen)

As a Mitglied (nicht Owner) einer Liste, die ich nicht mehr brauche,
I want to die Liste selbst verlassen können,
so that ich nicht darauf angewiesen bin, dass der Owner mich entfernt oder die Liste löscht.

Background

PO-Entscheidung (2026-08-17, per Rückfrage bestätigt): Löschen ist bewusst owner-only (verifiziert in
ListActionsMenu.tsx, ShoppingListItem.tsx, MasterPackingListItem.tsx, PantryItem.tsx — die
"Delete"-Option ist überall an isOwner gebunden). Es existiert aber keine Gegenstück-Aktion für
Mitglieder, um sich selbst aus einer Liste zu entfernen — nur der Owner kann Mitglieder entfernen
(03_remove_member_from_list.md). Ein Mitglied, das eine geteilte Liste nicht mehr sehen will, hat
aktuell keine Möglichkeit dazu. Das ist die eigentliche "Löschen geht nicht bei allen"-Lücke aus Nutzersicht.

AC

  • Neue Aktion "Liste verlassen" im "⋯"-Menü, sichtbar für Nicht-Owner-Mitglieder, für alle
    Listentypen mit Sharing (Todo-Listen inkl. Priority/Project-Varianten, Einkaufslisten,
    Masterpacklisten, Vorratsschrank).
  • Bestätigungsdialog vor dem Verlassen (analog zu bestehenden Lösch-Bestätigungen).
  • Nach dem Verlassen: die eigene Mitgliedschaft (TodoListToUserEntity/Pendants) wird entfernt, die
    Liste verschwindet aus der eigenen Übersicht, Navigation weg von der Liste (analog zu
    handleDeletes navigate('/')-Verhalten).
  • Verbleibende Mitglieder/der Owner werden per WebSocket-Broadcast/Activity-Feed informiert (analog zum
    bestehenden "joined the list"-Activity-Event bei AcceptListInvitationCommandHandler — Pendant für
    "left the list").
  • Owner können die eigene Liste nicht "verlassen" (dafür existiert bereits Transfer Ownership bzw.
    Delete) — die Aktion bleibt Nicht-Ownern vorbehalten.

Out of scope

  • Änderungen am owner-only Lösch-Recht selbst.
  • Konkreter Bug bei einem einzelnen Listentyp — keiner wurde beim Code-Review gefunden (Delete ist für
    alle Listentypen konsistent implementiert); separat gemeldet wurde stattdessen ein UI-Sichtbarkeits-Bug
    beim Masterpackliste-Menü, siehe #122.
# Story: "Liste verlassen" — Self-Service für Mitglieder (alle Listentypen) **As a** Mitglied (nicht Owner) einer Liste, die ich nicht mehr brauche, **I want to** die Liste selbst verlassen können, **so that** ich nicht darauf angewiesen bin, dass der Owner mich entfernt oder die Liste löscht. ## Background PO-Entscheidung (2026-08-17, per Rückfrage bestätigt): Löschen ist bewusst owner-only (verifiziert in `ListActionsMenu.tsx`, `ShoppingListItem.tsx`, `MasterPackingListItem.tsx`, `PantryItem.tsx` — die "Delete"-Option ist überall an `isOwner` gebunden). Es existiert aber **keine** Gegenstück-Aktion für Mitglieder, um sich selbst aus einer Liste zu entfernen — nur der Owner kann Mitglieder entfernen (`03_remove_member_from_list.md`). Ein Mitglied, das eine geteilte Liste nicht mehr sehen will, hat aktuell keine Möglichkeit dazu. Das ist die eigentliche "Löschen geht nicht bei allen"-Lücke aus Nutzersicht. ## AC - Neue Aktion "Liste verlassen" im "⋯"-Menü, sichtbar für **Nicht-Owner**-Mitglieder, für alle Listentypen mit Sharing (Todo-Listen inkl. Priority/Project-Varianten, Einkaufslisten, Masterpacklisten, Vorratsschrank). - Bestätigungsdialog vor dem Verlassen (analog zu bestehenden Lösch-Bestätigungen). - Nach dem Verlassen: die eigene Mitgliedschaft (`TodoListToUserEntity`/Pendants) wird entfernt, die Liste verschwindet aus der eigenen Übersicht, Navigation weg von der Liste (analog zu `handleDelete`s `navigate('/')`-Verhalten). - Verbleibende Mitglieder/der Owner werden per WebSocket-Broadcast/Activity-Feed informiert (analog zum bestehenden "joined the list"-Activity-Event bei `AcceptListInvitationCommandHandler` — Pendant für "left the list"). - Owner können die eigene Liste nicht "verlassen" (dafür existiert bereits Transfer Ownership bzw. Delete) — die Aktion bleibt Nicht-Ownern vorbehalten. ## Out of scope - Änderungen am owner-only Lösch-Recht selbst. - Konkreter Bug bei einem einzelnen Listentyp — keiner wurde beim Code-Review gefunden (Delete ist für alle Listentypen konsistent implementiert); separat gemeldet wurde stattdessen ein UI-Sichtbarkeits-Bug beim Masterpackliste-Menü, siehe `#122`.
lena commented 2026-08-18 21:00:57 +02:00 (Migrated from git.butzei.de)

Claimed for this go-cycle (2026-08-18).

Claimed for this go-cycle (2026-08-18).
lena commented 2026-08-19 00:20:29 +02:00 (Migrated from git.butzei.de)

Closing out. Delivered: LeaveTodoListCommand/LeaveShoppingListCommand/LeaveMasterPackingListCommand
(member-access authorized, always operates on the caller's own membership, owner guard), a new
ActivityEventKind.MemberLeft, and "Leave list" UI (gated on !isOwner, confirmation dialog,
navigate-home-if-selected) across ListActionsMenu/ShoppingListItem/MasterPackingListItem. No
Pantry action - its membership is derived from the linked Shopping List (#94), so leaving that
already covers it.

Verification: full local dotnet build (0 errors) and npm build/vitest (1004 tests, 15 new)
clean. Real CI (run 311) attempt 1: all 4 E2E legs green, one unrelated pre-existing test
(shopping-list ownership) failed with a transient Npgsql DB error. Attempts 2-3: the runner
pool was under heavy, sustained contention (many concurrent pushes/reruns across two sessions
today) - 6 scattered, unrelated test failures across both attempts, every single one the
identical "Npgsql.NpgsqlException: Exception while reading from stream, IsTransient: True"
I/O-level exception, never an assertion failure, never the same test twice. Combined with
attempt 1's clean E2E run and the full local verification, treating this as infra contention
rather than chasing further reruns - will be reconfirmed naturally by the next commit's CI run.

Closing out. Delivered: LeaveTodoListCommand/LeaveShoppingListCommand/LeaveMasterPackingListCommand (member-access authorized, always operates on the caller's own membership, owner guard), a new ActivityEventKind.MemberLeft, and "Leave list" UI (gated on !isOwner, confirmation dialog, navigate-home-if-selected) across ListActionsMenu/ShoppingListItem/MasterPackingListItem. No Pantry action - its membership is derived from the linked Shopping List (#94), so leaving that already covers it. Verification: full local dotnet build (0 errors) and npm build/vitest (1004 tests, 15 new) clean. Real CI (run 311) attempt 1: all 4 E2E legs green, one unrelated pre-existing test (shopping-list ownership) failed with a transient Npgsql DB error. Attempts 2-3: the runner pool was under heavy, sustained contention (many concurrent pushes/reruns across two sessions today) - 6 scattered, unrelated test failures across both attempts, every single one the identical "Npgsql.NpgsqlException: Exception while reading from stream, IsTransient: True" I/O-level exception, never an assertion failure, never the same test twice. Combined with attempt 1's clean E2E run and the full local verification, treating this as infra contention rather than chasing further reruns - will be reconfirmed naturally by the next commit's CI run.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
robert/todo#124
No description provided.