ADR-0024: server HTTP dei grafi delle pipeline (etl serve)
- Stato: Accettata
- Data: 2026-07-21
Contesto
Fino a questa decisione la topologia dei grafi delle pipeline (i PlanSpec prodotti da getSpec()) veniva materializzata a build-time dalla UI: noeva-etl-ui lanciava etl plan, catturava il JSON e lo congelava in src/data/plans.generated.json, importato in modo sincrono. La generazione dei dati viveva quindi nel repo sbagliato (la UI), e i grafi erano un artefatto di build statico: aggiungere o cambiare una pipeline richiedeva rigenerare e ricommittare il JSON nella UI.
Volevamo ribaltare la responsabilità: i grafi devono essere generati da noeva-etl (che possiede il registro PIPELINES) ed esposti via API HTTP, così che la UI li consumi a runtime senza artefatti di build.
Decisione
Introdotto un server HTTP read-only in src/server/, avviato dal nuovo comando etl serve (src/cli.ts), stack Express 5 + cors (coerente con noeva-server-api):
buildGraphCache()(src/server/graph-cache.ts) iteraPIPELINES, chiamagetSpec()e costruisce una cache immutabilenome → PlanSpecuna sola volta all'avvio.getSpec()è puro/deterministico (nessuna credenziale, nessun I/O), quindi la generazione al boot è sicura e a costo trascurabile.createServer()(src/server/http-server.ts) espone:GET /health→{ status: "ok" };GET /graphs→{ name, description }[](lista per il selettore pipeline);GET /graphs/:name→PlanSpec(dettaglio),404 { message }se sconosciuto.
startServer()(src/server/run-server.ts) leggeETL_HTTP_PORT(default 3005, distinta danoeva-server-api= 3002) eETL_HTTP_CORS_ORIGIN(default*).- Lifecycle SIGTERM/SIGINT come
etl worker.
Nessuna autenticazione sull'API: espone solo topologia + descriptor non sensibili (ADR-0020), gli stessi dati che erano già pubblici nel bundle della UI. In produzione la protezione è la restrizione dell'origine via ETL_HTTP_CORS_ORIGIN.
etl plan (stampa su stdout) resta invariato per uso da CLI/debug.
Conseguenze
- La UI passa da import statico a fetch async (
VITE_ETL_API_BASE_URL), con stati loading/error;scripts/generate-plans.mjseplans.generated.jsonvengono rimossi. - Il container etl deve ora esporre una porta e girare
etl servecome servizio distinto dalworker— aggiornamento diDockerfile/docker-compose.yml/deploy-ecr.sh(follow-up operativo, vedi runbook). - Il contratto
PlanSpecè invariato: la sincronizzazione manuale col contratto Zod della UI (ADR-0020) resta valida.

