c468b24d2b
Registry (issue 0130a):
- 5 fns infra: parse_issue_md, write_issue_md, scan_issues_dir,
scan_flows_dir, watch_dir_fsnotify
- 3 tipos: Issue, Flow, FsEvent
- Tests round-trip + scan reales + watcher fsnotify (all PASS)
- Capability group 'kanban' nuevo (docs/capabilities/kanban.md)
Apps:
- apps/kanban_cpp/ (sub-repo) — frontend ImGui: board drag-drop,
flows, filters, detail con CSV editors
- apps/kanban_cpp/backend/ — Go service port 8487: REST + SSE +
fsnotify watcher, parser bidireccional MD<->SQLite cache
Issues:
- dev/issues/0130-kanban-cpp-v2.md (epic)
- 0130a parser, 0130b backend, 0130c frontend
CMakeLists.txt: add_subdirectory apps/kanban_cpp (registrado por
init_cpp_app scaffolder).
End-to-end verde: backend devuelve 189 issues + 9 flows; PATCH a
/api/issues/{id} reescribe .md (solo frontmatter, body intacto);
frontend --self-test exit 0; tests Go infra 5/5 PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
115 lines
3.4 KiB
Markdown
115 lines
3.4 KiB
Markdown
---
|
|
id: "0130b"
|
|
title: "Backend Go kanban_cpp v2: schema + handlers + watcher + SSE"
|
|
status: pendiente
|
|
type: app
|
|
domain:
|
|
- apps-infra
|
|
- dev-ux
|
|
scope: app-scoped
|
|
priority: alta
|
|
depends:
|
|
- "0130a"
|
|
blocks:
|
|
- "0130c"
|
|
related:
|
|
- "0130"
|
|
created: 2026-05-22
|
|
updated: 2026-05-22
|
|
tags: [service, kanban, go, sqlite, sse]
|
|
flow: "0130"
|
|
---
|
|
|
|
# 0130b — Backend Go kanban_cpp v2
|
|
|
|
**Status:** pendiente
|
|
|
|
## Por que
|
|
|
|
Servicio HTTP local que sirve los issues + flows del proyecto al frontend C++. Es un wrapper fino sobre las funciones del registry de 0130a + SQLite cache + watcher.
|
|
|
|
## Estructura
|
|
|
|
```
|
|
apps/kanban_cpp/backend/
|
|
app.md # tag service
|
|
go.mod
|
|
main.go # entry: flags + run
|
|
db.go # open + apply migrations + upsert helpers
|
|
handlers.go # endpoints REST
|
|
sse_hub.go # broadcaster
|
|
watcher.go # bind a watch_dir_fsnotify + re-ingesta + emit SSE
|
|
ingest.go # scan → upsert; usa 0130a
|
|
migrations/
|
|
001_init.sql
|
|
operations.db # creada en runtime
|
|
```
|
|
|
|
## Endpoints
|
|
|
|
| Verbo | Path | Notas |
|
|
|---|---|---|
|
|
| GET | `/api/health` | `{ok:true, version, count_issues, count_flows}` |
|
|
| GET | `/api/issues` | filtros: `status`, `domain`, `priority`, `tag`, `scope` |
|
|
| GET | `/api/issues/{id}` | issue + body |
|
|
| PATCH | `/api/issues/{id}` | partial update frontmatter → `write_issue_md` + re-ingesta + SSE |
|
|
| GET | `/api/flows` | filtros: `status`, `kind` |
|
|
| GET | `/api/flows/{id}` | flow + body |
|
|
| GET | `/api/meta` | enums leidos de `dev/TAXONOMY.md` |
|
|
| GET | `/api/sse` | stream `{type, id, path}` |
|
|
|
|
CORS abierto local (`*`). Logger middleware.
|
|
|
|
## Schema (migrations/001_init.sql)
|
|
|
|
```sql
|
|
CREATE TABLE IF NOT EXISTS issues (
|
|
id TEXT PRIMARY KEY,
|
|
title TEXT NOT NULL,
|
|
status TEXT NOT NULL,
|
|
type TEXT,
|
|
scope TEXT,
|
|
priority TEXT,
|
|
domain_json TEXT NOT NULL DEFAULT '[]',
|
|
tags_json TEXT NOT NULL DEFAULT '[]',
|
|
depends_json TEXT NOT NULL DEFAULT '[]',
|
|
blocks_json TEXT NOT NULL DEFAULT '[]',
|
|
related_json TEXT NOT NULL DEFAULT '[]',
|
|
flow_id TEXT,
|
|
body TEXT NOT NULL DEFAULT '',
|
|
file_path TEXT NOT NULL,
|
|
mtime_ns INTEGER NOT NULL,
|
|
created_at TEXT,
|
|
updated_at TEXT,
|
|
completed INTEGER NOT NULL DEFAULT 0 -- 1 si vive en completed/
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_issues_status ON issues(status);
|
|
CREATE INDEX IF NOT EXISTS idx_issues_priority ON issues(priority);
|
|
|
|
CREATE TABLE IF NOT EXISTS flows (
|
|
id TEXT PRIMARY KEY,
|
|
title TEXT NOT NULL,
|
|
status TEXT,
|
|
kind TEXT,
|
|
tags_json TEXT NOT NULL DEFAULT '[]',
|
|
body TEXT NOT NULL DEFAULT '',
|
|
file_path TEXT NOT NULL,
|
|
mtime_ns INTEGER NOT NULL
|
|
);
|
|
```
|
|
|
|
## DoD
|
|
|
|
- `curl http://localhost:8487/api/health` devuelve 200 + counts.
|
|
- `curl http://localhost:8487/api/issues | jq 'length' >= 90`.
|
|
- `curl -X PATCH /api/issues/0130 -d '{"status":"in-progress"}'` reescribe `dev/issues/0130-*.md` (status updated, body intacto).
|
|
- Despues del PATCH, suscriptor SSE recibe evento `{type:"updated", id:"0130"}`.
|
|
- Tras `mv dev/issues/0130-*.md dev/issues/completed/`, watcher actualiza fila (`completed=1`).
|
|
- `go test ./...` verde.
|
|
|
|
## Anti-scope
|
|
|
|
- No expone proposals ni capabilities (eso es MCP registry).
|
|
- No autentica (local-only por ahora).
|
|
- No persiste estado UI (eso lo hace el frontend).
|