Let a conversation be deleted, and its thread with it (#197)
* feat: let a conversation be deleted, and its Intelligence thread with it Nothing removed a channel, so the roster only ever grew (#196). Adds DELETE /api/channels/:channelId: the channel row, its memberships, agent links, and thread mapping go through the FK cascades that already existed for them, and the deployment asks Intelligence to permanently delete the thread itself. The local delete commits first. A rejected or unreachable upstream thread delete is non-fatal and leaves the channel gone from the roster either way, with an audit row (channel.deleted) naming the thread and whether Intelligence actually forgot it - a channel gone locally with an orphaned thread is a smaller, more honest failure than one still sitting in the roster with its history silently wiped. Removal fans out over the existing channel_activity NOTIFY topic so other open tabs see it live. The sidebar row gets an options menu with a two-button confirm dialog (new alert-dialog.tsx, wrapping @base-ui/react/alert-dialog). * Keep the roster memoized, attribute the row, and stop a failed delete vanishing The confirm button was AlertDialogAction, which renders the primitive's Close: it shut the dialog the instant it was pressed, before the request it started was answered. A delete that failed then reported nothing at all, leaving the conversation in the roster with no explanation, and "Deleting…" could never appear. A plain button waits for the answer, closes on success, and shows the server's message otherwise. DELETE answers 200 with historyLeftBehind rather than a bare 204. The thread deletion is the half that can fail on its own, and 204 said the whole act succeeded whichever way it went, so a screen had no way to avoid claiming a message history was gone while it was still on the platform. The roster row lost its memo for a stated reason that does not hold: memo compares props and says nothing about a hook, and use-channel-events preserves row identity precisely so rows do not re-render. The audit row dropped the actor in single-user mode, believing audit_events.actor_user_id has a foreign key into users. It has none, and initializeDevActorUser writes that row at start-up anyway. Single-user is the mode .env.example ships switched on, so that was the default row, and it recorded that a conversation was deleted but not by whom. Also move a tab that is looking at the channel another tab just deleted, which was left on a route that no longer resolves, and cover the audit row, which nothing tested. --------- Co-authored-by: David McKay <davidmckayv@users.noreply.github.com>
C
Cristian Peralta Segura committed
983c9092c874f15f0d62dfe9cd24162e32bcdec4
Parent: 574b4cd
Committed by GitHub <noreply@github.com>
on 8/24/2026, 5:04:12 PM