Skip to content

0044. La documentazione vive nell'app desktop, al posto della guida in-app

  • Stato: Accettata
  • Data: 2026-09-14
  • Decisori: Team BI/ETL
  • Contesto correlato: ADR-0043 (il sito), ADR-0025 (l'app desktop Tauri)

Contesto

ADR-0043 ha introdotto il sito di documentazione generato da docs/, lasciando aperto dove pubblicarlo. Nel frattempo noeva-etl-ui aveva la sua pagina /guida: una sintesi scritta a mano in JSX di due documenti del repository, da rivedere a mano ogni volta che quei documenti cambiavano (noeva-etl-ui/docs/navigation.md, § Contenuto della guida). Due testi sullo stesso argomento, uno dei quali destinato a restare indietro.

L'app è usata solo dal team di Gruppo4D, e chi la apre è esattamente il pubblico del sito: chi consulta i processi e chi li crea. GitHub Pages sui repo privati non è disponibile con il piano dell'org, e un hosting separato avrebbe voluto dire un accesso in più da gestire.

Decisione

Il sito di documentazione è la guida dell'app: la pagina /guida di noeva-etl-ui lo mostra al posto della sintesi in JSX.

  • Nel bundle, non da rete. pnpm run docs:bundle (in noeva-etl-ui) builda il sito dal repository padre con base /docs/ dentro noeva-etl-ui/public/docs/ (git-ignored); Vite lo copia nel bundle e Tauri lo serve come il resto del frontend. La build di produzione (pnpm build, quindi pnpm tauri build) lo esegue da sola, e fallisce con un messaggio chiaro se la UI non è dentro un checkout di noeva-etl con le dipendenze installate. Funziona offline, come i font self-hostati dell'app.

  • In un iframe, dentro l'app. /guida tiene l'header dell'app (marchio, «← Processi», tema) e sotto mostra il sito. Resta fuori dal gate di autenticazione, come prima.

  • Un protocollo postMessage minimo fra le due parti — lato sito docs/.vitepress/lib/embed-protocol.ts e il componente EmbedBridge, lato app src/lib/docs-embed.ts — con tre messaggi:

    • ready (sito → app): il sito si è montato. Un percorso che l'app non trova ricade sul suo index.html: senza questo segnale l'iframe potrebbe mostrare l'app dentro sé stessa. L'iframe resta nascosto finché il sito non risponde, e se non risponde l'app dice che la documentazione non è inclusa nella build.
    • theme (app → sito): il tema lo decide l'app; dentro l'iframe il selettore del sito sparisce.
    • open-external (sito → app): nella webview Tauri un link esterno non apre nulla. Il sito intercetta il clic e l'app apre l'URL nel browser di sistema con @tauri-apps/plugin-opener, con lo scope limitato a https e all'http verso localhost e 127.0.0.1.
  • Il sito resta un sito. Fuori da un iframe nessun messaggio parte e nulla cambia: la stessa build si può ancora consultare con pnpm run docs:dev. Dentro l'app, logo e wordmark lasciano il posto alla scritta «Documentazione», perché il marchio sta già nell'header dell'app.

  • Due varianti, scelte con NOEVA_DOCS_TARGET. Ogni cliente ha le sue pipeline, quindi le parti che parlano di un cliente non vanno in una documentazione pubblicata fuori dall'app:

    • app — la variante che docs:bundle mette nell'app. Contiene tutto.
    • public — il default, per un hosting esterno (Cloudflare Workers, ADR-0045). Esclude i percorsi elencati in APP_ONLY (docs/.vitepress/lib/docs-target.ts: le schede pipeline e i runbook delle pipeline di un cliente) e i passaggi dei documenti pubblici racchiusi in un blocco ::: solo-app. I link verso ciò che è escluso diventano testo semplice: un link a GitHub direbbe comunque di quale cliente è la pipeline. Sparisce anche il conteggio delle schede nella home.

    Il default è public perché una build lanciata senza pensarci non deve esporre le pipeline dei clienti. Il gate (pnpm run check e la CI) builda entrambe le varianti.

Alternative considerate

  • Servire il sito da etl serve. L'app parla già con quel server, ma la documentazione dipenderebbe dalla rete e da un server acceso, e un container ETL servirebbe pagine web che non sono affar suo.
  • Aprire il sito a finestra piena, uscendo dall'app React. Nella finestra Tauri non c'è un pulsante Indietro: servirebbe un link di ritorno dentro il sito, e il tema non sarebbe più dell'app.
  • Link esterni disattivati nell'app. Nessun permesso Tauri in più, ma i riferimenti a GitHub e Jira — decine, non i due che avevano fatto scartare il plugin opener per la vecchia guida — diventerebbero testo morto per chi ha accesso al repository.
  • Un hosting esterno come unica sede. Un accesso in più da proteggere e un posto in più da tenere aggiornato, per un pubblico che ha già l'app. Resta possibile come sede aggiuntiva per la variante public, che non contiene nulla di specifico dei clienti: con ADR-0045 la si pubblica su Cloudflare Workers.
  • Un'unica variante, con le pipeline in pagine non linkate. Una pagina fuori dal menu resta raggiungibile e finisce nell'indice di ricerca: nascondere non basta, bisogna non pubblicare.

Conseguenze

  • Positive. Una sola documentazione, sempre coerente con i documenti del repository al momento della build dell'app; consultabile offline; la sintesi a mano sparisce, e con lei il lavoro di tenerla allineata.
  • Costi. Il bundle dell'app cresce di circa 17 MB, soprattutto per mermaid, che però si carica solo sulle pagine con un diagramma. La build della UI richiede il checkout di noeva-etl con pnpm install fatto: è già il modo in cui la UI si builda, come submodule.
  • La documentazione nell'app è quella del momento della build. Un documento cambiato dopo arriva nell'app con la release successiva. In sviluppo si rigenera con pnpm run docs:bundle (./dev-desktop.sh lo fa da solo la prima volta).
  • Contratto a due metà. Il protocollo è definito in due repository; ciascuna metà ha i suoi test, e i due file si citano a vicenda. Chi ne cambia uno cambia l'altro.
  • Un vincolo in più per chi scrive. Un documento nuovo specifico di un cliente va sotto docs/pipelines/, oppure si aggiunge ad APP_ONLY; un passaggio che nomina un cliente in un documento pubblico va in un blocco ::: solo-app. Su GitHub i marcatori del blocco restano visibili come testo.

Noeva è un marchio registrato di 4D S.R.L.