# 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`. 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 `