- app.md - backend/handlers.go - backend/main.go - frontend/src/App.tsx - frontend/src/api.ts - frontend/vite.config.ts - backend/mcp_http.go - backend/mcp_tokens.go - backend/mcp_tokens_handlers.go - backend/migrations/016_mcp_tokens.sql - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
9.0 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.4.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. |
|
|
|
net/http + vite + react + mantine + dnd-kit | backend/main.go | apps/kanban |
|
|
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.sql … 010_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
- Una entrada con
- 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-reactpara UI. - Modales con
@mantine/modals(confirmacion borrado, history timeline). - Time-in-column live:
time_in_column_msdel backend + tick local cada segundo para que el badge se actualice sin reload. - DnD con
closestCorners+DragOverlaypara 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 mantieneCardForm(titulo, solicitante, descripcion, asignacion, tags); derecha es unTabsconChat(por defecto) |Enlaces|Archivos(proximamente). Tamaño del modal: 85% del viewport.- Chat per-card (
CardChatPanel): lista de comentarios humano-a-humano persistidos encard_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").
- Chat per-card (
- Duplicar card: click derecho sobre la card abre el menu contextual (mismo que el boton
⋮), donde aparece el item "Duplicar". Al pulsarlo invocaPOST /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}/messagesexige sesion activa (401 si falta).author_idsiempre poblado; no hay comentarios anonimos. - Archivos (proximamente): blobs persistidos en SQLite (
card_attachmentsconBLOB), 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.dben 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.
-
v0.3.1 (2026-05-21) — patch: debounce board.invalidated (300ms trailing) + autoClose 4s en toasts de notification.created. Fix de blow-up de memoria en navegador por ráfagas de SSE.
-
v0.4.0 (2026-05-22) — minor: endpoint MCP Streamable HTTP
/mcpcon per-user bearer tokens (tablamcp_tokens, migration 016). Modal "MCP tokens" en avatar menu para generar/listar/revocar. Vite proxy enruta/mcpa WSL. Usa nueva funcionmcp_server_http_go_infra. Doc endocs/MCP.md.