Files
fn_registry/dev/issues/0092-kanban-done-archive.md
T
egutierrez be8a61e724 docs(issues): kanban 0089-0093 reportes diarios + perf + archive
Archivos de issue para el trabajo de kanban de las ultimas iteraciones:

- 0089: tiempo maximo por columna con borde rojo (incluye followup popover
  con seleccion de unidad min/h/d/sem/mes).
- 0090: seleccion aleatoria por columna con animacion de ruleta. Ya con
  fix de no mostrar en columnas Done.
- 0092: archivo automatico para cards en columnas Done con +30 dias.
- 0093: reporte diario al pulsar el numero del dia en el calendario.

Los issues 0088 y 0091 ya estaban registrados.
2026-05-14 17:57:44 +02:00

3.0 KiB

id, title, status, created_at, priority, app
id title status created_at priority app
0092 kanban: archivo automatico para cards en columnas Done con +30 dias open 2026-05-14 medium 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:

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.