From 28ee44bcf1c1499e2b4e0d9af415610ea5836b1f Mon Sep 17 00:00:00 2001 From: Adriano Dal Pastro Date: Tue, 28 Jul 2026 15:41:57 +0000 Subject: [PATCH] feat(client): includi librerie e font in locale per il funzionamento offline Punto 12 del documento modifiche del 28/07. L'installazione a Trafilo e' on-premise su rete di produzione isolata: finche' Alpine.js, Plotly, PDF.js, Fabric.js e i Google Fonts venivano scaricati da CDN a ogni apertura di pagina, senza internet l'interfaccia non partiva affatto (Alpine governa tutta la UI). Le librerie passano in static/vendor/ con la versione nel nome del file, e la CSP del backend si chiude a solo-origine. Il worker di PDF.js e' ripuntato in tutti e quattro i template che lo usano: ripuntando solo lo script principale la libreria si carica in locale ma il worker continua a cercare internet, e sembra funzionare finche' non si apre un disegno. Alpine e' pinnato a 3.15.12, cioe' la versione a cui "3.x.x" risolveva oggi: il congelamento non cambia il comportamento di quanto e' gia' in esercizio, e toglie il fatto che l'applicazione cambiasse da sola a ogni rilascio degli autori - rilevante per le evidenze ISO 9001 / IATF 16949. Inter e JetBrains Mono sono font variabili: un solo woff2 per subset copre tutti i pesi, dove Google serviva lo stesso file sotto otto URL. Tenuti i soli subset latin e latin-ext, che coprono per intero italiano e inglese. Provenienza, versioni e impronte SHA-256 in static/vendor/VERSIONS.md. Co-Authored-By: Claude Opus 5 (1M context) --- .../api/middleware/security_headers.py | 14 ++-- .../flask_app/static/vendor/VERSIONS.md | 77 ++++++++++++++++++ .../static/vendor/alpinejs-3.15.12.min.js | 5 ++ .../static/vendor/fabric-5.3.1.min.js | 1 + .../flask_app/static/vendor/fonts.css | 44 ++++++++++ .../static/vendor/fonts/inter-latin-ext.woff2 | Bin 0 -> 85068 bytes .../static/vendor/fonts/inter-latin.woff2 | Bin 0 -> 48256 bytes .../fonts/jetbrains-mono-latin-ext.woff2 | Bin 0 -> 11624 bytes .../vendor/fonts/jetbrains-mono-latin.woff2 | Bin 0 -> 31432 bytes .../static/vendor/pdf-3.11.174.min.js | 22 +++++ .../static/vendor/pdf.worker-3.11.174.min.js | 22 +++++ .../static/vendor/plotly-2.32.0.min.js | 8 ++ src/frontend/flask_app/templates/base.html | 10 +-- .../templates/maker/recipe_preview.html | 4 +- .../templates/maker/task_drawing.html | 6 +- .../templates/maker/task_editor.html | 4 +- .../templates/measure/task_execute.html | 4 +- .../templates/statistics/dashboard.html | 2 +- 18 files changed, 201 insertions(+), 22 deletions(-) create mode 100644 src/frontend/flask_app/static/vendor/VERSIONS.md create mode 100644 src/frontend/flask_app/static/vendor/alpinejs-3.15.12.min.js create mode 100644 src/frontend/flask_app/static/vendor/fabric-5.3.1.min.js create mode 100644 src/frontend/flask_app/static/vendor/fonts.css create mode 100644 src/frontend/flask_app/static/vendor/fonts/inter-latin-ext.woff2 create mode 100644 src/frontend/flask_app/static/vendor/fonts/inter-latin.woff2 create mode 100644 src/frontend/flask_app/static/vendor/fonts/jetbrains-mono-latin-ext.woff2 create mode 100644 src/frontend/flask_app/static/vendor/fonts/jetbrains-mono-latin.woff2 create mode 100644 src/frontend/flask_app/static/vendor/pdf-3.11.174.min.js create mode 100644 src/frontend/flask_app/static/vendor/pdf.worker-3.11.174.min.js create mode 100644 src/frontend/flask_app/static/vendor/plotly-2.32.0.min.js diff --git a/src/backend/api/middleware/security_headers.py b/src/backend/api/middleware/security_headers.py index f67720d..9f2ba44 100644 --- a/src/backend/api/middleware/security_headers.py +++ b/src/backend/api/middleware/security_headers.py @@ -10,16 +10,18 @@ from starlette.middleware.base import BaseHTTPMiddleware from src.backend.config import settings -# Content Security Policy - allows CDN resources used by the client +# Content Security Policy - same-origin only: every third-party library now ships with +# the app (see frontend static/vendor/), so no CDN host needs allowing. The install runs +# on an isolated shop-floor network where an outbound fetch would simply fail. # Note: 'unsafe-eval' required for Plotly.js runtime evaluation in SPC charts CSP = ( "default-src 'self'; " - "script-src 'self' 'unsafe-inline' 'unsafe-eval' " - "https://cdn.tailwindcss.com https://cdn.jsdelivr.net https://cdn.plot.ly; " - "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " - "font-src 'self' https://fonts.gstatic.com; " + "script-src 'self' 'unsafe-inline' 'unsafe-eval'; " + "style-src 'self' 'unsafe-inline'; " + "font-src 'self'; " "img-src 'self' data: blob:; " - "connect-src 'self'" + "connect-src 'self'; " + "worker-src 'self' blob:" ) diff --git a/src/frontend/flask_app/static/vendor/VERSIONS.md b/src/frontend/flask_app/static/vendor/VERSIONS.md new file mode 100644 index 0000000..3cea9dc --- /dev/null +++ b/src/frontend/flask_app/static/vendor/VERSIONS.md @@ -0,0 +1,77 @@ +# 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 `` 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 100–900, JetBrains Mono +400–800): 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`. + +## Aggiornare una libreria + +1. Scaricare la nuova versione con il nome comprensivo di versione. +2. Ripuntare i ` + + diff --git a/src/frontend/flask_app/templates/maker/recipe_preview.html b/src/frontend/flask_app/templates/maker/recipe_preview.html index 17a86ee..5562e15 100644 --- a/src/frontend/flask_app/templates/maker/recipe_preview.html +++ b/src/frontend/flask_app/templates/maker/recipe_preview.html @@ -432,9 +432,9 @@ {% endblock %} {% block extra_js %} - + - + + - + + + diff --git a/src/frontend/flask_app/templates/statistics/dashboard.html b/src/frontend/flask_app/templates/statistics/dashboard.html index f591e7a..6b25177 100644 --- a/src/frontend/flask_app/templates/statistics/dashboard.html +++ b/src/frontend/flask_app/templates/statistics/dashboard.html @@ -4,7 +4,7 @@ {% block extra_head %} - + {% endblock %} {% block content %}