[DOCS] Rischi rework: help online + manuale + KB (matrice 4 fasce/toggle, trasversali 12 col)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
DevEnv nis2-agile
2026-08-03 10:44:58 +02:00
co-authored by Claude Opus 4.8
parent 4809d8e895
commit f421f4ecdb
38 changed files with 61 additions and 47 deletions
+18 -4
View File
@@ -78,11 +78,25 @@ Un requisito può essere **conforme** e avere comunque un **rischio residuo alto
sono due piani distinti. Questa scelta evita di far dire al sistema "sei conforme perché il rischio
è basso", che sarebbe normativamente scorretto.
## 6. La matrice 5×5
Ogni rischio con **inerente** valutato compare nella matrice 5×5 (sempre visibile), insieme ai rischi trasversali. La matrice è uno **strumento di rappresentazione**, non un obbligo (art. 24
D.Lgs. 138/2024). Esclude i requisiti "non applicabili".
## 6. Le matrici di rischio 5×5
Ci sono **due matrici**: una per i **rischi dai requisiti** (subito sotto la prima tabella) e una
per i **rischi trasversali** (in fondo). Ogni rischio valutato con Probabilità e Impatto compare
automaticamente nella propria matrice.
## 7. Chi può fare cosa
- **4 fasce di rischio** (dal prodotto Probabilità × Impatto): **1–2 basso** (verde), **3–8 medio**
(arancione), **9–12 alto** (rosso tenue), **15–25 critico** (rosso) — le stesse soglie della colonna Alert.
- Il tasto **Inerente / Residuo** sopra ogni matrice mostra i giudizi prima o dopo il trattamento.
- La matrice dei requisiti esclude i "non applicabili".
La matrice è uno **strumento di rappresentazione**, non un obbligo (art. 24 D.Lgs. 138/2024).
## 7. La sezione «Rischi trasversali» (in fondo alla pagina)
Comprimibile e riservata ai profili amministrativi. Ha le **stesse 12 colonne** dei rischi dai requisiti
(valutazione inerente e residua, Alert, Esito residuo). In testa ci sono i tasti **AI Suggerisci** e
**Nuovo Rischio**; ogni riga ha un tasto per **eliminare** il rischio; sotto la tabella c'è la sua
**matrice 5×5** con lo stesso tasto Inerente/Residuo.
## 8. Chi può fare cosa
- **Tutti** vedono la tabella e i valori.
- **Amministratore / Compliance Manager / super admin**: compilano Probabilità/Impatto (inerente e
residuo), creano azioni, aggiornano lo stato del requisito, aggiungono rischi all-hazard.
+2 -1
View File
@@ -29,7 +29,8 @@ I profili che valutano (super_admin/org_admin/compliance_manager) compilano Prob
- Rischio **inerente** = rischio di non conformità **prima** del trattamento; **residuo** = **dopo** il trattamento (framing coerente con "rischio di non conformità"). "Inerente/residuo" è impostazione **ISO 27005 / ISO 27001 §6.1.3** (accettazione del rischio residuo dal risk owner): **best practice**, non obbligo NIS2.
- Le **soglie** dell'Alert e il metodo P×I sono una **scelta metodologica** dell'organizzazione (rif. ISO/IEC 27001 §6.1.2), **strumento di rappresentazione, NON obbligo**: l'**art. 24 del D.Lgs. 138/2024** richiede un'analisi dei rischi proporzionata e con approccio **multirischio (all-hazard)**, senza imporre una metodologia specifica.
- **Impatto** è una scala di severità 1-5 (non euro). La matrice 5×5 (sempre visibile) esclude i requisiti "non applicabili".
- **Impatto** è una scala di severità 1-5 (non euro).
- **Matrici 5×5**: ce ne sono **due** — una per i rischi dai requisiti (sotto la prima tabella) e una per i rischi trasversali (in fondo). Le celle hanno **4 fasce** (prodotto P×I): 1-2 basso (verde), 3-8 medio (arancione), 9-12 alto (rosso tenue), 15-25 critico (rosso) — stesse soglie dell'Alert. Un **tasto Inerente/Residuo** mostra i giudizi prima o dopo il trattamento. La matrice dei requisiti esclude i "non applicabili". È uno strumento di rappresentazione, non un obbligo (metodo interno, ISO 27001 §6.1.2).
- Dall'Alert si possono creare **azioni** sul rischio (seme del futuro Modulo Azioni: registro azioni, audit, KPI, budget).
## Rischi trasversali (all-hazards) — sezione comprimibile
+1 -1
View File
@@ -167,7 +167,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// ── Auth check ───────────────────────────────────────────
if (!checkAuth()) throw new Error('Not authenticated');
+1 -1
View File
@@ -90,7 +90,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// ── Auth check ───────────────────────────────────────────
if (!checkAuth()) throw new Error('Not authenticated');
+1 -1
View File
@@ -97,7 +97,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// ── Auth check ───────────────────────────────────────────
if (!checkAuth()) throw new Error('Not authenticated');
+1 -1
View File
@@ -1127,7 +1127,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
if (!checkAuth()) throw new Error('Not authenticated');
loadSidebar(); // = loadTopnavV3()
+1 -1
View File
@@ -275,7 +275,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// ── Auth check ───────────────────────────────────────────
if (!checkAuth()) throw new Error('Not authenticated');
+1 -1
View File
@@ -382,7 +382,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// ── Auth & Init ─────────────────────────────────────────
if (!checkAuth()) throw new Error('Not authenticated');
+1 -1
View File
@@ -195,7 +195,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
'use strict';
/*
+1 -1
View File
@@ -202,7 +202,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
if (!checkAuth()) throw new Error('Not authenticated');
+1 -1
View File
@@ -197,7 +197,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script src="/js/competenze.js?v=20260627"></script>
<script>
function v3Icons() { if (window.lucide && lucide.createIcons) { try { lucide.createIcons(); } catch (e) {} } }
+1 -1
View File
@@ -103,7 +103,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script src="/js/connettori-discovery.js?v=20260627"></script>
<script>
if (typeof checkAuth === 'function' && !checkAuth()) {
+1 -1
View File
@@ -160,7 +160,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
'use strict';
/* Controlli periodici (control monitoring §9.1/A.8.16): controlli ricorrenti + esecuzioni (evidenza) + NC/AC. */
+1 -1
View File
@@ -227,7 +227,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// ── Icone inline (Lucide stroke) usate nelle stringhe HTML generate dal JS.
// Renderizzate immediatamente (no createIcons re-run), self-host, niente sprite BI. ──
+1 -1
View File
@@ -117,7 +117,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script src="/js/dashboard.js?v=20260724a"></script>
<script>
// ── Auth check ───────────────────────────────────────────
+1 -1
View File
@@ -1182,7 +1182,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// La guida è accessibile anche da non autenticati (utile per onboarding)
// ma se sei loggato carichi chrome + i18n normalmente. ZERO modifiche backend.
+1 -1
View File
@@ -364,7 +364,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// ── Auth & Init ──────────────────────────────────────────────
if (!checkAuth()) throw new Error('Not authenticated');
+1 -1
View File
@@ -936,7 +936,7 @@ curl -H <span class="str">"X-API-Key: nis2_TUA_CHIAVE"</span> \
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
if (!checkAuth()) throw new Error('Not authenticated');
loadSidebar(); // = loadTopnavV3()
+1 -1
View File
@@ -165,7 +165,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
'use strict';
/*
+1 -1
View File
@@ -204,7 +204,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script src="/js/isms.js?v=20260627v3"></script>
<script>
// Icone Lucide della chrome + crumb/page-head statici. L'init dati e il wiring
+6 -7
View File
@@ -611,18 +611,17 @@ const HelpSystem = (function () {
'La colonna <strong>Alert</strong> compare in base al punteggio inerente: <em>Azione Prioritaria</em> (15–25), <em>Azione Critica</em> (9–12), <em>Azione Necessaria</em> (3–8), <em>Azione Suggerita</em> (1–2). Le soglie sono una <strong>scelta metodologica</strong> dell\'organizzazione (rif. ISO/IEC 27001 §6.1.2), <strong>non un obbligo di legge</strong>. Cliccando l\'Alert si apre l\'elenco delle azioni passate su quel rischio e si può <strong>creare una nuova azione</strong>.',
'La colonna <strong>Esito residuo</strong> segnala se il rischio residuo va <strong>rivalutato</strong> (punteggio 9–25) o è <strong>adeguato</strong> (1–8). <strong>Importante</strong>: il punteggio di rischio residuo <strong>non</strong> determina automaticamente lo <em>stato di conformità</em> del requisito. La <strong>conformità</strong> dipende dall\'attuazione della misura e dalle evidenze e si aggiorna in modo esplicito dal link "stato" nella colonna Rischio Residuo. Sono due piani distinti (punteggio di rischio ≠ conformità al requisito).',
'La tabella elenca <strong>solo i requisiti applicabili alla tua classe</strong> (importante &rarr; Allegato 1, essenziale &rarr; Allegato 2 della Determinazione ACN 164179/2025). Se l\'elenco e\' lungo, il riquadro <strong>scorre verticalmente</strong> con l\'intestazione fissa.',
'La seconda sezione, <strong>Rischi trasversali (approccio multirischio / all-hazards)</strong> — comprimibile, riservata ai <strong>profili amministrativi</strong> — serve a registrare le minacce non riconducibili a un singolo requisito (ambiente fisico, catena di fornitura, eventi naturali, errore umano): copre l\'approccio multirischio richiesto dall\'art. 24 D.Lgs. 138/2024 (che recepisce l\'art. 21 §2 della Direttiva (UE) 2022/2555). Si distingue dai «rischi di non conformità» derivati dai requisiti. La sezione resta sempre presente: se è vuota si apre da sola.'
'In <strong>fondo alla pagina</strong> trovi la sezione <strong>Rischi trasversali (approccio multirischio / all-hazards)</strong> — comprimibile, riservata ai <strong>profili amministrativi</strong> — per registrare le minacce non riconducibili a un singolo requisito (ambiente fisico, catena di fornitura, eventi naturali, errore umano): copre l\'approccio multirischio richiesto dall\'art. 24 D.Lgs. 138/2024 (che recepisce l\'art. 21 §2 della Direttiva (UE) 2022/2555). Si distingue dai «rischi di non conformità» derivati dai requisiti.',
'La tabella dei <strong>Rischi trasversali</strong> ha le <strong>stesse 12 colonne</strong> dei rischi dai requisiti (valutazione inerente e residua, Alert, Esito residuo). In testa alla tabella ci sono i tasti <strong>AI Suggerisci</strong> e <strong>Nuovo Rischio</strong>; ogni riga ha un tasto per <strong>eliminare</strong> il rischio. Sotto la tabella c\'è una <strong>seconda matrice 5×5</strong> dedicata ai soli rischi trasversali, con lo stesso tasto Inerente/Residuo.'
]
},
{
heading: 'Matrice di Rischio',
items: [
'La matrice 5×5 e\' uno <strong>strumento di rappresentazione</strong>, non un obbligo normativo: l\'art. 24 D.Lgs. 138/2024 richiede un\'analisi dei rischi proporzionata e con approccio multirischio, senza imporre una metodologia specifica.',
'Ogni rischio-da-requisito <strong>valutato con Probabilità e Impatto</strong> compare automaticamente nella matrice 5×5, insieme ai <strong>rischi aggiuntivi</strong> (custom): la matrice rappresenta così <strong>tutti i rischi</strong>. La matrice <strong>esclude i requisiti "non applicabili"</strong> (per classe o marcati tali).',
'La <strong>matrice Probabilita\' x Impatto</strong> (5x5) classifica automaticamente i rischi in base alla loro gravita\'.',
'I livelli di probabilita\' vanno da <em>Molto Bassa</em> a <em>Molto Alta</em>.',
'I livelli di impatto vanno da <em>Trascurabile</em> a <em>Critico</em>.',
'Il punteggio di rischio risultante determina il colore e la priorita\' del rischio.'
'La matrice 5×5 (Probabilità × Impatto) e\' uno <strong>strumento di rappresentazione</strong>, non un obbligo normativo: l\'art. 24 D.Lgs. 138/2024 richiede un\'analisi dei rischi proporzionata e con approccio multirischio, senza imporre una metodologia specifica.',
'Le celle hanno <strong>4 fasce di rischio</strong> (dal prodotto Probabilità × Impatto): <strong>1–2 basso</strong> (verde), <strong>3–8 medio</strong> (arancione), <strong>9–12 alto</strong> (rosso tenue), <strong>15–25 critico</strong> (rosso). Sono le stesse soglie della colonna Alert; una <strong>scelta metodologica</strong> dell\'organizzazione (ISO/IEC 27001 §6.1.2), <strong>non un obbligo di legge</strong>.',
'Il tasto <strong>Inerente / Residuo</strong> sopra la matrice mostra i giudizi <strong>prima</strong> o <strong>dopo</strong> il trattamento.',
'Ci sono <strong>due matrici</strong>: una per i <strong>rischi dai requisiti</strong> (subito sotto la prima tabella) e una per i <strong>rischi trasversali</strong> (in fondo). La matrice dei requisiti <strong>esclude i "non applicabili"</strong> (per classe o marcati tali).'
]
},
{
+1 -1
View File
@@ -180,7 +180,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script src="/js/kb.js"></script>
<script>
// Gate auth + chrome come le altre pagine V3.
+1 -1
View File
@@ -152,7 +152,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
'use strict';
/*
+1 -1
View File
@@ -180,7 +180,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
'use strict';
/*
+1 -1
View File
@@ -142,7 +142,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// ── Auth + chrome + i18n + help ──────────────────────────
if (!checkAuth()) throw new Error('Not authenticated');
+1 -1
View File
@@ -156,7 +156,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script src="/js/organigramma.js?v=20260627"></script>
<script>
// Render icone Lucide (chrome + crumb + bottoni). organigramma.js fa render albero
+1 -1
View File
@@ -345,7 +345,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// ── Auth & Init ─────────────────────────────────────────
if (!checkAuth()) throw new Error('Not authenticated');
+1 -1
View File
@@ -146,7 +146,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script src="/js/raci.js?v=20260627"></script>
<script>
function v3Icons() { if (window.lucide && lucide.createIcons) { try { lucide.createIcons(); } catch (e) {} } }
+1 -1
View File
@@ -237,7 +237,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// ── Auth & Init ─────────────────────────────────────────
if (!checkAuth()) throw new Error('Not authenticated');
+1 -1
View File
@@ -162,7 +162,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
'use strict';
/*
+1 -1
View File
@@ -612,7 +612,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// ── Auth & Init ──────────────────────────────────────────────
if (!checkAuth()) throw new Error('Not authenticated');
+1 -1
View File
@@ -740,7 +740,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// ── Auth check ───────────────────────────────────────────
if (!checkAuth()) throw new Error('Not authenticated');
+1 -1
View File
@@ -220,7 +220,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
'use strict';
/*
+1 -1
View File
@@ -215,7 +215,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
'use strict';
/*
+1 -1
View File
@@ -547,7 +547,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// ── Auth & Init ─────────────────────────────────────────
if (!checkAuth()) throw new Error('Not authenticated');
+1 -1
View File
@@ -195,7 +195,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// ── Auth & Init (ordine V3) ─────────────────────────────
if (!checkAuth()) throw new Error('Not authenticated');
+1 -1
View File
@@ -263,7 +263,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
if (!checkAuth()) throw new Error('Not authenticated');
loadSidebar();
+1 -1
View File
@@ -148,7 +148,7 @@
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260729"></script>
<script src="/js/i18n.js?v=20260731"></script>
<script src="/js/help.js?v=20260731"></script>
<script src="/js/help.js?v=20260801"></script>
<script>
// ── Auth + chrome + i18n + help ──────────────────────────────
if (!checkAuth()) throw new Error('Not authenticated');