Files
kanban/app.md
T
egutierrez b599090876 chore: auto-commit (1 archivos)
- app.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:32:55 +02:00

8.5 KiB

name, lang, domain, version, description, tags, uses_functions, uses_types, framework, entry_point, dir_path, service, e2e_checks
name lang domain version description tags uses_functions uses_types framework entry_point dir_path service e2e_checks
kanban go tools 0.1.0 Kanban board con persistencia SQLite, drag-and-drop entre columnas (dnd-kit) y tracking del tiempo que cada tarjeta pasa en cada columna. Frontend Vite + React + Mantine v9 embebido en el binario Go.
service
kanban
web
dnd-kit
mantine
sqlite
time-tracking
random_hex_id_go_core
parse_date_or_default_go_core
sqlite_open_go_infra
sqlite_apply_migrations_go_infra
sqlite_column_exists_go_infra
spa_handler_go_infra
http_router_go_infra
http_serve_go_infra
http_middleware_chain_go_infra
http_cors_middleware_go_infra
http_logger_middleware_go_infra
http_json_response_go_infra
http_error_response_go_infra
http_parse_body_go_infra
http_session_cookie_middleware_go_infra
http_session_token_extract_go_infra
http_session_cookie_set_go_infra
http_session_cookie_clear_go_infra
password_hash_go_infra
password_verify_go_infra
session_create_go_infra
session_cleanup_go_infra
duration_stats_go_datascience
format_duration_ts_core
format_datetime_short_ts_core
string_hash_palette_ts_core
color_bg_ts_ui
color_border_ts_ui
color_swatch_ts_ui
fetch_json_ts_infra
claude_stream_go_core
mcp_server_stdio_go_infra
ws_upgrader_go_infra
DurationStats_go_datascience
net/http + vite + react + mantine + dnd-kit backend/main.go apps/kanban
port health_endpoint health_timeout_s systemd_unit systemd_scope restart_policy runtime pc_targets is_local_only
8095 /api/board 3 kanban.service user always systemd-user
aurgi-pc
false
id cmd timeout_s expect_exit
build_frontend cd frontend && pnpm install --frozen-lockfile && pnpm build 180 0
id cmd timeout_s expect_exit
build_backend CGO_ENABLED=1 go build -tags fts5 -o kanban . 120 0
id cmd timeout_s expect_exit
migrations_apply rm -f /tmp/kanban_e2e.db && ./kanban --port 0 --db /tmp/kanban_e2e.db --migrate-only 15 0
id cmd expect_stdout_contains
migrations_schema sqlite3 /tmp/kanban_e2e.db 'SELECT version FROM schema_migrations ORDER BY version;' 1
id cmd health timeout_s
smoke_api ./kanban --port 8195 --db /tmp/kanban_e2e.db & http://127.0.0.1:8195/api/board 10
id cmd timeout_s expect_exit
tests_go go test -tags fts5 -count=1 ./... 120 0

Arquitectura

Single-binary: backend Go con frontend Vite embebido. SQLite local con tres tablas (columns, cards, card_column_history) y endpoints REST.

./kanban --port 8095 --db kanban.db

Schema SQLite (migrations/001_init.sql010_card_messages.sql)

  • columns — id, name, position, created_at
  • cards — id, title, description, column_id (FK), position, created_at, updated_at
  • card_column_history — id, card_id (FK), column_id, entered_at, exited_at
    • Una entrada con exited_at IS NULL = posicion actual
    • Al mover una tarjeta a otra columna: cierra la entrada activa (exited_at = now) e inserta una nueva
    • El borrado de tarjeta hace CASCADE sobre el historial
  • card_messages (migration 010) — id, card_id (FK CASCADE), author_id (nullable), body, created_at. Comentarios humano-a-humano por card; distintos de card_events (sistema) y /api/chat (LLM global).

API REST

Metodo Path Cuerpo
GET /api/board — (retorna {columns, cards}, cada card incluye time_in_column_ms)
POST /api/columns {name}
PATCH /api/columns/{id} {name?, position?}
DELETE /api/columns/{id} — (cascade a cards)
POST /api/columns/reorder {ids: [...]}
POST /api/cards {column_id, title, description?}
PATCH /api/cards/{id} {title?, description?}
DELETE /api/cards/{id}
POST /api/cards/{id}/move {column_id, ordered_ids: [...]}
POST /api/cards/{id}/duplicate — (clona la card en la misma columna al final; copia titulo+" (copia)", descripcion, color, requester, assignee, tags, stickers, deadline; NO copia historial ni mensajes)
GET /api/cards/{id}/messages — (lista de comentarios humano-a-humano de la card)
POST /api/cards/{id}/messages {body} (crea comentario; author = usuario de la sesion)
DELETE /api/cards/{cid}/messages/{mid} — (solo el autor puede borrar su mensaje)
GET /api/cards/{id}/history — (timeline con duraciones por columna)
GET /api/flags — (retorna { <name>: bool } con los feature flags efectivos en esta instancia)
POST /api/auth/register {username, password, display_name?} (devuelve 403 registration_disabled si el flag registration-enabled esta en false)

Feature flags

dev/feature_flags.json (lado del repo) define los flags por instancia. Se cargan al arrancar (override con --flags <path>); fichero ausente equivale a "todos los flags en false". El endpoint GET /api/flags expone el estado actual para que el frontend oculte UI condicional (ej. el toggle de "Registrate" en LoginPage solo aparece cuando registration-enabled es true).

Flag Default Efecto cuando esta en true
registration-enabled false Permite crear cuentas nuevas via POST /api/auth/register y muestra el toggle "Registrate" en la pantalla de login.

Frontend

  • dnd-kit (@dnd-kit/core + @dnd-kit/sortable) para drag-and-drop entre y dentro de columnas (multi-container).
  • Mantine v9 + @tabler/icons-react para UI.
  • Modales con @mantine/modals (confirmacion borrado, history timeline).
  • Time-in-column live: time_in_column_ms del backend + tick local cada segundo para que el badge se actualice sin reload.
  • DnD con closestCorners + DragOverlay para feedback visual al arrastrar.
  • Auto-refresh: el board se recarga cada 30s (api.getBoard) sin interaccion del usuario; equivalente a pulsar el boton de refresco. El tick de 1s del time-in-column es independiente y no toca red.
  • Modal de card en dos columnas (CardEditPanel): izquierda mantiene CardForm (titulo, solicitante, descripcion, asignacion, tags); derecha es un Tabs con Chat (por defecto) | Enlaces | Archivos (proximamente). Tamaño del modal: 85% del viewport.
    • Chat per-card (CardChatPanel): lista de comentarios humano-a-humano persistidos en card_messages. Enter envia, Shift+Enter salto de linea. Solo el autor puede borrar su propio mensaje.
    • Enlaces (CardLinksPanel): extrae URLs (https?://...) de titulo, descripcion y cuerpo de cada mensaje del chat. Deduplica, muestra hostname + URL completa + badge de origen. Click abre en pestaña nueva (target="_blank").
  • Duplicar card: click derecho sobre la card abre el menu contextual (mismo que el boton ), donde aparece el item "Duplicar". Al pulsarlo invoca POST /api/cards/{id}/duplicate. La copia se inserta al final de la misma columna con titulo + " (copia)".
  • Sesion obligatoria para chat: POST/DELETE /api/cards/{id}/messages exige sesion activa (401 si falta). author_id siempre poblado; no hay comentarios anonimos.
  • Archivos (proximamente): blobs persistidos en SQLite (card_attachments con BLOB), no en filesystem.

Build

cd frontend && pnpm install && pnpm build
cd .. && CGO_ENABLED=1 go build -tags fts5 -o kanban .
./kanban --port 8095 --db kanban.db
# Browser: http://localhost:8095

Dev (frontend con HMR contra backend)

# Terminal 1
./kanban --port 8095 --db kanban.db

# Terminal 2
cd frontend && pnpm dev
# Browser: http://localhost:5180 (vite proxy /api → 8095)

Notas

  • Puerto por defecto 8095.
  • DB por defecto kanban.db en cwd.
  • IDs de columnas y tarjetas: 16 chars hex (8 bytes random) via random_hex_id_go_core.
  • El historial conserva la cronologia exacta — incluso despues de cerrar y reabrir el server, los tiempos vivos siguen contando desde entered_at.
  • El borrado de columna hace CASCADE: las tarjetas se borran y su historial tambien. Si se quiere preservar el historial al borrar, deberia archivarse en lugar de borrar.

Capability growth log

Una linea por bump SemVer. Bump-type segun .claude/commands/version.md:

  • major: breaking observable (CLI args, schema BBDD propia, formato wire).

  • minor: feature aditiva (nuevo panel, endpoint, opcion).

  • patch: bugfix sin cambio observable.

  • v0.1.0 (2026-05-18) — baseline.