Files
TieMeasureFlow/src/frontend/flask_app/static/vendor/VERSIONS.md
T
Adriano Dal Pastro c4a429d952 feat(offline): la policy arriva dove le pagine si aprono davvero
Punto 12. Le cinque librerie erano già state portate in casa (28ee44b): nessun
template carica più niente dalla rete, il worker di PDF.js è locale in tutti e
quattro i file che lo impostano, i font sono woff2 nel pacchetto. Verificato riga
per riga, e le impronte SHA-256 in VERSIONS.md corrispondono ancora.

Mancava però la seconda metà dell'intervento, e mancava dove conta. La
Content-Security-Policy a sola origine locale esisteva sul backend, cioè sulle
risposte API; le pagine HTML le serve il client Flask, che non mandava alcuna
policy. La regola stava scritta dove non poteva essere infranta e assente dove
poteva. Ora il client la manda su ogni risposta.

Serve meno a difendere e più a non far tornare indietro il punto: un tag verso un
CDN aggiunto fra sei mesi viene rifiutato dal browser alla scrivania, dove c'è la
rete e l'errore si legge in console, invece che in reparto dove la rete non c'è.

Tailwind era ancora agganciato a `tailwindcss@3` nel Dockerfile: stesso difetto
che il documento cita per le librerie del browser, un gradino più in basso. Fissato
a 3.4.19, che è la versione con cui l'immagine in esercizio è stata costruita.

I test non renderizzano niente: leggono i sorgenti, perché il difetto che devono
impedire si scrive in un template e non si vede finché non si stacca la rete.
Controllano anche le impronte — una libreria sostituita sul posto tiene lo stesso
nome e la stessa riga in tabella, e l'hash è l'unica parte che se ne accorge.

Annotato in VERSIONS.md che `html5-qrcode` è l'unica libreria dichiarata e mai
caricata: lo scanner da fotocamera non è incluso da nessuna pagina, il lettore che
l'operatore usa è un campo di testo. Va portata in casa prima di accenderlo.

README aggiornato a V3.0.0: novità della versione punto per punto, ruolo
Supervisor, librerie locali al posto dei CDN, stato dei test.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 21:58:13 +00:00

6.0 KiB
Raw Blame History

Librerie di terze parti — copie locali

Queste copie servono al punto 12 del documento delle modifiche: l'installazione a Tràfilo è on-premise, su rete di produzione isolata. Finché queste librerie venivano scaricate da CDN a ogni apertura di pagina, senza internet l'interfaccia non partiva affatto (Alpine.js governa tutta la UI).

Secondo effetto, non meno importante: le versioni sono congelate. Prima Alpine.js era agganciato a alpinejs@3.x.x, cioè l'applicazione cambiava da sola a ogni rilascio degli autori, senza validazione. Per un sistema che produce evidenze per audit ISO 9001 / IATF 16949 questo è di per sé un difetto.

Scaricate il 28 luglio 2026.

JavaScript

File Versione Origine
alpinejs-3.15.12.min.js 3.15.12 https://cdn.jsdelivr.net/npm/alpinejs@3.15.12/dist/cdn.min.js
plotly-2.32.0.min.js 2.32.0 https://cdn.plot.ly/plotly-2.32.0.min.js
pdf-3.11.174.min.js 3.11.174 https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js
pdf.worker-3.11.174.min.js 3.11.174 https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js
fabric-5.3.1.min.js 5.3.1 https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.1/fabric.min.js

La versione di Alpine è quella a cui 3.x.x risolveva il giorno del congelamento: il pin non cambia il comportamento rispetto a quanto già in esercizio.

pdf.worker è un file a sé che PDF.js carica a runtime via pdfjsLib.GlobalWorkerOptions.workerSrc. Va ripuntato in tutti i template che usano PDF.js, non basta lo script principale: altrimenti la libreria si carica in locale e il worker continua a cercare internet — sembra funzionare finché non si apre un disegno.

Font

fonts.css sostituisce il <link> a fonts.googleapis.com in base.html.

File Famiglia Subset
fonts/inter-latin.woff2 Inter latin
fonts/inter-latin-ext.woff2 Inter latin-ext
fonts/jetbrains-mono-latin.woff2 JetBrains Mono latin
fonts/jetbrains-mono-latin-ext.woff2 JetBrains Mono latin-ext

Entrambe le famiglie sono font variabili (asse wght: Inter 100900, JetBrains Mono 400800): un solo file per subset copre tutti i pesi usati dall'interfaccia. Google serviva lo stesso woff2 sotto otto URL diversi, uno per peso dichiarato.

Tenuti i soli subset latin e latin-ext, che coprono per intero italiano e inglese. Per gli altri alfabeti il browser ricade sul font di sistema — scelta consapevole: cirillico, greco e vietnamita valevano 600 KB di peso morto.

Impronte SHA-256

57b37d7cae9a27d965fdae4adcc844245dfdc407e655aee85dcfff3a08036a3f  alpinejs-3.15.12.min.js
bb0442d69a4d4673320f689bc6e16c05a0e3f16ccfbf551f394d90a7e7cfc772  fabric-5.3.1.min.js
5b5799e6f8c680663207ac5b42ee14eed2a406fa7af48f50c154f0c0b1566946  pdf-3.11.174.min.js
feabdf309770ed24bba31a5467836cdc8cf639c705af27d52b585b041bb8527b  pdf.worker-3.11.174.min.js
0a17719a72751704861215da0e5c5cdb3f9a8d50eff5cb84cb6f8b80786682b0  plotly-2.32.0.min.js
34b9c504cab7a73e37b746343a449132e56cf7b5481af2cb81dc74dcff25c956  fonts/inter-latin-ext.woff2
3100e775e8616cd2611beecfa23a4263d7037586789b43f035236a2e6fbd4c62  fonts/inter-latin.woff2
db5ff4db83e580426280e9337a58dc57d3a83784a1b03ad80914651594441d52  fonts/jetbrains-mono-latin-ext.woff2
83c005d49d8a6a50474c73a5a36ac0468076e9c4a29da7bdb14995d80560a5be  fonts/jetbrains-mono-latin.woff2

Verifica: sha256sum -c da questa cartella, oppure sha256sum *.js fonts/*.woff2. Il confronto è anche un test (tests/test_offline.py::test_the_shipped_libraries_are_the_ones_that_were_checked): una libreria sostituita sul posto tiene lo stesso nome e la stessa riga in tabella, e l'impronta è l'unica parte che se ne accorge.

La regola che tiene il punto chiuso

Le copie locali risolvono il problema una volta; quello che lo tiene risolto è la Content-Security-Policy servita dal client Flask (app.py, CSP), che ammette solo l'origine locale. Prima esisteva solo sul backend — cioè sulle risposte API, non sulle pagine che il browser disegna: la regola stava scritta dove non poteva essere infranta e mancava dove poteva.

Con la policy in vigore, un <script src="https://cdn…"> aggiunto fra sei mesi viene rifiutato dal browser alla scrivania, dove c'è la rete e l'errore si legge in console, invece che in reparto dove la rete non c'è.

Tailwind

Tailwind non sta in questa cartella: è compilato in fase di build dell'immagine (Dockerfile.frontend) e il CSS finito viene servito da static/css/tailwind.css. Vale però lo stesso vincolo — la versione è fissata a tailwindcss@3.4.19. Con tailwindcss@3 ogni ricostruzione poteva prendere una minor diversa e produrre un foglio di stile diverso senza che nessuno l'avesse validato.

Nota per l'installazione on-premise: la costruzione dell'immagine richiede rete (npm, apt, uv). È l'esecuzione a non richiederla. In reparto va portata l'immagine già costruita, non il repository da compilare sul posto.

Una sesta libreria, oggi non caricata

static/js/barcode.js e templates/components/barcode_scanner.html implementano lo scanner QR con la fotocamera e si appoggiano a html5-qrcode, che non è mai caricata da nessuna pagina: il componente non è incluso da nessuna parte e la libreria non è in questa cartella. A runtime non rompe niente — è codice morto.

La lettura del barcode che l'operatore usa davvero è un campo di testo in measure/select_recipe.html: il lettore hardware la digita, e non serve nessuna libreria.

Se un giorno si accende lo scanner da fotocamera, html5-qrcode va portata qui prima, altrimenti in reparto quel pulsante mostra «scanner_lib_not_loaded» e basta.

Aggiornare una libreria

  1. Scaricare la nuova versione con il nome comprensivo di versione.
  2. Ripuntare i <script>/<link> nei template (grep -rn vendor/ ../../templates/).
  3. Aggiornare questa tabella e le impronte.
  4. Rimuovere il file vecchio.

Il nome del file porta la versione apposta: un aggiornamento non passa inosservato in revisione, e la modifica resta tracciata in git.