[DOCS] Pagina documentazione Testing & Simulazione
Pagina HTML standalone che descrive: - Test Runner (L1-L6, SSE streaming, token auth, comandi speciali) - Simulazione Demo (6 scenari SIM-01→06, 3 aziende, architettura) - Worker Feedback AI (cron, flow, configurazione) - URL di accesso, credenziali, reset dati demo Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
fc4fbda732
commit
ca8f077a7a
789
public/docs/testing-simulazione.html
Normal file
789
public/docs/testing-simulazione.html
Normal file
@ -0,0 +1,789 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="it">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>NIS2 Agile — Sistema di Testing & Simulazione</title>
|
||||
<style>
|
||||
:root {
|
||||
--primary: #06b6d4;
|
||||
--green: #22c55e;
|
||||
--red: #ef4444;
|
||||
--yellow: #f59e0b;
|
||||
--purple: #8b5cf6;
|
||||
--orange: #f97316;
|
||||
--dark: #0f172a;
|
||||
--card: #1e293b;
|
||||
--border: #334155;
|
||||
--text: #e2e8f0;
|
||||
--muted: #94a3b8;
|
||||
}
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
background: var(--dark);
|
||||
color: var(--text);
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* ── Header ── */
|
||||
.header {
|
||||
background: linear-gradient(135deg, #0c4a6e 0%, #0e7490 100%);
|
||||
padding: 48px;
|
||||
border-bottom: 1px solid #0e7490;
|
||||
}
|
||||
.header-inner { max-width: 1100px; margin: 0 auto; }
|
||||
.header h1 { font-size: 2rem; font-weight: 800; color: #fff; margin-bottom: 8px; }
|
||||
.header p { color: #7dd3fc; font-size: 1rem; max-width: 640px; }
|
||||
.badge-row { margin-top: 20px; display: flex; flex-wrap: wrap; gap: 8px; }
|
||||
.badge {
|
||||
display: inline-block; padding: 4px 14px; border-radius: 20px;
|
||||
font-size: 0.75rem; font-weight: 700;
|
||||
}
|
||||
.badge-cyan { background: rgba(6,182,212,.2); color: #67e8f9; border: 1px solid rgba(6,182,212,.3); }
|
||||
.badge-green { background: rgba(34,197,94,.2); color: #86efac; border: 1px solid rgba(34,197,94,.3); }
|
||||
.badge-purple { background: rgba(139,92,246,.2); color: #c4b5fd; border: 1px solid rgba(139,92,246,.3); }
|
||||
|
||||
/* ── Nav ── */
|
||||
.nav {
|
||||
background: #1e293b;
|
||||
border-bottom: 1px solid var(--border);
|
||||
position: sticky; top: 0; z-index: 100;
|
||||
}
|
||||
.nav-inner {
|
||||
max-width: 1100px; margin: 0 auto;
|
||||
display: flex; gap: 0; overflow-x: auto;
|
||||
}
|
||||
.nav a {
|
||||
padding: 14px 20px; font-size: 0.875rem; font-weight: 600;
|
||||
color: var(--muted); text-decoration: none; white-space: nowrap;
|
||||
border-bottom: 2px solid transparent; transition: all .2s;
|
||||
}
|
||||
.nav a:hover { color: var(--text); background: rgba(255,255,255,.03); }
|
||||
.nav a.active { color: var(--primary); border-bottom-color: var(--primary); }
|
||||
|
||||
/* ── Layout ── */
|
||||
.main { max-width: 1100px; margin: 0 auto; padding: 48px 24px; }
|
||||
section { margin-bottom: 64px; }
|
||||
h2 {
|
||||
font-size: 1.375rem; font-weight: 800; color: #fff;
|
||||
margin-bottom: 24px; padding-bottom: 12px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
}
|
||||
h2 .icon { font-size: 1.25rem; }
|
||||
h3 { font-size: 1rem; font-weight: 700; color: #cbd5e1; margin-bottom: 12px; margin-top: 28px; }
|
||||
p { color: #94a3b8; margin-bottom: 12px; }
|
||||
|
||||
/* ── Cards ── */
|
||||
.card {
|
||||
background: var(--card); border: 1px solid var(--border);
|
||||
border-radius: 12px; padding: 24px; margin-bottom: 16px;
|
||||
}
|
||||
.card-title { font-size: 0.9375rem; font-weight: 700; color: #fff; margin-bottom: 6px; }
|
||||
.card p { margin-bottom: 0; }
|
||||
|
||||
/* ── Grid ── */
|
||||
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
|
||||
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
|
||||
@media (max-width: 768px) {
|
||||
.grid-2, .grid-3 { grid-template-columns: 1fr; }
|
||||
.header { padding: 32px 24px; }
|
||||
.header h1 { font-size: 1.5rem; }
|
||||
}
|
||||
|
||||
/* ── Level badges ── */
|
||||
.level-badge {
|
||||
display: inline-block; padding: 2px 10px; border-radius: 6px;
|
||||
font-size: 0.7rem; font-weight: 800; font-family: monospace;
|
||||
margin-right: 8px; vertical-align: middle;
|
||||
}
|
||||
.lv-l1 { background: rgba(6,182,212,.15); color: #67e8f9; border: 1px solid rgba(6,182,212,.3); }
|
||||
.lv-l2 { background: rgba(139,92,246,.15); color: #c4b5fd; border: 1px solid rgba(139,92,246,.3); }
|
||||
.lv-l3 { background: rgba(34,197,94,.15); color: #86efac; border: 1px solid rgba(34,197,94,.3); }
|
||||
.lv-l4 { background: rgba(249,115,22,.15); color: #fdba74; border: 1px solid rgba(249,115,22,.3); }
|
||||
.lv-l5 { background: rgba(245,158,11,.15); color: #fcd34d; border: 1px solid rgba(245,158,11,.3); }
|
||||
.lv-l6 { background: rgba(236,72,153,.15); color: #f9a8d4; border: 1px solid rgba(236,72,153,.3); }
|
||||
.lv-sim { background: rgba(239,68,68,.15); color: #fca5a5; border: 1px solid rgba(239,68,68,.3); }
|
||||
.lv-infra { background: rgba(148,163,184,.15); color: #cbd5e1; border: 1px solid rgba(148,163,184,.3); }
|
||||
|
||||
/* ── Test table ── */
|
||||
.test-table { width: 100%; border-collapse: collapse; font-size: 0.875rem; }
|
||||
.test-table th {
|
||||
text-align: left; padding: 10px 14px; font-size: 0.75rem; font-weight: 700;
|
||||
color: var(--muted); text-transform: uppercase; letter-spacing: .05em;
|
||||
border-bottom: 1px solid var(--border); background: rgba(255,255,255,.02);
|
||||
}
|
||||
.test-table td { padding: 10px 14px; border-bottom: 1px solid rgba(51,65,85,.5); color: #cbd5e1; }
|
||||
.test-table tr:last-child td { border-bottom: none; }
|
||||
.test-table tr:hover td { background: rgba(255,255,255,.02); }
|
||||
|
||||
/* ── Scenario cards ── */
|
||||
.sim-card {
|
||||
background: var(--card); border: 1px solid var(--border);
|
||||
border-radius: 10px; padding: 20px; position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.sim-card::before {
|
||||
content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
|
||||
}
|
||||
.sim-card.cyan::before { background: linear-gradient(90deg, #06b6d4, #0891b2); }
|
||||
.sim-card.orange::before { background: linear-gradient(90deg, #f97316, #ea580c); }
|
||||
.sim-card.red::before { background: linear-gradient(90deg, #ef4444, #dc2626); }
|
||||
.sim-card.purple::before { background: linear-gradient(90deg, #8b5cf6, #7c3aed); }
|
||||
.sim-card.green::before { background: linear-gradient(90deg, #22c55e, #16a34a); }
|
||||
.sim-card.yellow::before { background: linear-gradient(90deg, #f59e0b, #d97706); }
|
||||
.sim-num { font-size: 0.7rem; font-weight: 800; color: var(--muted); margin-bottom: 6px; font-family: monospace; }
|
||||
.sim-title { font-size: 0.9375rem; font-weight: 700; color: #fff; margin-bottom: 6px; }
|
||||
.sim-desc { font-size: 0.8125rem; color: var(--muted); line-height: 1.5; }
|
||||
.sim-steps { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
|
||||
.sim-step { font-size: 0.75rem; color: #64748b; display: flex; gap: 8px; margin-bottom: 4px; }
|
||||
.sim-step span { color: #94a3b8; }
|
||||
|
||||
/* ── Company pills ── */
|
||||
.company-pill {
|
||||
display: inline-flex; align-items: center; gap: 6px;
|
||||
padding: 4px 12px; border-radius: 20px; font-size: 0.75rem; font-weight: 600;
|
||||
border: 1px solid var(--border); background: rgba(255,255,255,.04);
|
||||
margin: 3px;
|
||||
}
|
||||
.dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
|
||||
|
||||
/* ── Code block ── */
|
||||
.code-block {
|
||||
background: #0f172a; border: 1px solid var(--border);
|
||||
border-radius: 8px; padding: 16px 20px; font-family: 'Fira Code', 'Cascadia Code', monospace;
|
||||
font-size: 0.8125rem; color: #93c5fd; overflow-x: auto;
|
||||
margin: 12px 0;
|
||||
}
|
||||
.code-block .comment { color: #475569; }
|
||||
.code-block .keyword { color: #67e8f9; }
|
||||
.code-block .string { color: #86efac; }
|
||||
.code-block .url { color: #fcd34d; }
|
||||
|
||||
/* ── Alert ── */
|
||||
.alert {
|
||||
padding: 14px 18px; border-radius: 8px; font-size: 0.875rem;
|
||||
display: flex; gap: 12px; align-items: flex-start; margin-bottom: 16px;
|
||||
}
|
||||
.alert-info { background: rgba(6,182,212,.08); border: 1px solid rgba(6,182,212,.2); color: #7dd3fc; }
|
||||
.alert-warning { background: rgba(245,158,11,.08); border: 1px solid rgba(245,158,11,.2); color: #fcd34d; }
|
||||
.alert-success { background: rgba(34,197,94,.08); border: 1px solid rgba(34,197,94,.2); color: #86efac; }
|
||||
|
||||
/* ── URL button ── */
|
||||
.url-btn {
|
||||
display: inline-flex; align-items: center; gap: 8px;
|
||||
background: rgba(6,182,212,.1); border: 1px solid rgba(6,182,212,.3);
|
||||
color: #67e8f9; padding: 10px 18px; border-radius: 8px;
|
||||
text-decoration: none; font-size: 0.875rem; font-weight: 600;
|
||||
transition: all .2s; margin-right: 8px; margin-bottom: 8px;
|
||||
}
|
||||
.url-btn:hover { background: rgba(6,182,212,.2); border-color: #06b6d4; }
|
||||
.url-btn-red {
|
||||
background: rgba(239,68,68,.1); border-color: rgba(239,68,68,.3); color: #fca5a5;
|
||||
}
|
||||
.url-btn-red:hover { background: rgba(239,68,68,.2); }
|
||||
|
||||
/* ── Stats strip ── */
|
||||
.stats-strip { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 24px; }
|
||||
.stat-box {
|
||||
background: var(--card); border: 1px solid var(--border);
|
||||
border-radius: 10px; padding: 16px 24px; text-align: center; flex: 1; min-width: 100px;
|
||||
}
|
||||
.stat-num { font-size: 2rem; font-weight: 800; }
|
||||
.stat-lbl { font-size: 0.75rem; color: var(--muted); margin-top: 2px; }
|
||||
|
||||
/* ── Worker box ── */
|
||||
.worker-flow {
|
||||
display: flex; align-items: center; flex-wrap: wrap; gap: 0;
|
||||
background: #0f172a; border: 1px solid var(--border);
|
||||
border-radius: 10px; overflow: hidden; margin: 16px 0;
|
||||
}
|
||||
.wf-step {
|
||||
padding: 14px 18px; font-size: 0.8125rem; flex: 1; min-width: 120px;
|
||||
text-align: center; border-right: 1px solid var(--border);
|
||||
}
|
||||
.wf-step:last-child { border-right: none; }
|
||||
.wf-step .wf-icon { font-size: 1.25rem; display: block; margin-bottom: 4px; }
|
||||
.wf-step .wf-label { color: #cbd5e1; font-weight: 600; }
|
||||
.wf-step .wf-sub { color: var(--muted); font-size: 0.725rem; margin-top: 2px; }
|
||||
|
||||
/* ── Credentials box ── */
|
||||
.creds-box {
|
||||
background: #0f172a; border: 1px solid var(--border);
|
||||
border-radius: 8px; overflow: hidden;
|
||||
}
|
||||
.creds-row {
|
||||
display: flex; gap: 0; border-bottom: 1px solid rgba(51,65,85,.5);
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
.creds-row:last-child { border-bottom: none; }
|
||||
.creds-key {
|
||||
padding: 10px 16px; width: 200px; flex-shrink: 0;
|
||||
color: var(--muted); font-weight: 600; border-right: 1px solid rgba(51,65,85,.5);
|
||||
font-family: monospace; font-size: 0.75rem;
|
||||
}
|
||||
.creds-val {
|
||||
padding: 10px 16px; color: #93c5fd; font-family: monospace; font-size: 0.75rem;
|
||||
}
|
||||
|
||||
/* ── Footer ── */
|
||||
footer {
|
||||
background: #1e293b; border-top: 1px solid var(--border);
|
||||
padding: 32px 48px; text-align: center; color: var(--muted); font-size: 0.875rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- ── Header ── -->
|
||||
<div class="header">
|
||||
<div class="header-inner">
|
||||
<div style="font-size:.8rem;color:#7dd3fc;margin-bottom:8px;font-weight:600;">
|
||||
NIS2 Agile — Documentazione Tecnica
|
||||
</div>
|
||||
<h1>Sistema di Testing & Simulazione</h1>
|
||||
<p>Due strumenti integrati per verificare la correttezza della piattaforma e dimostrare scenari reali NIS2 in ambienti demo.</p>
|
||||
<div class="badge-row">
|
||||
<span class="badge badge-cyan">Test Runner v2 — 36+ test</span>
|
||||
<span class="badge badge-green">Simulazione — 6 scenari</span>
|
||||
<span class="badge badge-purple">3 aziende demo</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Nav ── -->
|
||||
<nav class="nav">
|
||||
<div class="nav-inner">
|
||||
<a href="#panoramica" class="active">Panoramica</a>
|
||||
<a href="#test-runner">Test Runner</a>
|
||||
<a href="#simulazione">Simulazione</a>
|
||||
<a href="#aziende-demo">Aziende Demo</a>
|
||||
<a href="#worker">Worker Feedback</a>
|
||||
<a href="#accesso">Accesso & URL</a>
|
||||
<a href="#credenziali">Credenziali</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="main">
|
||||
|
||||
<!-- ── Panoramica ── -->
|
||||
<section id="panoramica">
|
||||
<h2><span class="icon">🧭</span> Panoramica</h2>
|
||||
|
||||
<p>NIS2 Agile dispone di due strumenti distinti ma complementari per la verifica della qualità e la dimostrazione delle funzionalità:</p>
|
||||
|
||||
<div class="grid-2">
|
||||
<div class="card" style="border-color:rgba(6,182,212,.3);">
|
||||
<div class="card-title" style="color:#67e8f9;">🧪 Test Runner</div>
|
||||
<p>Suite di test automatizzati a 6 livelli che verifica ogni endpoint API con asserzioni precise. Accesso protetto da token, output streaming in tempo reale, reset dati integrato.</p>
|
||||
<div style="margin-top:12px;">
|
||||
<a href="https://nis2.agile.software/test-runner.php?t=Nis2Test2026" target="_blank" class="url-btn">Apri Test Runner →</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" style="border-color:rgba(34,197,94,.3);">
|
||||
<div class="card-title" style="color:#86efac;">🎬 Simulazione Demo</div>
|
||||
<p>Costruisce dati realistici attraverso le API reali (nessun INSERT SQL diretto) simulando 3 aziende con settori e complessità diversi su 6 scenari NIS2 reali.</p>
|
||||
<div style="margin-top:12px;">
|
||||
<a href="https://nis2.agile.software/simulate.html" target="_blank" class="url-btn">Apri Simulatore →</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info">
|
||||
<span>ℹ️</span>
|
||||
<div>I due sistemi sono progettati per lavorare in sequenza: prima si esegue la <strong>simulazione</strong> per creare i dati demo, poi il <strong>test runner</strong> per verificare che tutto funzioni correttamente. Il pulsante "Reset + Simula + Testa Tutto" li esegue entrambi in automatico.</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── Test Runner ── -->
|
||||
<section id="test-runner">
|
||||
<h2><span class="icon">🧪</span> Test Runner</h2>
|
||||
|
||||
<p>Il Test Runner è un'applicazione PHP (<code>public/test-runner.php</code>) che espone una UI web dark-theme con streaming SSE dei risultati in tempo reale. I test sono organizzati in <strong>6 livelli funzionali</strong> più un livello infrastrutturale.</p>
|
||||
|
||||
<div class="stats-strip">
|
||||
<div class="stat-box"><div class="stat-num" style="color:#67e8f9;">36+</div><div class="stat-lbl">Test totali</div></div>
|
||||
<div class="stat-box"><div class="stat-num" style="color:#86efac;">6</div><div class="stat-lbl">Livelli</div></div>
|
||||
<div class="stat-box"><div class="stat-num" style="color:#c4b5fd;">SSE</div><div class="stat-lbl">Output streaming</div></div>
|
||||
<div class="stat-box"><div class="stat-num" style="color:#fcd34d;">JWT</div><div class="stat-lbl">Auth token-based</div></div>
|
||||
</div>
|
||||
|
||||
<h3>Livelli di Test</h3>
|
||||
<div class="card" style="padding:0; overflow:hidden;">
|
||||
<table class="test-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Livello</th>
|
||||
<th>Nome</th>
|
||||
<th>Cosa verifica</th>
|
||||
<th>Dipendenze</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><span class="level-badge lv-infra">INFRA</span></td>
|
||||
<td>Health & Smoke</td>
|
||||
<td>API status, endpoint rapidi, connettività DB</td>
|
||||
<td>—</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="level-badge lv-l1">L1</span></td>
|
||||
<td>Auth & JWT</td>
|
||||
<td>Login, register, JWT access/refresh, change-password, rate limiting</td>
|
||||
<td>—</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="level-badge lv-l2">L2</span></td>
|
||||
<td>Multi-Tenant Isolation</td>
|
||||
<td>Isolamento dati tra organizzazioni diverse, cross-org protection</td>
|
||||
<td>SIM-01</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="level-badge lv-l3">L3</span></td>
|
||||
<td>Compliance Core</td>
|
||||
<td>Assessment, rischi, incidenti, policy, supply chain, asset, training, NCR/CAPA</td>
|
||||
<td>SIM-01</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="level-badge lv-l4">L4</span></td>
|
||||
<td>B2B & Services API</td>
|
||||
<td>X-API-Key auth, scopes (read:all, admin:licenses), invite lifecycle, webhook delivery</td>
|
||||
<td>SIM-01, SIM-06</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="level-badge lv-l5">L5</span></td>
|
||||
<td>Export & Reports</td>
|
||||
<td>CSV export (rischi/incidenti/asset/controlli), report HTML, audit executive</td>
|
||||
<td>SIM-01</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="level-badge lv-l6">L6</span></td>
|
||||
<td>AI Features</td>
|
||||
<td>Cross-org portfolio analysis, AI classify incident, AI suggest risk, normative feed</td>
|
||||
<td>SIM-01, consultant user</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="level-badge lv-sim">SIM</span></td>
|
||||
<td>Simulazioni</td>
|
||||
<td>Esecuzione completa SIM-01→06 con output dettagliato</td>
|
||||
<td>Demo users nel DB</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h3>Accesso e autenticazione</h3>
|
||||
<p>Il Test Runner è protetto da un token di sessione configurato come costante PHP:</p>
|
||||
<div class="code-block">
|
||||
<span class="comment">// Primo accesso — passa il token come query string</span>
|
||||
<span class="url">https://nis2.agile.software/test-runner.php?t=Nis2Test2026</span>
|
||||
|
||||
<span class="comment">// Sessioni successive — il token è memorizzato in $_SESSION</span>
|
||||
<span class="url">https://nis2.agile.software/test-runner.php</span>
|
||||
</div>
|
||||
|
||||
<h3>Output streaming (SSE)</h3>
|
||||
<p>I test vengono eseguiti come comandi bash su server. I risultati vengono trasmessi in tempo reale tramite <strong>Server-Sent Events</strong> al browser. Ogni test mostra:</p>
|
||||
<div class="grid-2">
|
||||
<div class="card"><div class="card-title" style="color:#86efac;">✓ PASS</div><p>Il comando ha restituito exit code 0 e l'output atteso.</p></div>
|
||||
<div class="card"><div class="card-title" style="color:#fca5a5;">✗ FAIL</div><p>Il comando ha restituito errore o output non corrispondente.</p></div>
|
||||
<div class="card"><div class="card-title" style="color:#fcd34d;">⚠ SKIP</div><p>Dipendenza mancante (utente demo non creato, SIM non eseguita).</p></div>
|
||||
<div class="card"><div class="card-title" style="color:#f97316;">⚡ WARN</div><p>Il test è passato ma con avvertimenti non bloccanti.</p></div>
|
||||
</div>
|
||||
|
||||
<h3>Comandi speciali</h3>
|
||||
<div class="card">
|
||||
<table class="test-table">
|
||||
<thead><tr><th>Comando</th><th>Funzione</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><span class="level-badge lv-infra">Verifica Hash Chain</span></td><td>Esegue <code>simulate-nis2.php --sim=SIM05</code> per verificare integrità SHA-256 del audit trail</td></tr>
|
||||
<tr><td><span class="level-badge lv-infra">Reset Dati Demo</span></td><td>Esegue <code>reset-demo.sql</code> — cancella org/utenti con id>4 e email <code>%.demo%</code></td></tr>
|
||||
<tr><td><span class="level-badge lv-infra">Full Suite L1→L6</span></td><td>Esegue tutti i 6 livelli in sequenza, con output cumulativo</td></tr>
|
||||
<tr><td><span class="level-badge lv-infra">Reset + Simula + Testa</span></td><td>Pipeline completa: reset → SIM-01→06 → Full Suite L1→L6</td></tr>
|
||||
<tr><td><span class="level-badge lv-infra">DB Stats</span></td><td>Conta record per tabella via endpoint JSON</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── Simulazione ── -->
|
||||
<section id="simulazione">
|
||||
<h2><span class="icon">🎬</span> Sistema di Simulazione</h2>
|
||||
|
||||
<p>Il simulatore (<code>simulate-nis2.php</code>) costruisce dati demo realistici <em>esclusivamente attraverso le API REST</em>, come farebbe un utente reale. Nessun INSERT SQL diretto: ogni operazione testa sia la logica di business che la persistenza dati.</p>
|
||||
|
||||
<div class="alert alert-warning">
|
||||
<span>⚠️</span>
|
||||
<div><strong>Idempotenza:</strong> se un'organizzazione demo esiste già (stessa P.IVA), lo step viene saltato silenziosamente (<code>SKIP idempotent</code>) senza errore. Per ripartire da zero usare prima il <strong>Reset Dati Demo</strong>.</div>
|
||||
</div>
|
||||
|
||||
<h3>Utilizzo</h3>
|
||||
<div class="code-block">
|
||||
<span class="comment"># Via browser (SSE streaming con UI dark-theme)</span>
|
||||
<span class="url">https://nis2.agile.software/simulate.html</span>
|
||||
|
||||
<span class="comment"># Via CLI sul server</span>
|
||||
<span class="keyword">php</span> simulate-nis2.php <span class="comment"># tutti gli scenari</span>
|
||||
<span class="keyword">php</span> simulate-nis2.php --sim=SIM02 <span class="comment"># solo SIM-02</span>
|
||||
<span class="keyword">php</span> simulate-nis2.php --sim=SIM06 <span class="comment"># solo B2B (indipendente)</span>
|
||||
|
||||
<span class="comment"># Variabili d'ambiente opzionali</span>
|
||||
<span class="keyword">NIS2_SIM</span>=SIM06 <span class="keyword">php</span> simulate-nis2.php <span class="comment"># alias env per --sim</span>
|
||||
<span class="keyword">NIS2_API_BASE</span>=https://... <span class="keyword">php</span> simulate-nis2.php <span class="comment"># override URL API</span>
|
||||
<span class="keyword">NIS2_DEMO_EMAIL</span>=test@... <span class="keyword">php</span> simulate-nis2.php <span class="comment"># redirect email demo</span>
|
||||
</div>
|
||||
|
||||
<h3>I 6 Scenari</h3>
|
||||
<div class="grid-2">
|
||||
|
||||
<div class="sim-card cyan">
|
||||
<div class="sim-num">SIM-01</div>
|
||||
<div class="sim-title">Onboarding + Gap Assessment</div>
|
||||
<div class="sim-desc">Registra 3 aziende, completa l'onboarding multi-step, esegue il gap assessment completo con tutte le 80 domande Art.21 NIS2 per ogni organizzazione.</div>
|
||||
<div class="sim-steps">
|
||||
<div class="sim-step">→ <span>Registrazione + email welcome</span></div>
|
||||
<div class="sim-step">→ <span>Setup org (settore, dipendenti, entity type)</span></div>
|
||||
<div class="sim-step">→ <span>80 domande × 3 aziende (categorizzate per Art.21)</span></div>
|
||||
<div class="sim-step">→ <span>Completamento assessment + score compliance</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sim-card orange">
|
||||
<div class="sim-num">SIM-02</div>
|
||||
<div class="sim-title">Incidente Ransomware Art.23</div>
|
||||
<div class="sim-desc">Simula un attacco ransomware critico su DataCore S.r.l. con attivazione della timeline obbligatoria NIS2 (early warning 24h, notification 72h, final report 30d).</div>
|
||||
<div class="sim-steps">
|
||||
<div class="sim-step">→ <span>Creazione incidente severity=critical</span></div>
|
||||
<div class="sim-step">→ <span>AI classify: categoria, suggerimenti, severity</span></div>
|
||||
<div class="sim-step">→ <span>Early warning CSIRT (24h)</span></div>
|
||||
<div class="sim-step">→ <span>Notification formale (72h) + final report (30d)</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sim-card red">
|
||||
<div class="sim-num">SIM-03</div>
|
||||
<div class="sim-title">Data Breach Supply Chain</div>
|
||||
<div class="sim-desc">Fornitore IT di MedClinic compromesso: aggiunta fornitore critico, assessment sicurezza, attivazione incidente Art.23 parallelo con gestione supply chain.</div>
|
||||
<div class="sim-steps">
|
||||
<div class="sim-step">→ <span>Aggiunta fornitore risk=critical</span></div>
|
||||
<div class="sim-step">→ <span>Security assessment fornitore</span></div>
|
||||
<div class="sim-step">→ <span>Data breach incident con AI classification</span></div>
|
||||
<div class="sim-step">→ <span>Risk register aggiornato automaticamente</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sim-card purple">
|
||||
<div class="sim-num">SIM-04</div>
|
||||
<div class="sim-title">Whistleblowing Anonimo SCADA</div>
|
||||
<div class="sim-desc">Segnalazione anonima Art.32 NIS2 per accesso non autorizzato ai sistemi SCADA di EnerNet. Assegnazione investigatore, tracciamento timeline, chiusura con esito.</div>
|
||||
<div class="sim-steps">
|
||||
<div class="sim-step">→ <span>Submit anonimo (no auth, solo token tracking)</span></div>
|
||||
<div class="sim-step">→ <span>Assegnazione a compliance manager</span></div>
|
||||
<div class="sim-step">→ <span>Timeline investigazione (3 eventi)</span></div>
|
||||
<div class="sim-step">→ <span>Chiusura con esito e verifica tracking anonimo</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sim-card green">
|
||||
<div class="sim-num">SIM-05</div>
|
||||
<div class="sim-title">Audit Trail Hash Chain</div>
|
||||
<div class="sim-desc">Verifica l'integrità della catena SHA-256 dell'audit trail per tutte e 3 le organizzazioni. Rileva eventuali record manomessi e genera export certificato.</div>
|
||||
<div class="sim-steps">
|
||||
<div class="sim-step">→ <span>Fetch audit log con prev_hash + entry_hash</span></div>
|
||||
<div class="sim-step">→ <span>Verifica catena SHA-256 record per record</span></div>
|
||||
<div class="sim-step">→ <span>Report integrità: verified/tampered/gaps</span></div>
|
||||
<div class="sim-step">→ <span>Export certificato JSON (con hash contenuto)</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sim-card yellow">
|
||||
<div class="sim-num">SIM-06</div>
|
||||
<div class="sim-title">B2B License Provisioning</div>
|
||||
<div class="sim-desc">Provisioning automatico di una nuova organizzazione tramite invite token B2B. SSO federato, token exchange, creazione org + utente + API key in un'unica chiamata.</div>
|
||||
<div class="sim-steps">
|
||||
<div class="sim-step">→ <span>Creazione invite token (admin:licenses)</span></div>
|
||||
<div class="sim-step">→ <span>POST /api/services/provision con X-Provision-Secret</span></div>
|
||||
<div class="sim-step">→ <span>Org + user + api_key creati atomicamente</span></div>
|
||||
<div class="sim-step">→ <span>Verifica scadenza licenza + SSO JWT exchange</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Architettura del simulatore</h3>
|
||||
<p>Il simulatore mantiene uno <strong>stato globale</strong> <code>$S</code> durante l'esecuzione per tracciare JWT, org IDs e statistiche:</p>
|
||||
<div class="code-block">
|
||||
<span class="comment">// Stato globale simulazione (in-memory per sessione)</span>
|
||||
$S = [
|
||||
<span class="string">'jwt'</span> => [], <span class="comment">// ['email' => token]</span>
|
||||
<span class="string">'orgs'</span> => [], <span class="comment">// ['slug' => ['id', 'name', 'jwt']]</span>
|
||||
<span class="string">'users'</span> => [], <span class="comment">// ['email' => ['id', 'jwt']]</span>
|
||||
<span class="string">'stats'</span> => [<span class="string">'pass'</span> => 0, <span class="string">'skip'</span> => 0, <span class="string">'fail'</span> => 0, <span class="string">'warn'</span> => 0],
|
||||
];
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── Aziende Demo ── -->
|
||||
<section id="aziende-demo">
|
||||
<h2><span class="icon">🏢</span> Aziende Demo</h2>
|
||||
|
||||
<p>Le simulazioni creano 3 organizzazioni demo con caratteristiche diversificate per coprire i principali settori NIS2 e i diversi livelli di obblighi normativi:</p>
|
||||
|
||||
<div class="grid-3">
|
||||
<div class="card" style="border-color:rgba(6,182,212,.3);">
|
||||
<div style="display:flex;align-items:center;gap:10px;margin-bottom:12px;">
|
||||
<div class="dot" style="background:#06b6d4;width:12px;height:12px;"></div>
|
||||
<div class="card-title" style="color:#67e8f9;">DataCore S.r.l.</div>
|
||||
</div>
|
||||
<div style="font-size:0.8rem;color:#94a3b8;line-height:1.8;">
|
||||
<div><strong style="color:#cbd5e1;">Settore:</strong> IT / Cloud & Data Center</div>
|
||||
<div><strong style="color:#cbd5e1;">Tipo:</strong> Essential Entity</div>
|
||||
<div><strong style="color:#cbd5e1;">Dipendenti:</strong> 320</div>
|
||||
<div><strong style="color:#cbd5e1;">Sede:</strong> Milano</div>
|
||||
<div><strong style="color:#cbd5e1;">Scenari:</strong> SIM-01, SIM-02 (Ransomware)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" style="border-color:rgba(139,92,246,.3);">
|
||||
<div style="display:flex;align-items:center;gap:10px;margin-bottom:12px;">
|
||||
<div class="dot" style="background:#8b5cf6;width:12px;height:12px;"></div>
|
||||
<div class="card-title" style="color:#c4b5fd;">MedClinic Italia S.p.A.</div>
|
||||
</div>
|
||||
<div style="font-size:0.8rem;color:#94a3b8;line-height:1.8;">
|
||||
<div><strong style="color:#cbd5e1;">Settore:</strong> Sanità</div>
|
||||
<div><strong style="color:#cbd5e1;">Tipo:</strong> Important Entity</div>
|
||||
<div><strong style="color:#cbd5e1;">Dipendenti:</strong> 750</div>
|
||||
<div><strong style="color:#cbd5e1;">Sede:</strong> Roma</div>
|
||||
<div><strong style="color:#cbd5e1;">Scenari:</strong> SIM-01, SIM-03 (Supply Chain)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" style="border-color:rgba(34,197,94,.3);">
|
||||
<div style="display:flex;align-items:center;gap:10px;margin-bottom:12px;">
|
||||
<div class="dot" style="background:#22c55e;width:12px;height:12px;"></div>
|
||||
<div class="card-title" style="color:#86efac;">EnerNet Distribuzione S.r.l.</div>
|
||||
</div>
|
||||
<div style="font-size:0.8rem;color:#94a3b8;line-height:1.8;">
|
||||
<div><strong style="color:#cbd5e1;">Settore:</strong> Energia</div>
|
||||
<div><strong style="color:#cbd5e1;">Tipo:</strong> Essential / Critical</div>
|
||||
<div><strong style="color:#cbd5e1;">Dipendenti:</strong> 1.800</div>
|
||||
<div><strong style="color:#cbd5e1;">Sede:</strong> Torino</div>
|
||||
<div><strong style="color:#cbd5e1;">Scenari:</strong> SIM-01, SIM-04 (SCADA)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-success">
|
||||
<span>✅</span>
|
||||
<div>Tutti gli utenti demo usano la password <strong>NIS2Demo2026!</strong>. Le email vengono reindirizzate all'indirizzo configurato in <code>NIS2_DEMO_EMAIL</code> (default: <code>demo@nis2agile.it</code>).</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── Worker Feedback ── -->
|
||||
<section id="worker">
|
||||
<h2><span class="icon">🤖</span> Worker Feedback AI</h2>
|
||||
|
||||
<p>Oltre ai test e alle simulazioni, la piattaforma include un <strong>worker autonomo</strong> per la risoluzione automatica delle segnalazioni utente tramite Claude AI.</p>
|
||||
|
||||
<div class="worker-flow">
|
||||
<div class="wf-step">
|
||||
<span class="wf-icon">🕐</span>
|
||||
<div class="wf-label">Ogni 30 min</div>
|
||||
<div class="wf-sub">cron root</div>
|
||||
</div>
|
||||
<div class="wf-step">
|
||||
<span class="wf-icon">🔍</span>
|
||||
<div class="wf-label">Fetch ticket</div>
|
||||
<div class="wf-sub">status=in_lavorazione</div>
|
||||
</div>
|
||||
<div class="wf-step">
|
||||
<span class="wf-icon">🤖</span>
|
||||
<div class="wf-label">Claude Code CLI</div>
|
||||
<div class="wf-sub">docker exec nis2-agile-devenv</div>
|
||||
</div>
|
||||
<div class="wf-step">
|
||||
<span class="wf-icon">✅</span>
|
||||
<div class="wf-label">POST /resolve</div>
|
||||
<div class="wf-sub">con password gate</div>
|
||||
</div>
|
||||
<div class="wf-step">
|
||||
<span class="wf-icon">📧</span>
|
||||
<div class="wf-label">Email broadcast</div>
|
||||
<div class="wf-sub">tutti i membri org</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Configurazione</h3>
|
||||
<div class="creds-box">
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">Script</div>
|
||||
<div class="creds-val">scripts/feedback-worker.php</div>
|
||||
</div>
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">Crontab</div>
|
||||
<div class="creds-val">*/30 * * * * /usr/bin/php8.4 /var/www/nis2-agile/scripts/feedback-worker.php</div>
|
||||
</div>
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">Log</div>
|
||||
<div class="creds-val">/var/log/nis2/feedback-worker.log</div>
|
||||
</div>
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">Account worker</div>
|
||||
<div class="creds-val">worker@nis2.agile.software (super_admin, dedicato)</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Test del worker</h3>
|
||||
<div class="code-block">
|
||||
<span class="comment"># Run manuale (Hetzner SSH)</span>
|
||||
<span class="keyword">php8.4</span> /var/www/nis2-agile/scripts/feedback-worker.php
|
||||
|
||||
<span class="comment"># Verifica log</span>
|
||||
<span class="keyword">tail</span> -f /var/log/nis2/feedback-worker.log
|
||||
|
||||
<span class="comment"># Output atteso (nessun ticket)</span>
|
||||
[2026-03-10 09:16:27] === Feedback Worker avviato ===
|
||||
[2026-03-10 09:16:27] Nessun ticket in lavorazione. Worker terminato.
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── Accesso ── -->
|
||||
<section id="accesso">
|
||||
<h2><span class="icon">🔗</span> URL di Accesso</h2>
|
||||
|
||||
<div class="grid-2">
|
||||
<div>
|
||||
<h3>Produzione</h3>
|
||||
<a href="https://nis2.agile.software/simulate.html" target="_blank" class="url-btn">
|
||||
🎬 Simulatore Demo
|
||||
</a>
|
||||
<a href="https://nis2.agile.software/test-runner.php?t=Nis2Test2026" target="_blank" class="url-btn">
|
||||
🧪 Test Runner
|
||||
</a>
|
||||
<a href="https://nis2.agile.software/api-status.php" target="_blank" class="url-btn">
|
||||
❤️ Health Check
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<h3>DevEnv (container locale)</h3>
|
||||
<a href="https://certisource.it/dev-nis2-api/" target="_blank" class="url-btn">
|
||||
🔧 Dev API
|
||||
</a>
|
||||
<a href="https://certisource.it/dev-nis2-ide/" target="_blank" class="url-btn">
|
||||
💻 Dev IDE
|
||||
</a>
|
||||
<a href="https://certisource.it/dev-nis2-browser/" target="_blank" class="url-btn">
|
||||
🌐 Dev Browser
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Reset dati demo</h3>
|
||||
<div class="alert alert-warning">
|
||||
<span>⚠️</span>
|
||||
<div>Il reset cancella tutte le organizzazioni e gli utenti con <code>id > 4</code> e email che contengono <code>.demo</code>. Le 4 org base e i super admin vengono preservati.</div>
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<span class="comment"># Via Test Runner UI → tasto "Reset Dati Demo"</span>
|
||||
<span class="comment"># Via SSH (Hetzner)</span>
|
||||
<span class="keyword">mysql</span> -u nis2_user -p nis2_agile_db < /var/www/nis2-agile/docs/sql/reset-demo.sql
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── Credenziali ── -->
|
||||
<section id="credenziali">
|
||||
<h2><span class="icon">🔑</span> Credenziali</h2>
|
||||
|
||||
<h3>Test Runner</h3>
|
||||
<div class="creds-box">
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">Token accesso</div>
|
||||
<div class="creds-val">Nis2Test2026</div>
|
||||
</div>
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">URL</div>
|
||||
<div class="creds-val">https://nis2.agile.software/test-runner.php?t=Nis2Test2026</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Utenti demo (creati da SIM-01)</h3>
|
||||
<div class="creds-box">
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">Password comune</div>
|
||||
<div class="creds-val">NIS2Demo2026!</div>
|
||||
</div>
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">DataCore admin</div>
|
||||
<div class="creds-val">admin@datacore-srl.demo</div>
|
||||
</div>
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">MedClinic admin</div>
|
||||
<div class="creds-val">admin@medclinic.demo</div>
|
||||
</div>
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">EnerNet admin</div>
|
||||
<div class="creds-val">admin@enernet.demo</div>
|
||||
</div>
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">Consultant</div>
|
||||
<div class="creds-val">consultant@nis2agile.demo</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>API Key demo (DataCore — read:all)</h3>
|
||||
<div class="creds-box">
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">Chiave</div>
|
||||
<div class="creds-val">nis2_152c1d87f8e6613d18a0510fd907c082</div>
|
||||
</div>
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">Scope</div>
|
||||
<div class="creds-val">read:all</div>
|
||||
</div>
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">Header</div>
|
||||
<div class="creds-val">X-API-Key: nis2_152c1d87f8e6613d18a0510fd907c082</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Sistema Feedback</h3>
|
||||
<div class="creds-box">
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">Password resolve</div>
|
||||
<div class="creds-val">Nis2Feedback2026!</div>
|
||||
</div>
|
||||
<div class="creds-row">
|
||||
<div class="creds-key">Worker account</div>
|
||||
<div class="creds-val">worker@nis2.agile.software</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning" style="margin-top:24px;">
|
||||
<span>🔒</span>
|
||||
<div>Queste credenziali sono per uso esclusivo in ambiente di test/demo. Non usarle in produzione reale. La pagina non è indicizzata dai motori di ricerca.</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
NIS2 Agile — Documentazione Testing & Simulazione · Aggiornata 2026-03-10 ·
|
||||
<a href="https://nis2.agile.software/" style="color:var(--primary);">nis2.agile.software</a>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
// Highlight nav link on scroll
|
||||
const sections = document.querySelectorAll('section[id]');
|
||||
const navLinks = document.querySelectorAll('.nav a');
|
||||
const observer = new IntersectionObserver(entries => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
navLinks.forEach(a => a.classList.remove('active'));
|
||||
const active = document.querySelector(`.nav a[href="#${entry.target.id}"]`);
|
||||
if (active) active.classList.add('active');
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.3 });
|
||||
sections.forEach(s => observer.observe(s));
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue
Block a user