fix(sidebar): scrub categorization on room leave (LC-79 AC #5) #133

Merged
nrupard merged 1 commit from fix/lc-79-ac5-forget-room-on-leave into main 2026-05-18 17:39:15 +02:00
Owner

Summary

Closes the last open acceptance criterion for LC-79: #5, "Leaving a room removes it from any category automatically." Phase-3 review surfaced that db::sidebar_categories::forget_room existed but had no callers; this PR wires it (plus a new bulk forget_rooms) into the three leave / kick handlers.

Behaviour

  • routes::enclave::post_leave (user leaves an enclave): resolves the enclave's rooms via list_rooms_in_enclave(can_see_all_private=false) so only rooms the user was actually a member of get scrubbed, then bulk-deletes their sidebar_category_rooms rows via the new forget_rooms helper.
  • routes::enclave::post_kick (admin kicks user from enclave): same pattern with the kicked user's id.
  • routes::enclave::post_remove_room_member (admin removes user from a single private room): single-room forget_room.

Why it matters

Without the cleanup, the assignment row in auth.db outlived the user's access to the room in chat.db. load_sidebar was already filtering inaccessible rooms out at render time, so the bug was silent while the user was out. The visible regression was re-joining: the stale row resurrected the categorization, putting the room back in the category the user had it in before they left. Now the row is dropped at leave time, so re-joining starts fresh in "All rooms".

Acceptance criteria

  • Create / rename / delete / assign via UI (PR #129 + #130).
  • Persist across devices / sessions (server-side state in auth.db).
  • Drag-and-drop within + between categories (PR #131; touch deferred).
  • Collapsed aggregate unread / mention indicator (PR #132).
  • Leaving a room removes it from any category - this PR.
  • Deleting a category leaves its rooms joined (FK CASCADE; PR #129).
  • Mobile layout renders categorization (PR #132).

Test plan

  • forget_rooms_drops_only_named_assignments (new): empty slice is no-op; named ids dropped; un-named id stays.
  • just check + just test green (10 sidebar tests pass).
  • Manual: assign room to category; leave its enclave; rejoin; verify room lands in "All rooms" not the original category.
## Summary Closes the last open acceptance criterion for [LC-79](https://niceguyit.myjetbrains.com/youtrack/issue/LC-79): #5, "Leaving a room removes it from any category automatically." Phase-3 review surfaced that `db::sidebar_categories::forget_room` existed but had no callers; this PR wires it (plus a new bulk `forget_rooms`) into the three leave / kick handlers. ## Behaviour - `routes::enclave::post_leave` (user leaves an enclave): resolves the enclave's rooms via `list_rooms_in_enclave(can_see_all_private=false)` so only rooms the user was actually a member of get scrubbed, then bulk-deletes their `sidebar_category_rooms` rows via the new `forget_rooms` helper. - `routes::enclave::post_kick` (admin kicks user from enclave): same pattern with the kicked user's id. - `routes::enclave::post_remove_room_member` (admin removes user from a single private room): single-room `forget_room`. ## Why it matters Without the cleanup, the assignment row in `auth.db` outlived the user's access to the room in `chat.db`. `load_sidebar` was already filtering inaccessible rooms out at render time, so the bug was silent while the user was out. The visible regression was re-joining: the stale row resurrected the categorization, putting the room back in the category the user had it in before they left. Now the row is dropped at leave time, so re-joining starts fresh in "All rooms". ## Acceptance criteria - [x] Create / rename / delete / assign via UI (PR #129 + #130). - [x] Persist across devices / sessions (server-side state in auth.db). - [x] Drag-and-drop within + between categories (PR #131; touch deferred). - [x] Collapsed aggregate unread / mention indicator (PR #132). - [x] Leaving a room removes it from any category - **this PR**. - [x] Deleting a category leaves its rooms joined (FK CASCADE; PR #129). - [x] Mobile layout renders categorization (PR #132). ## Test plan - [x] `forget_rooms_drops_only_named_assignments` (new): empty slice is no-op; named ids dropped; un-named id stays. - [x] `just check` + `just test` green (10 sidebar tests pass). - [ ] Manual: assign room to category; leave its enclave; rejoin; verify room lands in "All rooms" not the original category.
fix(sidebar): scrub category assignments when user leaves a room (LC-79 AC #5)
All checks were successful
Check / clippy + fmt + tests (pull_request) Successful in 53s
ce535a3a4a
LC-79's acceptance criterion #5 ("Leaving a room removes it from any category automatically") was previously not implemented: `db::sidebar_categories::forget_room` existed but had no callers. The handler-level cleanup was missing in three places:

- `routes::enclave::post_leave` (user leaves an enclave) -> resolves the enclave's rooms via `list_rooms_in_enclave(can_see_all_private=false)` so only rooms the user was actually in get touched, then bulk-deletes their `sidebar_category_rooms` entries via the new `forget_rooms`.
- `routes::enclave::post_kick` (admin kicks user from enclave) -> same pattern with the kicked user's id.
- `routes::enclave::post_remove_room_member` (admin removes user from a single private room) -> single-room `forget_room`.

`forget_rooms` is the new bulk helper. Empty slice short-circuits without SQL; otherwise it builds a parameterized `DELETE ... WHERE room_id IN (...)` statement. SQLite's variable limit (999) is well above any realistic enclave size.

Without this fix, a user's category assignments to inaccessible rooms persisted in `auth.db`. `load_sidebar` already filtered them out at render time (rooms the user can't see are dropped from `chat.db`'s sidebar query), so the bug was invisible while the user was out. The visible breakage was re-joining: the stale assignment row resurrected the categorization, putting the room back in the same category the user had it in before they left. With this fix the assignment is dropped at leave time so re-joining starts fresh in "All rooms".

LC-79 acceptance criteria status:
- [x] Create / rename / delete / assign via UI (PR #129 + #130).
- [x] Persist across devices / sessions (server-side state in auth.db).
- [x] Drag-and-drop within + between categories (PR #131; touch deferred).
- [x] Collapsed aggregate unread / mention indicator (PR #132).
- [x] Leaving a room removes it from any category - this PR.
- [x] Deleting a category leaves its rooms joined (FK CASCADE; PR #129).
- [x] Mobile layout renders categorization (PR #132 tap-target fix; sidebar slide-in inherits layout.html).

10 sidebar tests pass.
nrupard deleted branch fix/lc-79-ac5-forget-room-on-leave 2026-05-18 17:39:15 +02:00
Sign in to join this conversation.
No reviewers
No labels
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
psa-systems/lets-chat!133
No description provided.