Skip to content

feat(chats): archive chats instead of hard-deleting them#22406

Merged
kylecarbs merged 5 commits intomainfrom
archive-chats-soft-delete
Feb 27, 2026
Merged

feat(chats): archive chats instead of hard-deleting them#22406
kylecarbs merged 5 commits intomainfrom
archive-chats-soft-delete

Conversation

@kylecarbs
Copy link
Copy Markdown
Member

Summary

The UI has always labeled the action as "Archive agent" but the backend was performing a hard DELETE, permanently destroying chats and all their messages.

This change replaces the hard delete with a soft archive, consistent with the pattern used by template versions.

Changes

Database

  • Migration 000423: Add archived boolean DEFAULT false NOT NULL column to chats table
  • Replace DeleteChatByID query with ArchiveChatByID (UPDATE SET archived = true)
  • Add UnarchiveChatByID query (UPDATE SET archived = false)
  • Filter archived chats from GetChatsByOwnerID (WHERE archived = false)

API

  • Remove DELETE /api/experimental/chats/{chat}
  • Add POST /api/experimental/chats/{chat}/archive — archives a chat and all its descendants
  • Add POST /api/experimental/chats/{chat}/unarchive — unarchives a single chat (API only, no UI yet)

Backend

  • archiveChatTree() recursively archives child chats (replaces deleteChatTree() which hard-deleted)
  • Chat daemon's ArchiveChat() archives the full chat tree in a transaction
  • Authorization uses ActionUpdate instead of ActionDelete

SDK

  • Replace DeleteChat() with ArchiveChat() and UnarchiveChat()
  • Add Archived field to Chat struct

Frontend

  • archiveChat API call uses POST .../archive instead of DELETE
  • No UI changes — the "Archive agent" button now actually archives instead of deleting

Design Decision

This follows the template version archive pattern (Pattern B in the codebase):

  • archived boolean column (not deleted boolean)
  • Dedicated POST .../archive and POST .../unarchive routes (not repurposing DELETE)
  • Reversible — users can unarchive via the API (UI for this will come later)

@coder-tasks
Copy link
Copy Markdown
Contributor

coder-tasks bot commented Feb 27, 2026

Documentation Check

Updates Needed

  • coderd/chats.go — The archiveChat handler had an incorrect swagger annotation (@Router /chats/{chat} [post]) that was fixed in commit 3c5f77d. The generated docs/reference/api/chats.md now correctly documents the endpoint as POST /chats/{chat}/archive.

Automated review via Coder Tasks

The UI has always labeled the action as 'Archive agent' but the backend
was performing a hard DELETE, permanently destroying chats and messages.

This change replaces the hard delete with a soft archive:

- Add 'archived' boolean column to chats table (migration 000423)
- Replace DeleteChatByID with ArchiveChatByID/UnarchiveChatByID queries
- Filter archived chats from GetChatsByOwnerID (archived = false)
- Replace DELETE /chats/{chat} with POST /chats/{chat}/archive
- Add POST /chats/{chat}/unarchive endpoint (API only, no UI yet)
- Update chatd daemon to archive chat trees instead of deleting them
- Update SDK with ArchiveChat/UnarchiveChat client methods
- Frontend calls POST .../archive instead of DELETE

This follows the same pattern used by template versions, which also use
an archived boolean column with dedicated /archive and /unarchive routes.
@kylecarbs kylecarbs force-pushed the archive-chats-soft-delete branch from db5c3fe to 5069ea9 Compare February 27, 2026 21:34
@kylecarbs kylecarbs merged commit 1208344 into main Feb 27, 2026
30 checks passed
@kylecarbs kylecarbs deleted the archive-chats-soft-delete branch February 27, 2026 21:46
@github-actions github-actions bot locked and limited conversation to collaborators Feb 27, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant