- Tutti i riferimenti nis2.certisource.it → nis2.agile.software - Apache vhost HTTP nis2.agile.software attivo su Hetzner - Script setup-nis2-agile-software.sh: certbot SSL + redirect da vecchio dominio - .env server: APP_URL aggiornato a https://nis2.agile.software - CLAUDE.md, docs commerciali, integrazioni, API docs aggiornati DNS da aggiungere in Cloudflare: nis2.agile.software A 135.181.149.254 (proxy OFF) Poi eseguire: bash /opt/devenv/scripts/setup-nis2-agile-software.sh Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
661 lines
26 KiB
HTML
661 lines
26 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="it">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>NIS2 Agile — Scheda Tecnica</title>
|
||
<style>
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
body {
|
||
font-family: 'Segoe UI', Arial, sans-serif;
|
||
background: #f8faff;
|
||
color: #1a1a2e;
|
||
font-size: 12.5px;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.page {
|
||
width: 210mm;
|
||
margin: 0 auto;
|
||
background: #fff;
|
||
}
|
||
|
||
/* ── Header ── */
|
||
.header {
|
||
background: #0d2137;
|
||
padding: 24px 36px 20px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
}
|
||
.header-left h1 { font-size: 18px; font-weight: 800; color: #fff; margin-bottom: 4px; }
|
||
.header-left p { font-size: 10px; color: #7ea8c4; text-transform: uppercase; letter-spacing: 1px; }
|
||
.header-right {
|
||
text-align: right;
|
||
}
|
||
.version-badge {
|
||
display: inline-block;
|
||
background: #1a73e8;
|
||
color: #fff;
|
||
font-size: 9px;
|
||
font-weight: 700;
|
||
padding: 4px 10px;
|
||
border-radius: 4px;
|
||
margin-bottom: 4px;
|
||
}
|
||
.header-right p { font-size: 9px; color: #7ea8c4; }
|
||
|
||
/* ── Content ── */
|
||
.content { padding: 0 36px 24px; }
|
||
|
||
/* ── Section ── */
|
||
.section { margin-top: 22px; }
|
||
.section-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
margin-bottom: 12px;
|
||
padding-bottom: 6px;
|
||
border-bottom: 2px solid #e0eaff;
|
||
}
|
||
.section-num {
|
||
width: 22px; height: 22px;
|
||
background: #1a73e8;
|
||
color: #fff;
|
||
border-radius: 5px;
|
||
display: flex; align-items: center; justify-content: center;
|
||
font-size: 11px;
|
||
font-weight: 800;
|
||
flex-shrink: 0;
|
||
}
|
||
.section-title {
|
||
font-size: 12px;
|
||
font-weight: 800;
|
||
color: #0d2137;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.8px;
|
||
}
|
||
|
||
/* ── Stack grid ── */
|
||
.stack-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 10px;
|
||
}
|
||
.stack-item {
|
||
background: #f8faff;
|
||
border: 1px solid #e0eaff;
|
||
border-radius: 6px;
|
||
padding: 10px 14px;
|
||
display: flex;
|
||
gap: 10px;
|
||
align-items: flex-start;
|
||
}
|
||
.stack-label {
|
||
font-size: 9px;
|
||
font-weight: 800;
|
||
color: #1a73e8;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
min-width: 80px;
|
||
flex-shrink: 0;
|
||
padding-top: 1px;
|
||
}
|
||
.stack-value {
|
||
font-size: 11px;
|
||
color: #374151;
|
||
line-height: 1.5;
|
||
}
|
||
.stack-value strong { color: #0d2137; font-weight: 700; }
|
||
|
||
/* ── Architettura ── */
|
||
.arch-diagram {
|
||
background: #f8faff;
|
||
border: 1px solid #e0eaff;
|
||
border-radius: 8px;
|
||
padding: 16px;
|
||
font-size: 11px;
|
||
}
|
||
.arch-layers {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
.arch-layer {
|
||
display: flex;
|
||
gap: 8px;
|
||
align-items: center;
|
||
}
|
||
.arch-layer-label {
|
||
font-size: 8.5px;
|
||
font-weight: 800;
|
||
color: #6b7280;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
min-width: 68px;
|
||
text-align: right;
|
||
}
|
||
.arch-layer-boxes {
|
||
display: flex;
|
||
gap: 6px;
|
||
flex-wrap: wrap;
|
||
}
|
||
.arch-box {
|
||
background: #1a73e8;
|
||
color: #fff;
|
||
font-size: 9.5px;
|
||
font-weight: 600;
|
||
padding: 4px 10px;
|
||
border-radius: 4px;
|
||
white-space: nowrap;
|
||
}
|
||
.arch-box.alt { background: #0d47a1; }
|
||
.arch-box.gray { background: #4b5563; }
|
||
.arch-box.green { background: #059669; }
|
||
.arch-box.purple { background: #7c3aed; }
|
||
.arch-arrow {
|
||
font-size: 16px;
|
||
color: #9ca3af;
|
||
text-align: center;
|
||
padding-left: 68px;
|
||
margin: -4px 0;
|
||
}
|
||
|
||
/* ── API table ── */
|
||
.api-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
font-size: 10.5px;
|
||
}
|
||
.api-table th {
|
||
background: #0d2137;
|
||
color: #fff;
|
||
padding: 6px 10px;
|
||
font-size: 9px;
|
||
font-weight: 700;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
text-align: left;
|
||
}
|
||
.api-table td {
|
||
padding: 5px 10px;
|
||
border-bottom: 1px solid #e8edf3;
|
||
vertical-align: top;
|
||
}
|
||
.api-table tr:nth-child(even) td { background: #f8faff; }
|
||
.method {
|
||
display: inline-block;
|
||
font-size: 8.5px;
|
||
font-weight: 700;
|
||
padding: 1px 5px;
|
||
border-radius: 3px;
|
||
color: #fff;
|
||
}
|
||
.get { background: #059669; }
|
||
.post { background: #1a73e8; }
|
||
.put { background: #d97706; }
|
||
.del { background: #dc2626; }
|
||
|
||
/* ── DB table ── */
|
||
.db-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 6px;
|
||
}
|
||
.db-table-item {
|
||
background: #f8faff;
|
||
border: 1px solid #e0eaff;
|
||
border-radius: 5px;
|
||
padding: 7px 10px;
|
||
font-size: 10px;
|
||
}
|
||
.db-table-name { font-weight: 700; color: #0d2137; margin-bottom: 2px; }
|
||
.db-table-desc { font-size: 9px; color: #6b7280; }
|
||
|
||
/* ── Security ── */
|
||
.security-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 10px;
|
||
}
|
||
.sec-item {
|
||
background: #f0fdf4;
|
||
border: 1px solid #bbf7d0;
|
||
border-radius: 6px;
|
||
padding: 10px 12px;
|
||
}
|
||
.sec-item.warn { background: #fff7ed; border-color: #fed7aa; }
|
||
.sec-icon { font-size: 15px; margin-bottom: 4px; }
|
||
.sec-name { font-size: 10.5px; font-weight: 700; color: #14532d; margin-bottom: 3px; }
|
||
.sec-item.warn .sec-name { color: #92400e; }
|
||
.sec-desc { font-size: 9.5px; color: #166534; line-height: 1.5; }
|
||
.sec-item.warn .sec-desc { color: #78350f; }
|
||
|
||
/* ── Performance ── */
|
||
.perf-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
gap: 10px;
|
||
}
|
||
.perf-item {
|
||
background: #f8faff;
|
||
border: 1px solid #e0eaff;
|
||
border-radius: 6px;
|
||
padding: 10px;
|
||
text-align: center;
|
||
}
|
||
.perf-num { font-size: 18px; font-weight: 800; color: #1a73e8; }
|
||
.perf-unit { font-size: 9px; color: #6b7280; }
|
||
.perf-label { font-size: 9px; color: #4b5563; margin-top: 3px; }
|
||
|
||
/* ── Deploy ── */
|
||
.deploy-options {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 10px;
|
||
}
|
||
.deploy-card {
|
||
border: 1px solid #e0eaff;
|
||
border-radius: 6px;
|
||
padding: 12px;
|
||
}
|
||
.deploy-type {
|
||
font-size: 10px;
|
||
font-weight: 800;
|
||
color: #0d47a1;
|
||
margin-bottom: 6px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
.deploy-specs { list-style: none; }
|
||
.deploy-specs li {
|
||
font-size: 9.5px;
|
||
color: #4b5563;
|
||
padding: 1px 0 1px 12px;
|
||
position: relative;
|
||
}
|
||
.deploy-specs li::before {
|
||
content: '✓';
|
||
position: absolute;
|
||
left: 0;
|
||
color: #1a73e8;
|
||
font-size: 8px;
|
||
top: 2px;
|
||
}
|
||
|
||
/* ── Compliance map ── */
|
||
.compliance-map {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 8px;
|
||
}
|
||
.cm-item {
|
||
display: flex;
|
||
gap: 8px;
|
||
align-items: center;
|
||
background: #f8faff;
|
||
border: 1px solid #e0eaff;
|
||
border-radius: 5px;
|
||
padding: 7px 10px;
|
||
}
|
||
.cm-art {
|
||
font-size: 9px;
|
||
font-weight: 800;
|
||
color: #fff;
|
||
background: #1a73e8;
|
||
padding: 2px 6px;
|
||
border-radius: 4px;
|
||
white-space: nowrap;
|
||
}
|
||
.cm-desc { font-size: 10px; color: #374151; }
|
||
|
||
/* ── Footer ── */
|
||
.footer {
|
||
background: #0d2137;
|
||
padding: 12px 36px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-top: 20px;
|
||
}
|
||
.footer-left { font-size: 10px; color: #7ea8c4; }
|
||
.footer-left strong { color: #fff; font-size: 12px; }
|
||
.footer-right { font-size: 9px; color: #7ea8c4; text-align: right; }
|
||
|
||
@media print {
|
||
body { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
||
.page { width: 100%; margin: 0; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="page">
|
||
|
||
<!-- HEADER -->
|
||
<div class="header">
|
||
<div class="header-left">
|
||
<h1>NIS2 Agile — Scheda Tecnica</h1>
|
||
<p>Specifiche di architettura, stack tecnologico e integrazione</p>
|
||
</div>
|
||
<div class="header-right">
|
||
<div class="version-badge">v1.0 — Febbraio 2026</div>
|
||
<p>nis2.agile.software</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="content">
|
||
|
||
<!-- 1. STACK TECNOLOGICO -->
|
||
<div class="section">
|
||
<div class="section-header">
|
||
<div class="section-num">1</div>
|
||
<div class="section-title">Stack Tecnologico</div>
|
||
</div>
|
||
<div class="stack-grid">
|
||
<div class="stack-item">
|
||
<div class="stack-label">Backend</div>
|
||
<div class="stack-value"><strong>PHP 8.4</strong> — vanilla, Front Controller pattern, zero dipendenze framework. Router personalizzato con pattern matching per URI gerarchici.</div>
|
||
</div>
|
||
<div class="stack-item">
|
||
<div class="stack-label">Database</div>
|
||
<div class="stack-value"><strong>MySQL 8.0</strong> — 22 tabelle, indici ottimizzati, soft delete, trigger immutabili su audit_log. PDO con prepared statements.</div>
|
||
</div>
|
||
<div class="stack-item">
|
||
<div class="stack-label">Frontend</div>
|
||
<div class="stack-value"><strong>HTML5 / CSS3 / JavaScript</strong> — vanilla, nessun framework JS. 17 pagine HTML + 3 admin. CSS custom ~1.600 righe. i18n IT/EN integrato.</div>
|
||
</div>
|
||
<div class="stack-item">
|
||
<div class="stack-label">Autenticazione</div>
|
||
<div class="stack-value"><strong>JWT HS256</strong> — access token 2h, refresh token 7d. Refresh atomico con SELECT FOR UPDATE. Idle timeout 30min con avviso.</div>
|
||
</div>
|
||
<div class="stack-item">
|
||
<div class="stack-label">AI Integration</div>
|
||
<div class="stack-value"><strong>Anthropic Claude</strong> — modello <em>claude-sonnet-4-5</em>. Prompt anonimizzati (no ragione sociale, no fatturato). 4 funzionalità AI.</div>
|
||
</div>
|
||
<div class="stack-item">
|
||
<div class="stack-label">Infrastruttura</div>
|
||
<div class="stack-value"><strong>Hetzner CPX31</strong> — Ubuntu, Apache 2.4, subdomain dedicato. Docker-ready (Dockerfile + nginx.conf inclusi).</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 2. ARCHITETTURA -->
|
||
<div class="section">
|
||
<div class="section-header">
|
||
<div class="section-num">2</div>
|
||
<div class="section-title">Architettura Sistema</div>
|
||
</div>
|
||
<div class="arch-diagram">
|
||
<div class="arch-layers">
|
||
<div class="arch-layer">
|
||
<div class="arch-layer-label">Browser</div>
|
||
<div class="arch-layer-boxes">
|
||
<span class="arch-box">HTML5 Pages</span>
|
||
<span class="arch-box alt">api.js Client</span>
|
||
<span class="arch-box alt">i18n.js IT/EN</span>
|
||
<span class="arch-box alt">common.js Utils</span>
|
||
<span class="arch-box alt">help.js</span>
|
||
</div>
|
||
</div>
|
||
<div class="arch-arrow">↓ HTTPS / JWT Bearer</div>
|
||
<div class="arch-layer">
|
||
<div class="arch-layer-label">Router</div>
|
||
<div class="arch-layer-boxes">
|
||
<span class="arch-box green">public/index.php — Front Controller</span>
|
||
<span class="arch-box gray">.htaccess Rewrite</span>
|
||
</div>
|
||
</div>
|
||
<div class="arch-arrow">↓ /api/{controller}/{action}/{id?}</div>
|
||
<div class="arch-layer">
|
||
<div class="arch-layer-label">Controllers</div>
|
||
<div class="arch-layer-boxes">
|
||
<span class="arch-box">Auth</span>
|
||
<span class="arch-box">Assessment</span>
|
||
<span class="arch-box">Risk</span>
|
||
<span class="arch-box">Incident</span>
|
||
<span class="arch-box">Policy</span>
|
||
<span class="arch-box">SupplyChain</span>
|
||
<span class="arch-box">Audit</span>
|
||
<span class="arch-box alt">+ 8 altri</span>
|
||
</div>
|
||
</div>
|
||
<div class="arch-arrow">↓ PDO / Services</div>
|
||
<div class="arch-layer">
|
||
<div class="arch-layer-label">Services</div>
|
||
<div class="arch-layer-boxes">
|
||
<span class="arch-box purple">AIService (Claude)</span>
|
||
<span class="arch-box gray">EmailService</span>
|
||
<span class="arch-box gray">ReportService</span>
|
||
<span class="arch-box gray">RateLimitService</span>
|
||
<span class="arch-box gray">VisuraService</span>
|
||
</div>
|
||
</div>
|
||
<div class="arch-arrow">↓ PDO Singleton</div>
|
||
<div class="arch-layer">
|
||
<div class="arch-layer-label">Database</div>
|
||
<div class="arch-layer-boxes">
|
||
<span class="arch-box green">MySQL 8.0 — nis2_agile_db — 22 tabelle</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 3. API ENDPOINTS -->
|
||
<div class="section">
|
||
<div class="section-header">
|
||
<div class="section-num">3</div>
|
||
<div class="section-title">API REST — Endpoint Principali</div>
|
||
</div>
|
||
<p style="font-size:10px;color:#6b7280;margin-bottom:8px;">Base URL: <code style="background:#f8faff;padding:1px 5px;border-radius:3px;font-size:10px;">https://nis2.agile.software/api/{controller}/{action}/{id?}</code> — Auth: Bearer JWT + X-Organization-Id header</p>
|
||
<table class="api-table">
|
||
<thead>
|
||
<tr>
|
||
<th style="width:16%">Modulo</th>
|
||
<th style="width:12%">Metodo</th>
|
||
<th style="width:35%">Endpoint</th>
|
||
<th>Descrizione</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>Auth</td><td><span class="method post">POST</span></td><td>/auth/login, /register, /refresh</td><td>Login, registrazione, rinnovo token JWT</td></tr>
|
||
<tr><td>Auth</td><td><span class="method get">GET</span></td><td>/auth/me</td><td>Dati utente autenticato e organizzazioni</td></tr>
|
||
<tr><td>Organizations</td><td><span class="method post">POST</span></td><td>/organizations/create, /classify</td><td>Crea org, classifica soggetto NIS2</td></tr>
|
||
<tr><td>Assessment</td><td><span class="method get">GET</span></td><td>/assessments/{id}/questions</td><td>80 domande gap analysis (10 categorie Art.21)</td></tr>
|
||
<tr><td>Assessment</td><td><span class="method post">POST</span></td><td>/assessments/{id}/ai-analyze</td><td>Analisi AI dei gap con raccomandazioni</td></tr>
|
||
<tr><td>Risks</td><td><span class="method get">GET</span></td><td>/risks/matrix</td><td>Matrice rischi 5×5 aggregata</td></tr>
|
||
<tr><td>Risks</td><td><span class="method post">POST</span></td><td>/risks/ai-suggest</td><td>Suggerimenti rischi AI per settore/asset</td></tr>
|
||
<tr><td>Incidents</td><td><span class="method post">POST</span></td><td>/incidents/{id}/early-warning</td><td>Early warning CSIRT entro 24h (Art.23)</td></tr>
|
||
<tr><td>Incidents</td><td><span class="method post">POST</span></td><td>/incidents/{id}/final-report</td><td>Report finale CSIRT entro 30gg (Art.23)</td></tr>
|
||
<tr><td>Policies</td><td><span class="method post">POST</span></td><td>/policies/ai-generate</td><td>Genera policy NIS2 con AI (per categoria)</td></tr>
|
||
<tr><td>Audit</td><td><span class="method get">GET</span></td><td>/audit/executive-report</td><td>Report esecutivo HTML stampabile</td></tr>
|
||
<tr><td>Audit</td><td><span class="method get">GET</span></td><td>/audit/export?type=risks</td><td>Export CSV (rischi/incidenti/controlli/asset)</td></tr>
|
||
<tr><td>NCR/CAPA</td><td><span class="method post">POST</span></td><td>/ncr/from-assessment</td><td>Genera NCR automatiche dai gap assessment</td></tr>
|
||
<tr><td>Onboarding</td><td><span class="method post">POST</span></td><td>/onboarding/upload-visura</td><td>Estrazione AI da PDF visura camerale</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- 4. DATABASE -->
|
||
<div class="section">
|
||
<div class="section-header">
|
||
<div class="section-num">4</div>
|
||
<div class="section-title">Schema Database — 22 Tabelle</div>
|
||
</div>
|
||
<div class="db-grid">
|
||
<div class="db-table-item"><div class="db-table-name">organizations</div><div class="db-table-desc">Tenant principale + classificazione NIS2</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">users</div><div class="db-table-desc">Utenti (7 ruoli, multi-org)</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">user_organizations</div><div class="db-table-desc">Mapping utente↔org + ruolo</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">refresh_tokens</div><div class="db-table-desc">Token refresh JWT indicizzati</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">assessments</div><div class="db-table-desc">Sessioni gap analysis</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">assessment_responses</div><div class="db-table-desc">Risposte singole domande</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">risks</div><div class="db-table-desc">Register rischi (soft delete)</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">risk_treatments</div><div class="db-table-desc">Piani di trattamento</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">incidents</div><div class="db-table-desc">Incidenti + flag significativo</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">incident_timeline</div><div class="db-table-desc">Aggiornamenti e notifiche</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">policies</div><div class="db-table-desc">Policy (soft delete, versioning)</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">suppliers</div><div class="db-table-desc">Fornitori catena approvv.</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">training_courses</div><div class="db-table-desc">Catalogo corsi formazione</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">training_assignments</div><div class="db-table-desc">Assegnazioni e completamenti</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">assets</div><div class="db-table-desc">Inventario ICT (4 tipi)</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">compliance_controls</div><div class="db-table-desc">Controlli NIS2 per org</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">evidence_files</div><div class="db-table-desc">Allegati e documenti audit</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">audit_logs</div><div class="db-table-desc">Log immutabili (trigger MySQL)</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">ai_interactions</div><div class="db-table-desc">Storico chiamate API AI</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">email_log</div><div class="db-table-desc">Log notifiche email CSIRT</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">non_conformities</div><div class="db-table-desc">NCR — Non Conformity Reports</div></div>
|
||
<div class="db-table-item"><div class="db-table-name">corrective_actions</div><div class="db-table-desc">CAPA — Azioni correttive</div></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 5. SICUREZZA -->
|
||
<div class="section">
|
||
<div class="section-header">
|
||
<div class="section-num">5</div>
|
||
<div class="section-title">Sicurezza Applicativa</div>
|
||
</div>
|
||
<div class="security-grid">
|
||
<div class="sec-item">
|
||
<div class="sec-name">JWT + Refresh Token Atomico</div>
|
||
<div class="sec-desc">Access token 2h, refresh 7d. Rinnovo con SELECT FOR UPDATE (no race conditions). Revoca token al logout.</div>
|
||
</div>
|
||
<div class="sec-item">
|
||
<div class="sec-name">CORS Configurato</div>
|
||
<div class="sec-desc">No wildcard. Origin verificata contro lista bianca configurabile. Header personalizzati sicuri.</div>
|
||
</div>
|
||
<div class="sec-item">
|
||
<div class="sec-name">Rate Limiting</div>
|
||
<div class="sec-desc">File-based per IP (proxy-aware, X-Forwarded-For). Login: 5/min, 20/h. Register: 3/10min. AI: 10/min.</div>
|
||
</div>
|
||
<div class="sec-item">
|
||
<div class="sec-name">SQL Injection Prevention</div>
|
||
<div class="sec-desc">PDO esclusivo con prepared statements. Nessuna concatenazione di query. Input validato lato server.</div>
|
||
</div>
|
||
<div class="sec-item">
|
||
<div class="sec-name">XSS Prevention</div>
|
||
<div class="sec-desc">escapeHtml() su ogni output frontend. Content-Security-Policy header configurato.</div>
|
||
</div>
|
||
<div class="sec-item">
|
||
<div class="sec-name">Audit Log Immutabile</div>
|
||
<div class="sec-desc">Trigger MySQL prevent_update + prevent_delete su audit_logs. Ogni operazione registrata con utente, azione e timestamp.</div>
|
||
</div>
|
||
<div class="sec-item">
|
||
<div class="sec-name">AI Data Privacy</div>
|
||
<div class="sec-desc">Prompt anonimizzati: ragione sociale e fatturato mai inviati ad Anthropic. Dipendenti convertiti in range (micro/piccola/media/grande).</div>
|
||
</div>
|
||
<div class="sec-item warn">
|
||
<div class="sec-name">Idle Session Timeout</div>
|
||
<div class="sec-desc">Logout automatico dopo 30 min di inattività. Avviso con countdown 5 min. Monitoraggio eventi mouse/keyboard/scroll.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 6. PERFORMANCE -->
|
||
<div class="section">
|
||
<div class="section-header">
|
||
<div class="section-num">6</div>
|
||
<div class="section-title">Performance Target</div>
|
||
</div>
|
||
<div class="perf-grid">
|
||
<div class="perf-item">
|
||
<div class="perf-num"><1s</div>
|
||
<div class="perf-unit">secondi</div>
|
||
<div class="perf-label">Caricamento Dashboard</div>
|
||
</div>
|
||
<div class="perf-item">
|
||
<div class="perf-num"><2s</div>
|
||
<div class="perf-unit">secondi</div>
|
||
<div class="perf-label">Report Compliance</div>
|
||
</div>
|
||
<div class="perf-item">
|
||
<div class="perf-num">100+</div>
|
||
<div class="perf-unit">rischi</div>
|
||
<div class="perf-label">Matrice Fluida</div>
|
||
</div>
|
||
<div class="perf-item">
|
||
<div class="perf-num">∞</div>
|
||
<div class="perf-unit">tenant</div>
|
||
<div class="perf-label">Multi-Tenant Isolati</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 7. DEPLOY -->
|
||
<div class="section">
|
||
<div class="section-header">
|
||
<div class="section-num">7</div>
|
||
<div class="section-title">Opzioni di Deploy</div>
|
||
</div>
|
||
<div class="deploy-options">
|
||
<div class="deploy-card">
|
||
<div class="deploy-type">Cloud SaaS</div>
|
||
<ul class="deploy-specs">
|
||
<li>Hosting su nis2.agile.software</li>
|
||
<li>Zero configurazione client</li>
|
||
<li>Aggiornamenti automatici</li>
|
||
<li>Backup giornaliero incluso</li>
|
||
<li>SSL/TLS incluso</li>
|
||
</ul>
|
||
</div>
|
||
<div class="deploy-card">
|
||
<div class="deploy-type">On-Premise / VPS</div>
|
||
<ul class="deploy-specs">
|
||
<li>PHP 8.4 + MySQL 8.0 + Apache/Nginx</li>
|
||
<li>Deploy via git pull + .env config</li>
|
||
<li>Supporto subdomain dedicato</li>
|
||
<li>Documentazione SQL migrations</li>
|
||
<li>Chiave SSH per accesso sicuro</li>
|
||
</ul>
|
||
</div>
|
||
<div class="deploy-card">
|
||
<div class="deploy-type">Docker / Container</div>
|
||
<ul class="deploy-specs">
|
||
<li>Dockerfile ottimizzato incluso</li>
|
||
<li>docker-compose.yml pronto</li>
|
||
<li>nginx.conf + php.ini configurati</li>
|
||
<li>Compatibile Kubernetes</li>
|
||
<li>Multi-stage build support</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 8. COMPLIANCE MAP -->
|
||
<div class="section">
|
||
<div class="section-header">
|
||
<div class="section-num">8</div>
|
||
<div class="section-title">Copertura Normativa NIS2</div>
|
||
</div>
|
||
<div class="compliance-map">
|
||
<div class="cm-item"><span class="cm-art">Art. 20</span><div class="cm-desc">Governance — Formazione obbligatoria management, responsabilità organi</div></div>
|
||
<div class="cm-item"><span class="cm-art">Art. 21.1</span><div class="cm-desc">Risk-based approach — Risk register, matrice rischi, trattamenti</div></div>
|
||
<div class="cm-item"><span class="cm-art">Art. 21.2(a)</span><div class="cm-desc">Politiche sicurezza — Gap analysis 80 domande, policy management</div></div>
|
||
<div class="cm-item"><span class="cm-art">Art. 21.2(b)</span><div class="cm-desc">Gestione incidenti — Ciclo di vita, classificazione AI, timeline</div></div>
|
||
<div class="cm-item"><span class="cm-art">Art. 21.2(c)</span><div class="cm-desc">Business continuity — Asset inventory, dipendenze, backup</div></div>
|
||
<div class="cm-item"><span class="cm-art">Art. 21.2(d)</span><div class="cm-desc">Supply chain — Registro fornitori, valutazione rischio, scoring</div></div>
|
||
<div class="cm-item"><span class="cm-art">Art. 21.2(g)</span><div class="cm-desc">Formazione — Training management, compliance tracking, report</div></div>
|
||
<div class="cm-item"><span class="cm-art">Art. 23</span><div class="cm-desc">Notifica incidenti — Early warning 24h, notifica 72h, report 30gg</div></div>
|
||
<div class="cm-item"><span class="cm-art">Art. 32-33</span><div class="cm-desc">Vigilanza — Audit log immutabili, evidenze, controlli compliance</div></div>
|
||
<div class="cm-item"><span class="cm-art">D.Lgs. 138/2024</span><div class="cm-desc">Recepimento italiano NIS2 — Classificazione soggetti, settori</div></div>
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- /content -->
|
||
|
||
<!-- FOOTER -->
|
||
<div class="footer">
|
||
<div class="footer-left">
|
||
<strong>NIS2 Agile</strong><br>
|
||
Piattaforma SaaS compliance NIS2 per PMI e Enterprise
|
||
</div>
|
||
<div class="footer-right">
|
||
nis2.agile.software<br>
|
||
Versione 1.0 · Febbraio 2026<br>
|
||
24.000+ righe di codice · 50+ file sorgente
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</body>
|
||
</html>
|