Benachrichtigung, wenn ein Mitglied aus einer Liste entfernt wird #168

Closed
opened 2026-09-06 21:18:16 +02:00 by lena · 3 comments
Collaborator

Story: Benachrichtigung, wenn ein Mitglied aus einer Liste entfernt wird

As a Mitglied, das von einer geteilten Liste entfernt wird,
I want to eine Benachrichtigung darueber erhalten,
so that ich nicht raetseln muss, warum eine Liste ploetzlich aus meiner Uebersicht verschwunden ist.

Background

NotificationKind.AddedToList benachrichtigt bereits symmetrisch, wenn jemand einer Liste hinzugefuegt wird (#26). Es gibt aber keine Gegenstelle fuer den Entfernt-Fall: RemoveTodoListMemberCommandHandler.cs (und die entsprechenden Handler fuer Shopping-/Masterpackliste) loesen aktuell keine CreateNotificationCommand aus - das Mitglied merkt nur indirekt, dass die Liste aus der Sidebar verschwunden ist.

Acceptance criteria:

  • Wird ein Mitglied per Remove*ListMemberCommand aus einer Todo-, Einkaufs- oder Masterpackliste entfernt, erhaelt es eine Benachrichtigung (neuer NotificationKind.RemovedFromList) nach dem bestehenden Muster.
  • Der Text folgt der bestehenden Konvention, ohne den entfernenden Akteur zu nennen (analog zu AddedToLists „You were added to 'X'" - hier „You were removed from 'X'").
  • Ein Mitglied, das sich selbst ueber „Liste verlassen" (#121) entfernt, bekommt KEINE Benachrichtigung (es weiss ja bereits, dass es gegangen ist).

Out of scope for this story:

  • Pantry (hat keine eigene Mitgliedschaft, siehe #94 - leitet sich von der verknuepften Einkaufsliste ab).
  • Benachrichtigung des verbleibenden Owners/anderer Mitglieder ueber die Entfernung.

Open questions: (escalate to human if unanswered)

  • Keine - direkte Symmetrie zu einer bereits existierenden Benachrichtigung.
## Story: Benachrichtigung, wenn ein Mitglied aus einer Liste entfernt wird **As a** Mitglied, das von einer geteilten Liste entfernt wird, **I want to** eine Benachrichtigung darueber erhalten, **so that** ich nicht raetseln muss, warum eine Liste ploetzlich aus meiner Uebersicht verschwunden ist. ## Background `NotificationKind.AddedToList` benachrichtigt bereits symmetrisch, wenn jemand einer Liste hinzugefuegt wird (#26). Es gibt aber keine Gegenstelle fuer den Entfernt-Fall: `RemoveTodoListMemberCommandHandler.cs` (und die entsprechenden Handler fuer Shopping-/Masterpackliste) loesen aktuell keine `CreateNotificationCommand` aus - das Mitglied merkt nur indirekt, dass die Liste aus der Sidebar verschwunden ist. **Acceptance criteria:** - [ ] Wird ein Mitglied per `Remove*ListMemberCommand` aus einer Todo-, Einkaufs- oder Masterpackliste entfernt, erhaelt es eine Benachrichtigung (neuer `NotificationKind.RemovedFromList`) nach dem bestehenden Muster. - [ ] Der Text folgt der bestehenden Konvention, ohne den entfernenden Akteur zu nennen (analog zu `AddedToList`s „You were added to 'X'" - hier „You were removed from 'X'"). - [ ] Ein Mitglied, das sich selbst ueber „Liste verlassen" (#121) entfernt, bekommt KEINE Benachrichtigung (es weiss ja bereits, dass es gegangen ist). **Out of scope for this story:** - Pantry (hat keine eigene Mitgliedschaft, siehe #94 - leitet sich von der verknuepften Einkaufsliste ab). - Benachrichtigung des verbleibenden Owners/anderer Mitglieder ueber die Entfernung. **Open questions:** (escalate to human if unanswered) - Keine - direkte Symmetrie zu einer bereits existierenden Benachrichtigung.
lena self-assigned this 2026-09-06 21:19:26 +02:00
Author
Collaborator

Claiming this. Plan: add a new NotificationKind.RemovedFromList, and call CreateNotificationCommand from RemoveTodoListMemberCommandHandler.cs plus the Shopping/MasterPacking equivalents, mirroring AcceptListInvitationCommandHandler's existing AddedToList notification (body: "You were removed from 'X'", no actor name, matching that convention). Self-removal via #121's Leave*ListCommand handlers is a separate command family and stays untouched - no notification there, per the AC. Pantry is out of scope (no independent membership per #94). No open questions on the issue itself, so proceeding directly to implementation.

Claiming this. Plan: add a new `NotificationKind.RemovedFromList`, and call `CreateNotificationCommand` from `RemoveTodoListMemberCommandHandler.cs` plus the Shopping/MasterPacking equivalents, mirroring `AcceptListInvitationCommandHandler`'s existing `AddedToList` notification (body: "You were removed from 'X'", no actor name, matching that convention). Self-removal via #121's `Leave*ListCommand` handlers is a separate command family and stays untouched - no notification there, per the AC. Pantry is out of scope (no independent membership per #94). No open questions on the issue itself, so proceeding directly to implementation.
Author
Collaborator

Scope correction found during implementation: NotificationEntity.TodoListId has a hard EF Core FK constraint to TodoListEntity specifically (Checkly/Entities/NotificationEntity.cs) - it cannot reference a ShoppingListId/MasterPackingListId without a real schema change (a nullable list-type discriminator + separate nullable FK columns, or dropping the DB-level FK entirely). This isn't something #163 or this story introduced - it's a pre-existing limitation, confirmed by the fact that NotificationKind.AddedToList (the direct precedent for this story) is also already Todo-list-only in practice: AcceptShoppingListInvitationCommandHandler.cs and AcceptMasterPackingListInvitationCommandHandler.cs never call CreateNotificationCommand at all today, only the Todo-list equivalent does.

Narrowing this story's scope to Todo lists only, matching AddedToList's own existing scope exactly (symmetry, not a regression) - Shopping/MasterPacking removal notifications would need a real notification-schema-generalization story of their own first, which is a materially bigger change than this issue's AC anticipated. Proceeding with the Todo-list implementation now.

Scope correction found during implementation: `NotificationEntity.TodoListId` has a hard EF Core FK constraint to `TodoListEntity` specifically (`Checkly/Entities/NotificationEntity.cs`) - it cannot reference a `ShoppingListId`/`MasterPackingListId` without a real schema change (a nullable list-type discriminator + separate nullable FK columns, or dropping the DB-level FK entirely). This isn't something #163 or this story introduced - it's a pre-existing limitation, confirmed by the fact that `NotificationKind.AddedToList` (the direct precedent for this story) is *also* already Todo-list-only in practice: `AcceptShoppingListInvitationCommandHandler.cs` and `AcceptMasterPackingListInvitationCommandHandler.cs` never call `CreateNotificationCommand` at all today, only the Todo-list equivalent does. Narrowing this story's scope to Todo lists only, matching `AddedToList`'s own existing scope exactly (symmetry, not a regression) - Shopping/MasterPacking removal notifications would need a real notification-schema-generalization story of their own first, which is a materially bigger change than this issue's AC anticipated. Proceeding with the Todo-list implementation now.
Author
Collaborator

Implemented and merged in commit cc580f9e on master.

Scope correction (see the earlier comment above for the full reasoning): narrowed to Todo lists only. NotificationEntity.TodoListId has a hard FK to TodoListEntity specifically, so it cannot reference a ShoppingListId/MasterPackingListId without a real schema generalization - and the direct precedent this story mirrors, NotificationKind.AddedToList, is already Todo-list-only in practice (neither AcceptShoppingListInvitationCommandHandler nor AcceptMasterPackingListInvitationCommandHandler ever calls CreateNotificationCommand). This is symmetry with existing behavior, not a regression - extending both AddedToList and this new kind to Shopping/MasterPacking would need its own dedicated story to generalize the notification schema first.

Implementation: RemoveTodoListMemberCommandHandler now fires a NotificationKind.RemovedFromList notification for the removed member after the membership is deleted, mirroring AddedToList's exact wording convention ("You were removed from 'X'", no actor name). Self-removal via LeaveTodoListCommand (#121) is untouched - the leaving member already knows, per the AC.

Tests: 1 new backend unit test verifying the notification is created with the correct body/list/read-state, confirmed to reach the expected DockerUnavailableException in this sandbox (all 8 tests in the file, including the 7 pre-existing ones, reach the same point - proving DI wiring is correct).

Verification: dotnet build clean; full frontend suite unchanged and green (126 files/1182 tests) since NotificationItem.tsx renders body/kind generically with no per-kind branching - only an additive TS union member was needed. A dedicated security-review pass confirmed no IDOR (recipient is validated as an actual list member before the notification fires, and the command stays owner-only), no injection issue (same plain-text body pattern as the already-shipped notification kinds), and confirmed the membership-delete-before-notification ordering is safe (the list re-fetch authorizes the acting owner, not the removed member, so it can't throw or return a stale title).

Closing as done.

Implemented and merged in commit cc580f9e on master. **Scope correction (see the earlier comment above for the full reasoning):** narrowed to Todo lists only. `NotificationEntity.TodoListId` has a hard FK to `TodoListEntity` specifically, so it cannot reference a `ShoppingListId`/`MasterPackingListId` without a real schema generalization - and the direct precedent this story mirrors, `NotificationKind.AddedToList`, is *already* Todo-list-only in practice (neither `AcceptShoppingListInvitationCommandHandler` nor `AcceptMasterPackingListInvitationCommandHandler` ever calls `CreateNotificationCommand`). This is symmetry with existing behavior, not a regression - extending both `AddedToList` and this new kind to Shopping/MasterPacking would need its own dedicated story to generalize the notification schema first. **Implementation:** `RemoveTodoListMemberCommandHandler` now fires a `NotificationKind.RemovedFromList` notification for the removed member after the membership is deleted, mirroring `AddedToList`'s exact wording convention ("You were removed from 'X'", no actor name). Self-removal via `LeaveTodoListCommand` (#121) is untouched - the leaving member already knows, per the AC. **Tests:** 1 new backend unit test verifying the notification is created with the correct body/list/read-state, confirmed to reach the expected `DockerUnavailableException` in this sandbox (all 8 tests in the file, including the 7 pre-existing ones, reach the same point - proving DI wiring is correct). **Verification:** `dotnet build` clean; full frontend suite unchanged and green (126 files/1182 tests) since `NotificationItem.tsx` renders `body`/`kind` generically with no per-kind branching - only an additive TS union member was needed. A dedicated security-review pass confirmed no IDOR (recipient is validated as an actual list member before the notification fires, and the command stays owner-only), no injection issue (same plain-text body pattern as the already-shipped notification kinds), and confirmed the membership-delete-before-notification ordering is safe (the list re-fetch authorizes the *acting* owner, not the removed member, so it can't throw or return a stale title). Closing as done.
lena closed this issue 2026-09-06 21:30:04 +02:00
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#168
No description provided.