# 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/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/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/fn_registry $HOME/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