--- id: "0092" title: "kanban: archivo automatico para cards en columnas Done con +30 dias" status: open created_at: 2026-05-14 priority: medium app: kanban --- ## Problema Las columnas Done acumulan decenas de cards completadas que ya no participan en el trabajo activo. Lastran el board, gastan render (incluso con el split memoizado por perf) y obligan a scroll horizontal hasta el infinito sin aportar valor diario. ## Solucion Archive `archived_at` por card (independiente de papelera `deleted_at`). Card archivada sale del board pero sigue en BD. Cajon "Hecho (archivo)" en el sidebar bajo Papelera con boton para sacar una card de vuelta a su columna Done. ### Migration `apps/kanban/backend/migrations/012_card_archived.sql`: ```sql ALTER TABLE cards ADD COLUMN archived_at TEXT; ``` `NULL` = card activa. ISO timestamp = card archivada. ### Backend - `Card.ArchivedAt *string` json `archived_at`. - `ListCardsWithTime` filtra `archived_at IS NULL`. - `ArchiveCard(id)`, `UnarchiveCard(id)`, `ListArchivedCards()`. - `AutoArchiveDoneOlderThan(d)`: UPDATE cards SET archived_at=now WHERE archived_at IS NULL AND deleted_at IS NULL AND column_id IN (SELECT id FROM columns WHERE is_done=1) AND id IN (SELECT card_id FROM card_column_history WHERE exited_at IS NULL AND entered_at < cutoff). - `maybeAutoArchive(db)` con throttle `archiveSweepEvery = 30m` y `archiveAfter = 30d`. Disparado lazy desde `handleGetBoard`. - Rutas: - `GET /api/archive` - `POST /api/cards/{id}/archive` - `POST /api/cards/{id}/unarchive` ### Frontend - Tipo `Card.archived_at: string | null`. - `api.listArchive()` / `api.archiveCard(id)` / `api.unarchiveCard(id)`. - `App` state `archive`, `archiveOpen`, `reloadArchive`, `handleArchiveCard`, `handleUnarchiveCard`. `reloadArchive` se llama tras login + tras archivar/desarchivar. - UI: cajon "Hecho (archivo)" bajo "Papelera" en el sidebar. Toggle similar (`Badge` con conteo, `IconChevronRight/Down`). Solo boton "Restaurar" (`IconArrowBackUp`). No hay "purgar permanentemente" desde el archivo — solo borrado via card normal en su columna. - `KanbanCard`: nuevo `Menu.Item` "Archivar" (`IconArchive` teal) condicionado a `isDone && onArchive` antes del divisor + Borrar. ### Tests - Playwright `e2e/archive.spec.ts`: archivar manual via menu de card en columna done, asserta desaparece del board, abre cajon "Hecho", des-archiva, asserta vuelve al board. - Auto-archive 30d sin test e2e (timing real no es practico). Cubierto por audit manual del flag `archiveAfter` y la query SQL. ## Criterios de aceptacion - [ ] Cards con +30 dias en columna Done se auto-archivan tras la primera lectura del board (max 30m). - [ ] Cajon "Hecho (archivo)" visible bajo Papelera. Muestra conteo. - [ ] Boton "Restaurar" devuelve la card a su columna sin reset de historial. - [ ] Menu de card en columna Done muestra "Archivar" para archivado manual. - [ ] Cards archivadas NO aparecen en `/api/board`. - [ ] E2E `archive.spec.ts` pasa. ## Rama / commits - Rama: `issue/0092-kanban-done-archive` - Merge `--no-ff` a master.