--- id: "0109m" title: "issues_api service: HTTP backend para issues+flows (skill_tree, kanban, dashboards)" status: pendiente type: feature domain: - meta - apps-infra scope: app-scoped priority: media depends: [] blocks: - "0109h2" related: - "0109" - "0106" created: 2026-05-18 updated: 2026-05-18 tags: - service - go - http - issues - flows - api --- # 0109m — issues_api service ## Por que `skill_tree.exe` corre en Windows nativo. Necesita leer `dev/issues/*.md` + `dev/flows/*.md` que viven en WSL `~/fn_registry/`. Opciones: | Solucion | Pro | Contra | |---|---|---| | UNC `\\wsl.localhost\Ubuntu\home\lucas\fn_registry` | Cero infra extra | Hardcodea distro/user. No funciona si WSL caido. | | Service HTTP (este issue) | Robusto, reusable por otras apps (kanban, web dashboard) | Mas piezas que mantener | | Embeber YAML parser + nested fields | Self-contained | Mucha logica duplicada | Fix UNC ya esta hecho (0109l). Pero el patron canonico del registry son services (services_api, sqlite_api, registry_api). Este issue formaliza `issues_api`. ## Spec Service Go HTTP en puerto **8486**. Patron identico a `services_api` (issue 0106). ### Endpoints - `GET /api/health` → `{"status":"ok"}` - `GET /api/issues` → array JSON con TODOS los issues (open + completed) - `GET /api/issues/:id` → un issue concreto con body markdown completo - `GET /api/flows` → array JSON con todos los flows - `GET /api/flows/:id` → un flow concreto - `GET /api/stats` → counts por status/domain/type (agregados para Dashboard) - `POST /api/issues` → crea nuevo issue (escribe `.md`). Body: `{id, title, type, domain, depends, body, dod}`. Devuelve `{path}`. - `POST /api/flows` → crea nuevo flow. Mismo shape adaptado a frontmatter de flows. ### Schema JSON issue ```json { "id": "0109", "title": "...", "status": "pendiente", "status_eff": "pendiente_unlocked", "type": "epic", "domain": ["meta", "cpp-stack"], "priority": "media", "depends": [], "blocks": [], "related": ["0085"], "tags": ["skill-tree"], "created": "2026-05-17", "updated": "2026-05-18", "file_path": "dev/issues/0109-skill-tree-app-roadmap.md", "body_md": "(opcional, solo en /api/issues/:id)", "dod": [{"text":"App existe","done":true}, ...] } ``` ### Implementacion ```go // apps/issues_api/main.go package main import ( "encoding/json" "net/http" "log" "os" // reusa funciones del registry: // - extract_frontmatter (Go port; existe extract_frontmatter_py_core, pero // en C++ existe parse_md_frontmatter_cpp_core — necesitamos Go port o // reusar yaml.v3 directo aqui). ) func main() { root := os.Getenv("FN_REGISTRY_ROOT") if root == "" { log.Fatal("FN_REGISTRY_ROOT not set") } mux := http.NewServeMux() mux.HandleFunc("/api/health", health) mux.HandleFunc("/api/issues", listIssues(root)) mux.HandleFunc("/api/issues/", showIssue(root)) mux.HandleFunc("/api/flows", listFlows(root)) mux.HandleFunc("/api/flows/", showFlow(root)) mux.HandleFunc("/api/stats", stats(root)) log.Fatal(http.ListenAndServe(":8486", mux)) } ``` Frontmatter: existe `extract_frontmatter_py_core` (Python). Hace falta: - **Opcion A**: crear `parse_md_frontmatter_go_core` (port del C++). Reusable por otros services Go. - **Opcion B**: usar `gopkg.in/yaml.v3` directo dentro de `issues_api`. Recomiendo **A** — Go port reusable. Pattern: header `parse_md_frontmatter.go` en `functions/core/`. ### Frontmatter service: block en app.md ```yaml service: port: 8486 health_endpoint: /api/health health_timeout_s: 3 systemd_unit: issues_api.service systemd_scope: user restart_policy: always runtime: systemd-user pc_targets: - aurgi-pc - home-wsl is_local_only: false ``` ### Skill_tree consume Cambio en `skill_tree/main.cpp`: - Si `discover_registry_root()` falla, intentar HTTP `http://localhost:8486/api/issues`. - Si responde 200 → parsear JSON y poblar `g_scan.nodes`. - Fallback a UNC + file scan si no. Cliente HTTP en C++: - Linux: `libcurl` (ya disponible) o `popen("curl ...")`. - Windows: WinHTTP nativo o curl.exe (Windows 10+ trae curl). - Mas simple: spawn `curl.exe -s http://...` y parsear stdout (nlohmann json — habria que vendor). ## Sub-issues - **0109m1** — crear `parse_md_frontmatter_go_core` port del C++ (mismas semanticas, mismos tests). - **0109m2** — scaffolder `issues_api` app + service block + systemd unit. - **0109m3** — implementar endpoints GET (list, show, stats). - **0109m4** — implementar POST issues + POST flows (escribir .md valido). - **0109m5** — cliente HTTP en skill_tree + fallback chain (env > walk > UNC > HTTP). ## Beneficios cross-app Una vez issues_api existe, reutilizan: - `kanban` (issue 0058 sync) podria leer/sync issues. - Frontend web dashboard ya tendria backend. - CI/automation puede crear issues via POST en lugar de editar .md a mano. - `services_monitor` mostrara `issues_api` como service mas (auto via `tag: service`). ## DoD - [ ] `apps/issues_api/` scaffoldada via `/cpp-app` ?? no — Go service via `/app`. - [ ] Endpoints listed devuelven JSON valido. - [ ] systemd unit instalado (`issues_api.service`). - [ ] Visible en `services_monitor` como service activo. - [ ] skill_tree consume HTTP cuando esta disponible, cae a UNC/file si no. - [ ] Tests Go basicos (list, show, post).