diff --git a/dev/issues/0054-deploy-server-registry-first-refactor.md b/dev/issues/0054-deploy-server-registry-first-refactor.md new file mode 100644 index 00000000..cd48fc3a --- /dev/null +++ b/dev/issues/0054-deploy-server-registry-first-refactor.md @@ -0,0 +1,87 @@ +# 0054 — deploy_server: refactor registry-first (SSH/systemd/rsync/health/docker-compose) + +## APP Metadata + +| Campo | Valor | +|-------|-------| +| **ID** | 0054 | +| **Estado** | pendiente | +| **Prioridad** | alta | +| **Tipo** | refactor — `apps/deploy_server/` | + +## Dependencias + +- 13 funciones del registry ya existentes y testeadas: + - `ssh_check_go_infra`, `ssh_exec_go_infra`, `ssh_upload_go_infra`, `ssh_config_read_go_infra`, `ssh_config_find_go_infra` + - `systemd_install_go_infra`, `systemd_restart_go_infra`, `systemd_status_go_infra`, `systemd_generate_unit_go_infra` (pure) + - `rsync_deploy_bash_infra`, `docker_compose_remote_deploy_bash_infra` + - `health_check_http_go_infra` + - `vps_setup_app_go_infra` +- Pipelines `deploy_app_remote_go_infra` y `setup_vps_app_go_infra` orquestan varias. + +## Contexto + +`fn doctor uses-functions` (2026-05-07) detecto que `apps/deploy_server/` no importa NADA del registry. Toda la logica SSH/systemd/rsync/health/docker-compose esta reimplementada inline en `deployer.go` (`d.sshCheck`, `d.sshExec`, `d.rsyncDeploy`, `d.healthCheck`, `d.generateUnit`, `d.installUnit`, `deployDockerCompose`). + +Esta es la violacion mas grande de la regla `registry-first.md` actualmente activa. La app fue construida antes de que existieran las funciones del registry equivalentes; las funciones se crearon despues pero deploy_server quedo sin migrar. + +Tras sincronizar `app.md` (2026-05-07) las 13 funciones se quitaron del frontmatter — ahora refleja la realidad pero la deuda real (registry-first compliance) sigue. + +## Objetivo + +Reemplazar implementaciones inline de `deployer.go` por llamadas a las funciones del registry. Resultado: + +1. `apps/deploy_server/*.go` importa `fn-registry/functions/infra` y `fn-registry/functions/cybersecurity` segun corresponda. +2. `app.md` declara las 13 funciones en `uses_functions`. +3. Los tests existentes siguen pasando. +4. `fn doctor uses-functions` reporta `deploy_server_go_infra` sin drift. + +## Arquitectura + +### Archivos afectados + +- `apps/deploy_server/deployer.go` — ELIMINAR metodos `sshCheck`, `sshExec`, `sshUpload`, `rsyncDeploy`, `healthCheck`, `generateUnit`, `installUnit` y reemplazar por llamadas a funciones del registry. +- `apps/deploy_server/docker_compose.go` — sustituir `deployDockerCompose` por `docker_compose_remote_deploy_bash_infra`. +- `apps/deploy_server/handlers.go` (probable) — actualizar callsites. +- `apps/deploy_server/app.md` — anadir las 13 deps en `uses_functions`. +- `apps/deploy_server/go.mod` — anadir `replace fn-registry => ../..` si no esta. + +## Tareas + +### Fase 1 — preparacion +1.1 Listar callsites actuales en deployer.go (`grep -n 'd\.\(sshCheck\|sshExec\|sshUpload\|rsyncDeploy\|healthCheck\|generateUnit\|installUnit\)\|deployDockerCompose'`). +1.2 Verificar firmas de las funciones del registry vs los metodos inline. Documentar diferencias (parametros distintos, error wrapping). +1.3 Anadir `replace` directive en `go.mod` si falta. + +### Fase 2 — migracion SSH +2.1 Reemplazar `d.sshCheck` por `infra.SshCheck`. +2.2 Reemplazar `d.sshExec` por `infra.SshExec`. +2.3 Reemplazar `d.sshUpload` por `infra.SshUpload`. +2.4 Test build: `go build` en deploy_server. + +### Fase 3 — migracion systemd +3.1 Reemplazar `d.generateUnit` por `infra.SystemdGenerateUnit`. +3.2 Reemplazar `d.installUnit` por `infra.SystemdInstall`. +3.3 Reemplazar restart/status por `infra.SystemdRestart`, `infra.SystemdStatus`. + +### Fase 4 — migracion rsync + http + docker-compose +4.1 Reemplazar `d.rsyncDeploy` por shell-out a `bash/functions/infra/rsync_deploy.sh` (es bash, no Go). +4.2 Reemplazar `d.healthCheck` por `infra.HealthCheckHTTP`. +4.3 Reemplazar `deployDockerCompose` por shell-out a `bash/functions/infra/docker_compose_remote_deploy.sh`. + +### Fase 5 — tests + docs +5.1 Correr tests existentes. Si hay mocks de los metodos privados, actualizar. +5.2 Actualizar `app.md` `uses_functions` con las 13 IDs (orden alfabetico). +5.3 `fn index` y `fn doctor uses-functions` debe reportar deploy_server limpio. +5.4 Update CHANGELOG.md con la migracion. + +## Riesgos + +- Las firmas inline pueden tener parametros adicionales que las del registry no exponen. Mitigacion: si la diferencia es real, abrir proposal para extender la funcion del registry, NO duplicar inline. +- Tests con mocks de metodos privados rompen. Mitigacion: convertir a integration tests contra docker container o servidor SSH local. +- Build cross-platform: si `infra` paquete tiene CGo y deploy_server cross-compila, validar build linux/windows. + +## Decisiones de diseno + +- **No crear adapter layer**. Llamada directa a las funciones del registry. Si la firma cambia entre version, se actualiza el callsite — el costo es bajo y mantiene la regla registry-first sin ceremonia. +- Las funciones bash (`rsync_deploy`, `docker_compose_remote_deploy`) se invocan via `os/exec` con `bash `. NO portar a Go solo para "estar en el mismo lenguaje" — la version bash funciona y es la que el registry mantiene. diff --git a/dev/issues/0055-docker-tui-registry-first-refactor.md b/dev/issues/0055-docker-tui-registry-first-refactor.md new file mode 100644 index 00000000..fd6039cc --- /dev/null +++ b/dev/issues/0055-docker-tui-registry-first-refactor.md @@ -0,0 +1,87 @@ +# 0055 — docker_tui: refactor para usar funciones docker_* del registry + +## APP Metadata + +| Campo | Valor | +|-------|-------| +| **ID** | 0055 | +| **Estado** | pendiente | +| **Prioridad** | alta | +| **Tipo** | refactor — `apps/docker_tui/` | + +## Dependencias + +- 12 funciones del registry ya existentes: + - `docker_pull_image_go_infra`, `docker_list_containers_go_infra`, `docker_remove_container_go_infra` + - `docker_remove_image_go_infra`, `docker_remove_network_go_infra`, `docker_create_network_go_infra` + - `docker_stop_container_go_infra`, `docker_start_container_go_infra`, `docker_list_images_go_infra` + - `docker_inspect_container_go_infra`, `docker_run_container_go_infra`, `docker_container_logs_go_infra` +- Tipos relacionados en `functions/infra/` (Container, Image, Network). + +## Contexto + +`fn doctor uses-functions` (2026-05-07) detecto que `apps/docker_tui/` ejecuta el CLI `docker` directamente via `shell.RunWithTimeout` en `views/docker.go` (`ListContainers`, `StartContainer`, `StopContainer`...). Cero consumo del registry. + +Como en `0054`, la TUI fue construida antes de que existieran las funciones equivalentes en `functions/infra/`. Las 12 docker_* del registry parsean output JSON de docker CLI y devuelven tipos Go — exactamente lo que la TUI necesita. + +Tras sincronizar `app.md` (2026-05-07) las 12 funciones se quitaron — ahora refleja la realidad, pero la deuda registry-first persiste. + +## Objetivo + +Reemplazar `views/docker.go` (y similares) por llamadas a `functions/infra/docker_*.go`. Resultado: + +1. `apps/docker_tui/views/docker.go` importa `fn-registry/functions/infra`. +2. `app.md` declara las 12 docker_* funciones en `uses_functions`. +3. TUI sigue funcionando identica (acciones lentas se mantienen lentas, no es regresion). +4. `fn doctor uses-functions` reporta docker_tui limpio. + +## Arquitectura + +### Archivos afectados + +- `apps/docker_tui/views/docker.go` — sustituir todas las llamadas inline a docker CLI por funciones del registry. +- `apps/docker_tui/app.md` — anadir 12 deps en `uses_functions`. +- Probable: `apps/docker_tui/handlers/` o similar segun estructura. + +## Tareas + +### Fase 1 — preparacion +1.1 Listar callsites a docker CLI: `grep -rn 'shell\.Run.*docker\|exec\.Command.*"docker"' apps/docker_tui/`. +1.2 Mapear cada accion TUI (start, stop, list, logs, inspect, ...) a la funcion del registry equivalente. +1.3 Anadir `replace fn-registry => ../..` en `go.mod` si falta. + +### Fase 2 — migracion list/inspect (read-only primero) +2.1 `ListContainers` → `infra.DockerListContainers`. +2.2 `ListImages` → `infra.DockerListImages`. +2.3 `InspectContainer` → `infra.DockerInspectContainer`. +2.4 Validar que tipos retornados encajan con lo que la UI espera (`Container`, `Image`). + +### Fase 3 — migracion lifecycle (write) +3.1 `StartContainer` → `infra.DockerStartContainer`. +3.2 `StopContainer` → `infra.DockerStopContainer`. +3.3 `RemoveContainer` → `infra.DockerRemoveContainer`. +3.4 `PullImage` → `infra.DockerPullImage`. +3.5 `RemoveImage` → `infra.DockerRemoveImage`. + +### Fase 4 — migracion network/run/logs +4.1 `CreateNetwork` → `infra.DockerCreateNetwork`. +4.2 `RemoveNetwork` → `infra.DockerRemoveNetwork`. +4.3 `RunContainer` → `infra.DockerRunContainer`. +4.4 `ContainerLogs` → `infra.DockerContainerLogs`. + +### Fase 5 — tests + docs +5.1 Lanzar TUI manualmente, verificar todas las acciones funcionan (smoke test). +5.2 Actualizar `app.md` `uses_functions`. +5.3 `fn index` + `fn doctor uses-functions` limpio. +5.4 Update CHANGELOG.md. + +## Riesgos + +- Las funciones del registry parsean output JSON; si el TUI dependia de output text-mode, las firmas cambian. Mitigacion: las funciones del registry ya exponen tipos Go estructurados, mejor ergonomia. +- Acciones largas (PullImage, RunContainer con stream): verificar que las funciones del registry soportan streaming o callback. Si no, abrir proposal para extender. +- Tests existentes con mocks de docker CLI rompen. Mitigacion: usar un docker daemon real para integration tests. + +## Decisiones de diseno + +- Como en `0054`, NO crear adapter layer. Llamadas directas. +- Si una accion del TUI necesita algo que el registry no expone (ej. flags raros), abrir proposal `extend_existing_function` antes de duplicar. diff --git a/dev/issues/0056-audit-python-nested-imports.md b/dev/issues/0056-audit-python-nested-imports.md new file mode 100644 index 00000000..0c5cb428 --- /dev/null +++ b/dev/issues/0056-audit-python-nested-imports.md @@ -0,0 +1,62 @@ +# 0056 — audit_uses_functions: detectar imports Python anidados (`from pkg.subpkg import X`) + +## APP Metadata + +| Campo | Valor | +|-------|-------| +| **ID** | 0056 | +| **Estado** | pendiente | +| **Prioridad** | media | +| **Tipo** | enhancement — `functions/infra/audit_uses_functions.go` | + +## Dependencias + +- `audit_uses_functions_go_infra` ya existe. +- `fn doctor uses-functions` lo consume. + +## Contexto + +La heuristica actual de Python solo procesa `from import ` donde `` matches `python/functions/{domain}/`. NO maneja: + +1. `from . import ` — ej. `from metabase.cards import metabase_get_card`. Resultado: el import se ignora y `metabase_get_card_py_infra` se reporta como `unused_in_app_md`. +2. `import ; .(...)` — uso indirecto. + +Confirmado en sesion 2026-05-07: `apps/auto_metabase` y `apps/metabase_registry` tienen 8-44 falsos positivos por este motivo. Tras sincronizacion manual quedaron 4/12 apps con drift, todas por esta limitacion. + +## Objetivo + +Mejorar el parser Python para detectar imports anidados. Reducir falsos positivos `unused_in_app_md` a 0 en apps Python que usan paquetes anidados del registry. + +## Arquitectura + +### Archivos afectados + +- `functions/infra/audit_uses_functions.go` — bloque que parsea imports Python. +- `functions/infra/audit_uses_functions_test.go` — anadir test cases. +- `functions/infra/audit_uses_functions.md` — actualizar `notes` quitando la limitacion. + +## Tareas + +### Fase 1 — extender parser de imports Python +1.1 Aceptar regex `^from\s+(\S+)\s+import\s+(.+)` donde grupo 1 puede contener puntos. +1.2 Si grupo 1 es `` o `.` y `` matches un dominio Python del registry: para cada simbolo importado en grupo 2, buscar funcion con ese name en el dominio entero (no solo en el subpkg). +1.3 Soportar `import as ` y posterior `.(...)` — opcional, dejar como mejora futura si complica. + +### Fase 2 — test cases +2.1 `TestAuditUsesFunctions_DetectsNestedImport` — fixture con `from metabase.cards import metabase_get_card`. Verificar `metabase_get_card_py_infra` aparece en imports detectados. +2.2 `TestAuditUsesFunctions_NoFalsePositiveOnNested` — fixture con paquete + subpaquete del registry, ningun unused detectado. +2.3 `TestAuditUsesFunctions_StarImport` — `from import *` debe ignorarse o tratarse como "todo importado" (decision de diseno, documentar). + +### Fase 3 — verificacion en apps reales +3.1 Correr `fn doctor uses-functions` post-fix. `apps/auto_metabase` y `apps/metabase_registry` deben quedar sin drift o con drift residual <3 funciones. +3.2 Update CHANGELOG.md. + +## Riesgos + +- Falsos positivos invertidos: si el parser acepta cualquier import como uso, reduce el valor del audit. Mitigacion: solo aceptar imports cuyo paquete raiz mapee a un dominio del registry. +- Edge case: app importa `from numpy import X` — numpy no es del registry. El parser actual ya lo ignora; mantener. + +## Decisiones de diseno + +- NO portar a AST (`ast.parse`) — overkill para este caso. Regex sobre lineas basta y mantiene la funcion auto-contenida sin spawning Python. +- `from import *` se documenta como NO soportado (tratado como vacio). Practica recomendada en el registry: nunca star imports. diff --git a/dev/issues/0057-audit-go-symbol-naming.md b/dev/issues/0057-audit-go-symbol-naming.md new file mode 100644 index 00000000..1f191793 --- /dev/null +++ b/dev/issues/0057-audit-go-symbol-naming.md @@ -0,0 +1,63 @@ +# 0057 — audit_uses_functions: mejorar deteccion de simbolos Go con abreviaturas + +## APP Metadata + +| Campo | Valor | +|-------|-------| +| **ID** | 0057 | +| **Estado** | pendiente | +| **Prioridad** | baja | +| **Tipo** | enhancement — `functions/infra/audit_uses_functions.go` | + +## Dependencias + +- `audit_uses_functions_go_infra` ya existe. + +## Contexto + +La heuristica Go convierte `name` snake_case a CamelCase para buscar el simbolo exportado en el codigo. La conversion usa `commonAbbrevs` para mapear (ej. `cdp` → `CDP`, `http` → `HTTP`). Pero falla cuando: + +1. La abreviatura no esta en la lista (ej. `cdp_get_html` → `CdpGetHTML` pero codigo usa nombre distinto). +2. El simbolo se renombra en la funcion del registry vs el name del frontmatter. + +Caso real (2026-05-07): `cdp_get_html_go_browser` fue marcado `unused_in_app_md` en `script_navegador` aunque `runner.go:126` lo invoca. Se confirmo manualmente como falso positivo. + +## Objetivo + +Reducir falsos positivos en la deteccion de simbolos Go. Dos vias: + +1. Ampliar `commonAbbrevs` con mas terminos comunes en el registry (HTML, CDP, JWT, OAuth, JSON, YAML, SQL, BQ, ID, URL, IP, TCP, TLS, SSH, S3, RBAC). +2. Caer a una segunda heuristica: si no encuentra ``, buscar el nombre real exportado leyendo el `.go` de la funcion del registry y extraer `func (`. + +## Arquitectura + +### Archivos afectados + +- `functions/infra/audit_uses_functions.go` — funcion `snakeToCamel` o equivalente, y bucle de busqueda de simbolos. +- `functions/infra/audit_uses_functions_test.go` — anadir tests. + +## Tareas + +### Fase 1 — ampliar commonAbbrevs +1.1 Listar funciones del registry con abreviaturas en su `name`: `sqlite3 registry.db "SELECT name FROM functions WHERE lang='go';"` — extraer abreviaturas comunes. +1.2 Anadir HTML, CDP, JWT, OAuth, JSON, YAML, SQL, BQ, ID, URL, IP, TCP, TLS, SSH, S3, RBAC a `commonAbbrevs`. +1.3 Test `TestSnakeToCamel_HandlesAbbreviations` con todos los nuevos. + +### Fase 2 — fallback a lectura de `.go` +2.1 Si la conversion CamelCase no encuentra simbolo, leer `.go` de la funcion del registry, extraer primer `func (` exportado. +2.2 Buscar ese nombre en el codigo de la app. +2.3 Cachear el mapping (en memoria por ejecucion) para no reabrir el mismo archivo N veces. + +### Fase 3 — verificacion +3.1 `cdp_get_html_go_browser` ya NO debe aparecer unused para `script_navegador`. +3.2 Correr audit en todas las apps Go, comparar con baseline anterior. Diff de falsos positivos eliminados. + +## Riesgos + +- Lectura de N archivos `.go` ralentiza el audit. Mitigacion: cache + leer solo si la heuristica primaria falla. +- Cambio en commonAbbrevs puede romper tests existentes que asumian la conversion antigua. Validar. + +## Decisiones de diseno + +- NO usar `go/parser` — no necesitamos AST completo, basta regex sobre `func [A-Z]\w+(`. +- Tampoco cambiar el modelo de "cada funcion del registry tiene un simbolo exportado". Si en el futuro una funcion expone un struct con metodos, anadir manejo. diff --git a/dev/issues/0058-kanban-uses-functions-sync.md b/dev/issues/0058-kanban-uses-functions-sync.md new file mode 100644 index 00000000..4caa3e55 --- /dev/null +++ b/dev/issues/0058-kanban-uses-functions-sync.md @@ -0,0 +1,60 @@ +# 0058 — kanban: sync uses_functions cuando termine WIP en curso + +## APP Metadata + +| Campo | Valor | +|-------|-------| +| **ID** | 0058 | +| **Estado** | pendiente | +| **Prioridad** | baja | +| **Tipo** | docs — `apps/kanban/app.md` | + +## Dependencias + +- Pre-commit hook v2 ya bloqueara commits que toquen codigo de kanban con drift activo. + +## Contexto + +En sesion 2026-05-07 el audit detecto drift en `apps/kanban/app.md`: + +- Missing (en imports, NO en app.md): `password_hash_go_infra`, `password_verify_go_infra`, `session_create_go_infra`, `session_cleanup_go_infra`, `http_session_cookie_middleware_go_infra` (5 funciones, todas relacionadas con auth). +- Unused (en app.md, NO en imports detectados): `spa_handler_go_infra`, `sqlite_open_go_infra`, `http_cors_middleware_go_infra` (3 funciones). + +La sincronizacion se aplazo porque el usuario tiene WIP activo en kanban (auth.go, frontend/src/Root.tsx, LoginPage.tsx, etc. — featurea de auth en construccion). + +## Objetivo + +Cuando el WIP de kanban termine y este commiteado: + +1. Confirmar imports reales con `grep '"fn-registry/' apps/kanban/*.go`. +2. Sincronizar `app.md` `uses_functions` con la realidad. +3. Verificar `fn doctor uses-functions` reporta kanban limpio. + +## Arquitectura + +### Archivos afectados + +- `apps/kanban/app.md` — actualizar array `uses_functions`. + +## Tareas + +### Fase 1 — esperar WIP commiteado +1.1 Confirmar `git -C apps/kanban status` limpio. + +### Fase 2 — sincronizar +2.1 Listar imports reales: `grep -rh '"fn-registry/' apps/kanban/*.go | sort -u`. +2.2 Cruzar con `uses_functions` actual de `app.md`. +2.3 Anadir 5 missing si siguen siendo missing. +2.4 Quitar 3 unused si siguen sin usarse (cuidado: el WIP nuevo puede haberlas activado o desactivado otras). + +### Fase 3 — verificar +3.1 `fn index`. +3.2 `fn doctor uses-functions` debe reportar `kanban_go_tools` sin drift. + +## Riesgos + +- El WIP cambia el conjunto de drift original. Re-correr audit antes de aplicar cambios — no asumir que las 5+3 detectadas el 2026-05-07 son aun validas. + +## Decisiones de diseno + +- Issue trivial pero se documenta para no olvidar (el pre-commit hook ya lo bloquearia, asi que no es urgente — solo corrige fricciones de UX). diff --git a/dev/issues/0059-nested-app-md-tracking.md b/dev/issues/0059-nested-app-md-tracking.md new file mode 100644 index 00000000..109f2135 --- /dev/null +++ b/dev/issues/0059-nested-app-md-tracking.md @@ -0,0 +1,96 @@ +# 0059 — Resolver doble tracking de `apps/*/app.md` (fn_registry + sub-repo) + +## APP Metadata + +| Campo | Valor | +|-------|-------| +| **ID** | 0059 | +| **Estado** | pendiente | +| **Prioridad** | media | +| **Tipo** | infra — git, .gitignore, indexer | + +## Dependencias + +- ADR 0002 (apps_analyses_as_dataforge_master): cada app es su propio repo. +- `.gitignore` raiz: `apps/*/`. + +## Contexto + +Detectado en sesion 2026-05-07: + +- `.gitignore` de `fn_registry` excluye `apps/*/`. +- Pero `apps/dag_engine/app.md` aparece tracked tambien por `fn_registry` (legado pre-gitignore). +- Resultado: el mismo archivo fisico es tracked por DOS repos: `fn_registry` Y `dataforge/dag_engine` (sub-repo). +- Cualquier cambio crea conmits duplicados, status confuso, riesgo de divergencia. + +``` +$ git status # en fn_registry + M apps/dag_engine/app.md +$ git -C apps/dag_engine status + M app.md +``` + +Mismo archivo. Dos `git add` distintos. + +## Objetivo + +Eliminar el doble tracking. Decidir source of truth y limpiar la otra. + +## Decisiones a tomar + +**Opcion A: source of truth = sub-repo.** +- `git rm --cached apps/*/app.md` en fn_registry (sin borrar archivo). +- `app.md` solo se commitea desde el sub-repo. +- `fn index` lee desde disco igual. +- PRO: consistente con ADR 0002 (sub-repo es la unidad). +- CONTRA: `app.md` no se versiona junto con cambios al registry que lo rompan (ej. funciones referenciadas que se borran). + +**Opcion B: source of truth = fn_registry.** +- Sub-repo NO trackea `app.md` (anadir a su `.gitignore`). +- `fn_registry` lo versiona. +- PRO: el indexer y el registry tienen control directo. +- CONTRA: el sub-repo es incompleto (falta su propia ficha de identidad). + +**Opcion C: ambos lo trackean conscientemente.** +- Documentar en regla nueva. +- Hook que bloquea desync (post-commit en uno avisa para commitear en el otro). +- PRO: cada repo es self-describing. +- CONTRA: complejidad operacional alta, riesgo de drift. + +**Recomendada: Opcion A.** Alinea con ADR 0002. La cobertura "registry rompe app.md" se cubre con `fn doctor uses-functions` + pre-commit hook v2. + +## Arquitectura + +### Archivos afectados + +- `.gitignore` raiz — verificar que `apps/*/` cubre todo. +- Posiblemente otros `apps/*/app.md` tracked legacy (auditar). +- `docs/adr/0004-app-md-source-of-truth.md` — NUEVO ADR. + +## Tareas + +### Fase 1 — auditar +1.1 `git ls-files apps/ | grep app.md` — listar todos los `app.md` tracked en fn_registry. +1.2 Cruzar con sub-repos para confirmar duplicacion. + +### Fase 2 — decision (humano) +2.1 Confirmar Opcion A o cambiar a B/C con razon documentada. + +### Fase 3 — implementacion (Opcion A) +3.1 Para cada `app.md` duplicado: confirmar que existe identico en el sub-repo. +3.2 `git rm --cached apps//app.md` en fn_registry. +3.3 Commit limpio en fn_registry. +3.4 No tocar el sub-repo (ya esta correcto). + +### Fase 4 — ADR + docs +4.1 Crear `docs/adr/0004-app-md-source-of-truth.md` con la decision y razon. +4.2 Actualizar `.claude/rules/cpp_apps.md` y `apps_vs_functions.md` si mencionan tracking. + +## Riesgos + +- Si el indexer asume que `app.md` esta tracked en fn_registry (no es el caso, lee de disco), cero impacto. +- Si `fn sync` o `pc_locations` asumen tracking, validar que solo dependen del archivo fisico. + +## Decisiones de diseno + +- Opcion A es coherente con ADR 0002 — apps son sub-repos completos. diff --git a/dev/issues/0060-fn-doctor-secrets-subcommand.md b/dev/issues/0060-fn-doctor-secrets-subcommand.md new file mode 100644 index 00000000..a5c43c8c --- /dev/null +++ b/dev/issues/0060-fn-doctor-secrets-subcommand.md @@ -0,0 +1,80 @@ +# 0060 — `fn doctor secrets`: scan de secrets en TODOS los repos + +## APP Metadata + +| Campo | Valor | +|-------|-------| +| **ID** | 0060 | +| **Estado** | pendiente | +| **Prioridad** | media | +| **Tipo** | feature — `cmd/fn/doctor.go` + funcion del registry | + +## Dependencias + +- `scan_secrets_in_dirty_bash_cybersecurity` ya existe (escanea solo dirty trees por nombres sospechosos). +- `discover_git_repos_bash_infra` ya existe. +- Pre-commit hook v2 invoca `scan_secrets_in_dirty` por repo. + +## Contexto + +Hoy el escaneo de secrets ocurre solo: + +1. En el pre-commit hook (de cada repo, sobre dirty tree antes del commit). +2. Cuando el usuario invoca manualmente `scan_secrets_in_dirty.sh`. + +NO hay un audit global "scan TODOS los repos en una pasada" para detectar secrets que ya esten commiteados (caso peor) o staged en repos que no se commitearon hoy. Riesgo: una key olvidada en un repo viejo puede estar pushed a Gitea desde hace meses sin que nadie lo sepa. + +## Objetivo + +Anadir subcomando `fn doctor secrets` que: + +1. Itera TODOS los repos descubiertos por `discover_git_repos`. +2. Por cada uno, escanea TODO el HEAD (no solo dirty) buscando: + - Nombres sospechosos (`*.env`, `*credentials*`, `*.key`, `*.pem`, `id_rsa*`, `*secret*`, `*token*.txt`). + - Patterns en contenido: AWS keys (`AKIA...`), JWT tokens, GitHub tokens (`ghp_...`), Google API keys (`AIza...`). +3. Reporta hallazgos como en otros `fn doctor` (texto humano + `--json`). +4. Exit 0 si limpio, 1 si encuentra algo. + +## Arquitectura + +### Archivos afectados + +- NUEVA funcion `scan_secrets_repo_bash_cybersecurity` (`bash/functions/cybersecurity/scan_secrets_repo.sh` + `.md`) — version "todo el repo" del existente. +- NUEVA funcion `scan_secrets_all_repos_go_cybersecurity` (`functions/cybersecurity/scan_secrets_all_repos.go`) — orquestador Go que itera repos y compone resultado. +- `cmd/fn/doctor.go` — anadir subcomando `secrets` que invoca la funcion Go. +- `.claude/rules/fn_doctor.md` — anadir entrada para `secrets`. + +## Tareas + +### Fase 1 — funcion bash de scan completo +1.1 Crear `scan_secrets_repo_bash_cybersecurity`: + - Args: ``. + - Lista todos los archivos tracked por git (`git ls-files`). + - Para cada uno, aplica los filtros de nombre y luego `grep -E` patterns en contenido. + - Output: lineas `SECRET :: `. + - Exit 0 si limpio, 1 si hay matches. + +### Fase 2 — orquestador Go +2.1 `ScanSecretsAllRepos(registryRoot string) ([]SecretFinding, error)`. +2.2 Llama internamente `discover_git_repos` (via shell-out o portar a Go). +2.3 Por cada repo, ejecuta `scan_secrets_repo.sh` y agrega findings. +2.4 Test con repo temporal con archivo dummy `.env`. + +### Fase 3 — CLI + docs +3.1 Anadir case `secrets` a `cmd/fn/doctor.go`. +3.2 Texto humano: tabla `REPO | FILE | TYPE | MATCH`. +3.3 `--json`: array de findings. +3.4 Anadir a `fn doctor` (todos los checks). +3.5 Actualizar `.claude/rules/fn_doctor.md` y CHANGELOG. + +## Riesgos + +- False positives en repos con muchos archivos. Mitigacion: aplicar filtros estrictos, opcion `--ignore-file` con regex. +- Lentitud: escanear todos los `git ls-files` de 32 sub-repos puede tardar segundos. Mitigacion: paralelizar por repo (goroutines). +- Si encuentra secret real, exponerlo en stdout es contradictorio. Mitigacion: redactar el match (`AKIA****REDACTED****`) en output. + +## Decisiones de diseno + +- Mantener la deteccion bash (scan_secrets_repo) — es lo que usan los hooks. El orquestador Go solo agrega. +- Patterns hardcodeados al principio. Despues mover a archivo de config si crecen. +- NO integrar gitleaks/trufflehog — aumenta deps externas. Los patterns basicos cubren 95% de casos. diff --git a/dev/issues/0061-notify-telegram-integration.md b/dev/issues/0061-notify-telegram-integration.md new file mode 100644 index 00000000..6c4cb559 --- /dev/null +++ b/dev/issues/0061-notify-telegram-integration.md @@ -0,0 +1,79 @@ +# 0061 — Integrar `notify_telegram` en deploy_server + bucle reactivo + +## APP Metadata + +| Campo | Valor | +|-------|-------| +| **ID** | 0061 | +| **Estado** | pendiente | +| **Prioridad** | media | +| **Tipo** | integration — `apps/deploy_server/`, `fn_operations/` | + +## Dependencias + +- `notify_telegram_go_infra` creada el 2026-05-07. +- `pass` con bot token guardado (`pass insert telegram/bot_token`). +- `pass` con chat_id (`pass insert telegram/chat_id`). +- `apps/deploy_server` (issue 0054 paralelo — refactor registry-first). +- `fn_operations/operations.go::ExecuteAndReact()` (bucle reactivo Go). + +## Contexto + +`notify_telegram_go_infra` fue creada como funcion atomica pero no esta integrada en ningun consumidor. El bucle reactivo (`assertions` que fallan) y los deploys (deploy_server) son los dos puntos donde alertas reales tendrian valor inmediato: + +- **deploy_server**: hoy si un deploy falla solo queda en `deploy_logs`. El usuario tiene que mirar la BD o la TUI para enterarse. Ideal: notify_telegram con `[FAIL] @: `. +- **bucle reactivo**: assertion `critical` falla → corruption detectada en datos. Hoy solo se persiste en `assertion_results`. Ideal: notify_telegram con `[CRITICAL] : : (expected )`. + +## Objetivo + +Anadir hooks de notificacion en los dos puntos: + +1. `deploy_server` envia notify al final de cada deploy (success o fail). +2. `fn_operations.ExecuteAndReact` envia notify cuando una assertion `critical` falla. + +Ambos hooks usan `notify_telegram_go_infra` y leen credenciales de `pass`. + +## Arquitectura + +### Archivos afectados + +- `apps/deploy_server/deployer.go` — anadir post-deploy hook que invoca notify. +- `apps/deploy_server/app.md` — declarar `notify_telegram_go_infra` en uses_functions. +- `fn_operations/operations.go` — extender `ExecuteAndReact` con notify hook. +- `fn_operations/operations_test.go` — test que mockea notify. +- NUEVA funcion `pass_telegram_creds_bash_infra` o helper Go para leer pass entries. + +## Tareas + +### Fase 1 — credenciales desde pass +1.1 Decidir naming: `pass insert telegram/bot_token` y `pass insert telegram/chat_id`. +1.2 Helper para leer ambas (existe `pass_get_bash_infra`, basta invocarlo). +1.3 Documentar setup en `docs/sync_setup.md` (no commitear values). + +### Fase 2 — integracion deploy_server +2.1 En `deployer.go` post-deploy: si `deploy_telegram_enabled = true` (config en `deploy_targets`), construir mensaje y llamar `infra.NotifyTelegram(...)`. +2.2 Truncar mensaje a 4096 chars (la funcion ya lo hace, pero documentar). +2.3 Schema de `deploy_targets`: anadir columna `notify_telegram BOOLEAN DEFAULT false`. +2.4 CLI: `deploy_server target add ... --notify-telegram`. + +### Fase 3 — integracion bucle reactivo +3.1 En `ExecuteAndReact`, tras evaluar assertions, si alguna `critical` fallo, construir mensaje y llamar notify. +3.2 Config: `assertion.notify_telegram BOOLEAN` (por assertion) — solo notifica si true. +3.3 Test `TestExecuteAndReact_NotifiesCriticalFailure` con notify mockeado. + +### Fase 4 — docs + verificacion +4.1 Update CHANGELOG.md. +4.2 Manual test: forzar un deploy fail, verificar mensaje llega. +4.3 Manual test: forzar assertion fail, verificar mensaje llega. + +## Riesgos + +- Spam de notificaciones si una assertion falla repetidamente. Mitigacion: rate limiting (no enviar si ya se envio en ultima hora) — opcional, dejar para v2. +- Token expuesto en logs si `notify_telegram` lo loggea. Verificar que la funcion redacta el token. +- Sin pass: la integracion debe degradar silenciosa (log warning, no abortar deploy). + +## Decisiones de diseno + +- Mensajes en formato `[] : ` para grep facil en chat. +- Markdown opcional (parseMode "Markdown") — abre superficie a inyeccion de markdown si el body viene de error externo. Default `parseMode=""` (plain). +- NO crear topic/thread de Telegram — un solo chat para todo. Si crece, refactor. diff --git a/dev/issues/0062-deprecate-unused-core-functions.md b/dev/issues/0062-deprecate-unused-core-functions.md new file mode 100644 index 00000000..d11cddc6 --- /dev/null +++ b/dev/issues/0062-deprecate-unused-core-functions.md @@ -0,0 +1,79 @@ +# 0062 — Politica de deprecacion para funciones del registry sin consumidores + +## APP Metadata + +| Campo | Valor | +|-------|-------| +| **ID** | 0062 | +| **Estado** | pendiente | +| **Prioridad** | baja | +| **Tipo** | research + policy — `.claude/rules/`, `docs/` | + +## Dependencias + +- `find_unused_functions_go_infra` (existe, lista 704 funciones sin consumidores al 2026-05-07). +- `fn doctor unused`. + +## Contexto + +Sesion 2026-05-07: el registry tiene 1066 funciones. `fn doctor unused` reporta 704 sin consumidores (66%). La mayoria son utilities core puras (`compose2_go_core`, `curry2_go_core`, `chunk_go_core`, `flat_map_slice_go_core`, etc.) construidas especulativamente — esperando que alguna app las consuma. + +Sin politica explicita de "que hacer con unused", el registry crece sin freno. Posibles destinos: + +1. **Mantener** indefinidamente (libreria publica disponible). +2. **Deprecar via tag** (`tags: [deprecated]`) — sigue presente pero senala "no usar para codigo nuevo". +3. **Borrar** despues de N meses sin consumidor. + +Decision pospuesta: cualquier eleccion afecta cientos de archivos y la velocidad de scaffold de nuevas apps que pueden recogerlas. + +## Objetivo + +Definir y documentar una politica formal: + +1. Criterios cuantitativos: cuanto tiempo (en dias) sin consumidor justifica deprecar. +2. Excepciones: funciones con tag `core-utility` o `library-quality` se mantienen. +3. Workflow de deprecacion: tag → 90 dias → borrar. +4. Hook automatico: `fn doctor unused --propose-deprecation` abre proposals. + +## Arquitectura + +### Archivos afectados + +- NUEVA regla `.claude/rules/unused_functions.md`. +- NUEVO ADR `docs/adr/0005-unused-functions-policy.md`. +- `find_unused_functions_go_infra` — opcionalmente extender con `AgeDays` desde `updated_at` (ya lo tiene) y filtrar por edad. +- `cmd/fn/doctor.go` — anadir flag `--older-than ` al subcomando `unused`. + +## Tareas + +### Fase 1 — definir politica (humano) +1.1 Decidir umbrales: `tag deprecated` tras 60 dias sin consumidor; `borrar` tras 180 dias. +1.2 Decidir excepciones: tag `core-utility` exime, tag `library-quality` exime, dominios `core` puros mas tolerantes que dominios infra. +1.3 Decidir si la deprecacion es manual (humano via proposal) o automatica (cron). + +### Fase 2 — escribir ADR + regla +2.1 ADR 0005 con la decision, alternativas, consecuencias. +2.2 Regla `.claude/rules/unused_functions.md` operacional. +2.3 Update `INDEX.md`. + +### Fase 3 — extender herramienta +3.1 `fn doctor unused --older-than 60` filtra por edad. +3.2 `fn doctor unused --propose-deprecation` crea proposals automaticas con `kind=deprecate_function`. +3.3 Workflow humano: revisar proposals, aprobar, agente aplica el tag. + +### Fase 4 — primera ronda +4.1 Correr `fn doctor unused --older-than 90`. +4.2 Decidir caso por caso (o lote por dominio): mantener / deprecar / borrar. +4.3 Aplicar tags. Re-indexar. Update CHANGELOG. + +## Riesgos + +- Borrar funciones que el usuario planeaba usar pronto. Mitigacion: ventana larga (180 dias) + proposal manual antes de borrar. +- Tags desfasados: una funcion deprecated puede seguir siendo usada. Mitigacion: el indexer puede warn si una app declara una `deprecated` en `uses_functions`. +- Deprecation como excusa para no usar (cosmica). Mitigacion: revisiones trimestrales, no que se acumule. + +## Decisiones de diseno + +- NO borrar nunca automaticamente. Borrado siempre humano via PR/proposal aprobada. +- Tag `deprecated` es el verbo automatizable: un agente puede aplicarlo via proposal. +- Para funciones nuevas creadas tras adoptar la politica, exigir que tengan al menos UN consumidor previsto al merge — sino van directo con tag `experimental`. diff --git a/dev/issues/README.md b/dev/issues/README.md index 21901d86..00e6c482 100644 --- a/dev/issues/README.md +++ b/dev/issues/README.md @@ -69,3 +69,12 @@ | [0050](0050-jupyter-exec-collab-client-failure.md) | `jupyter_exec` falla por cliente colaborativo (workaround documentado) | pendiente | media | bug | — | | [0051](0051-extraction-pipeline-followups.md) | Funciones pendientes del pipeline NER+RE (NuExtract, extract_graph_from_pdf, spaCy ES V2, kernel startup fix, REBEL EN) | pendiente | media | feature | — | | [0053](completed/0053-kanban-chat-panel.md) | Chat lateral en apps/kanban via `claude -p` (sonnet, persistencia localStorage) | completado | media | feature | — | +| [0054](0054-deploy-server-registry-first-refactor.md) | deploy_server: refactor registry-first (SSH/systemd/rsync inline → registry funcs) | pendiente | alta | refactor | — | +| [0055](0055-docker-tui-registry-first-refactor.md) | docker_tui: refactor para usar funciones docker_* del registry | pendiente | alta | refactor | — | +| [0056](0056-audit-python-nested-imports.md) | audit_uses_functions: detectar imports Python anidados (`from pkg.subpkg import X`) | pendiente | media | enhancement | — | +| [0057](0057-audit-go-symbol-naming.md) | audit_uses_functions: mejorar deteccion de simbolos Go con abreviaturas | pendiente | baja | enhancement | — | +| [0058](0058-kanban-uses-functions-sync.md) | kanban: sync uses_functions cuando termine WIP en curso | pendiente | baja | docs | — | +| [0059](0059-nested-app-md-tracking.md) | Resolver doble tracking de `apps/*/app.md` (fn_registry + sub-repo) | pendiente | media | infra | — | +| [0060](0060-fn-doctor-secrets-subcommand.md) | `fn doctor secrets`: scan de secrets en TODOS los repos | pendiente | media | feature | — | +| [0061](0061-notify-telegram-integration.md) | Integrar `notify_telegram` en deploy_server + bucle reactivo | pendiente | media | integration | 0054 | +| [0062](0062-deprecate-unused-core-functions.md) | Politica de deprecacion para funciones del registry sin consumidores | pendiente | baja | research | — |