feat(0121a): wave 2 e2e_checks proposals (8 apps) + README updated
8 fn-recopilador design-e2e paralelos: - services_api (Go service, schema custom operations.db) - registry_mcp (Go stdio MCP, JSON-RPC handshake test) - sqlite_api (Go service read-only HTTP, query_endpoint) - registry_dashboard (C++ ImGui, NO Go+React como yo supuse) - primitives_gallery (C++ build gate de toda API C++ del registry, 44 .cpp) - pipeline_launcher (Go TUI bubbletea) - docker_tui (Go TUI + go-duckdb) - fn_match (subcmd ./fn, hook helper, fuzzy match) 13/26 apps cubiertas. README documenta: - 6 bugs/drift descubiertos lateral (dag_engine x3, deploy_server, pipeline_launcher, docker_tui). - 3 correcciones de mi prompt (yo asumi stacks incorrectos). - Hallazgos arquitectonicos (primitives_gallery = build gate C++). Pendiente wave 3 (13 apps) + 0121b + 0121c. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
# e2e_checks proposal — sqlite_api
|
||||
# app_id: projects/fn_monitoring/apps/sqlite_api
|
||||
# lang: go
|
||||
# stack: Go service, net/http, CGO_ENABLED=1, SQLite FTS5
|
||||
# module: fn-registry (go.mod en raiz del repo)
|
||||
# binary: projects/fn_monitoring/apps/sqlite_api/sqlite_api (pre-compilado)
|
||||
# systemd: sqlite_api.service (user scope, ExecStart usa el binario compilado)
|
||||
# e2e port: 8684 (prod 8484 + 200)
|
||||
# e2e db: /tmp/sqlite_api_e2e.db
|
||||
# date: 2026-05-19
|
||||
# issue: 0121a wave 2
|
||||
# nota: service critico — caida 20h el 2026-05-17 por Restart=on-failure
|
||||
# (ya corregido a Restart=always en el unit). Checks refuerzan
|
||||
# que el binario arranca, responde, y ejecuta queries correctamente.
|
||||
|
||||
e2e_checks:
|
||||
# --- build ------------------------------------------------------------------
|
||||
- id: build
|
||||
# Compila el binario del service con CGO+FTS5.
|
||||
# El binario resultante es el mismo que usa el systemd unit.
|
||||
# Correr desde la raiz del repo porque go.mod vive ahi.
|
||||
cmd: >
|
||||
cd /home/lucas/fn_registry &&
|
||||
CGO_ENABLED=1 go build -tags fts5
|
||||
-o projects/fn_monitoring/apps/sqlite_api/sqlite_api
|
||||
./projects/fn_monitoring/apps/sqlite_api/
|
||||
timeout_s: 120
|
||||
severity: critical
|
||||
|
||||
# --- tests ------------------------------------------------------------------
|
||||
- id: tests
|
||||
# Suite de tests unitarios Go existente (handlers_test.go).
|
||||
# Cubre: /health, /api/databases, /api/databases/:db/query,
|
||||
# ValidateQuery (whitelist SELECT/PRAGMA/WITH/EXPLAIN),
|
||||
# DiscoverDatabases, /tables, /schema, 404 para DB inexistente.
|
||||
# Usan DB en t.TempDir() — totalmente efimeros.
|
||||
cmd: >
|
||||
cd /home/lucas/fn_registry &&
|
||||
CGO_ENABLED=1 go test -tags fts5 -count=1 -v
|
||||
./projects/fn_monitoring/apps/sqlite_api/
|
||||
timeout_s: 60
|
||||
severity: critical
|
||||
|
||||
# --- smoke ------------------------------------------------------------------
|
||||
- id: smoke
|
||||
# Arranca el binario compilado con BD efimera y puerto alto.
|
||||
# FN_REGISTRY_ROOT apunta a la raiz para que DiscoverDatabases
|
||||
# encuentre registry.db real (necesario para /api/databases).
|
||||
# El proceso queda en background; fn-analizador lo mata al terminar.
|
||||
cmd: >
|
||||
FN_REGISTRY_ROOT=/home/lucas/fn_registry
|
||||
/home/lucas/fn_registry/projects/fn_monitoring/apps/sqlite_api/sqlite_api
|
||||
--bind 127.0.0.1:8684
|
||||
--data-factory-db /tmp/sqlite_api_e2e_df.db &
|
||||
health: "http://127.0.0.1:8684/api/databases"
|
||||
timeout_s: 10
|
||||
severity: critical
|
||||
|
||||
# --- query_endpoint ---------------------------------------------------------
|
||||
- id: query_endpoint
|
||||
# Valida que el endpoint POST /api/databases/:db/query funciona end-to-end:
|
||||
# 1. Crea una BD SQLite efimera con una tabla trivial.
|
||||
# 2. La registra como argumento de query via BD de registro en /api/databases.
|
||||
# 3. Ejecuta SELECT 1 contra la BD "registry" (siempre disponible si hay
|
||||
# FN_REGISTRY_ROOT correcto) y valida JSON con count>=1 y campo "columns".
|
||||
# Alternativa mas simple: hit directo al endpoint con la BD ya registrada.
|
||||
cmd: >
|
||||
curl -sf -X POST http://127.0.0.1:8684/api/databases/registry/query
|
||||
-H 'Content-Type: application/json'
|
||||
-d '{"sql":"SELECT 1 AS ping"}'
|
||||
| python3 -c "
|
||||
import sys, json
|
||||
r = json.load(sys.stdin)
|
||||
assert r.get('count') == 1, f'count != 1: {r}'
|
||||
assert 'columns' in r, f'no columns: {r}'
|
||||
assert r['columns'][0] == 'ping', f'col != ping: {r}'
|
||||
print('query_endpoint OK:', r)
|
||||
"
|
||||
timeout_s: 10
|
||||
severity: critical
|
||||
|
||||
# --- write_rejection --------------------------------------------------------
|
||||
- id: write_rejection
|
||||
# El service se declara read-only. Verifica que INSERT es rechazado con 400.
|
||||
# Regresion directa del contrato de seguridad de sqlite_api.
|
||||
cmd: >
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}"
|
||||
-X POST http://127.0.0.1:8684/api/databases/registry/query
|
||||
-H 'Content-Type: application/json'
|
||||
-d '{"sql":"INSERT INTO functions VALUES (\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\",\"x\")"}') &&
|
||||
[ "$STATUS" = "400" ]
|
||||
timeout_s: 10
|
||||
severity: critical
|
||||
|
||||
# --- auth_check -------------------------------------------------------------
|
||||
- id: auth_check
|
||||
# Service actualmente NO requiere auth (bind 127.0.0.1 mitiga).
|
||||
# Este check documenta el estado actual: cualquier cliente local puede
|
||||
# hacer queries. Si en el futuro se añade X-Registry-Token, este check
|
||||
# debe actualizarse para enviar el token correcto y esperar 401 sin token.
|
||||
# Por ahora verifica que el endpoint responde sin auth header (comportamiento esperado).
|
||||
cmd: >
|
||||
curl -sf http://127.0.0.1:8684/health
|
||||
| python3 -c "import sys,json; r=json.load(sys.stdin); assert r['status']=='ok'"
|
||||
timeout_s: 5
|
||||
severity: warning
|
||||
|
||||
# --- ops_audit --------------------------------------------------------------
|
||||
- id: ops_audit
|
||||
# Invoca al fn-recopilador sobre las operations.db de apps de fn_monitoring.
|
||||
# sqlite_api no tiene su propio operations.db pero es parte del proyecto
|
||||
# fn_monitoring que sí tiene call_monitor con operations.db activa.
|
||||
ref: "fn-recopilador:projects/fn_monitoring/apps/sqlite_api"
|
||||
severity: warning
|
||||
Reference in New Issue
Block a user