---
id: "0089"
title: "kanban: tiempo maximo por columna con borde rojo"
status: pendiente
type: feature
domain:
  - kanban
scope: multi-app
priority: media
depends: []
blocks: []
related: []
created: 2026-05-17
updated: 2026-05-17
tags: [ausente-ready]
---

## Problema

No hay forma de marcar visualmente cards que llevan demasiado tiempo en una columna. Cards estancadas se diluyen entre el resto. El campo `card.time_in_column_ms` ya existe en `/api/board`, falta el limite por columna y el borde visual.

## Solucion

### Migration (preserva datos)

`apps/kanban/backend/migrations/011_column_max_time.sql` — `ALTER TABLE columns ADD COLUMN max_time_minutes INTEGER NOT NULL DEFAULT 0`. 0 = sin limite.

### Backend

- `Column` struct: `MaxTimeMinutes int json:"max_time_minutes"`.
- `ColumnPatch` + `UpdateColumn`: soporte para el nuevo campo, clamp a >= 0.
- `handleUpdateColumn` (PATCH `/api/columns/:id`): acepta `max_time_minutes` opcional.
- `ListColumns`: incluye el nuevo campo en el SELECT.

### Frontend

- `Column` TS interface + `UpdateColumnInput`: nuevo campo.
- `KanbanColumn` menu contextual: "Tiempo maximo" via `window.prompt` (idempotente, sin nuevo modal). Muestra valor actual en la entrada del menu si > 0.
- `KanbanColumn` -> `KanbanCard`: prop nueva `columnOverdue` calculada como `!is_done && max_time_minutes > 0 && time_in_column_ms > max_time_minutes * 60_000`.
- `KanbanCard`: cuando `columnOverdue` y NO highlighted ni locked, pinta `border-color: var(--mantine-color-red-6)` + `border-width: 2` + halo rojo. data-attribute `data-column-overdue` para tests.
- Columnas con `is_done=true` nunca disparan overdue (regla del usuario).

### Tests

- Backend Go: `TestColumnMaxTimeMinutes_Defaults`, `TestColumnMaxTimeMinutes_Update` (default 0, clamp negativo, no toca otros campos).
- Frontend: testing visual del borde rojo via Playwright queda fuera de scope automatizado (requiere control de reloj o cards reales con > N min). Cubierto con verificacion manual al finalizar.

## Criterios de aceptacion

- [ ] Migration aplica sin perder datos.
- [ ] Menu contextual "Tiempo maximo" disponible en cada columna.
- [ ] Borde rojo aparece en cards `time_in_column_ms > max_time_minutes * 60s` cuando `is_done=false`.
- [ ] Columnas Done nunca muestran borde rojo aunque tengan limite configurado.
- [ ] Tests Go pasan (2).

## Rama / commits

- Rama: `issue/0089-kanban-column-max-time`
- Merge `--no-ff` a master.
