nis2-agile/docs/nis2/INTEGRAZIONE_COMPLETATA.md
DevEnv nis2-agile 5c545ea3d0 [FEAT] Integrazione analisi docs/nis2 v1.7.0 — scoring asset, tassonomia incidenti, PIR, NIST CSF, fonti certe
Fase 1 - Asset Relevance Scoring NIS2 (GV.OC-04): metodologia 0-100 a 6 criteri,
  AssetScoringService + endpoint scoringGrid/score/relevantSystems + UI assets.html + registro stampabile.
Fase 2 - Tassonomia incidenti Determina ACN 164179/2025: IS-1..4 + regime essenziale/importante (Allegati 3/4).
Fase 3 - Post-Incident Review (5-Whys) + metriche TTD/TTC/TTR + timestamp di fase.
Fase 4 - Mapping NIST CSF 2.0 (43 controlli) reference-only.
Fonti certe: registry config/nis2_sources.php + grounding AI (vieta riferimenti inventati) +
  citazioni help.js + ingest PDF normativi nella KB RAG (scripts/ingest-nis2-sources.php).
Migrazioni 020/021/022 (additive idempotenti). Fix VectorService IP Qdrant (drift .5->.3).
Analisi concorrenza Evix (docs/EVIX_ANALISI_CONCORRENZA.html, gap-driven).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 17:15:13 +02:00

89 lines
6.4 KiB
Markdown

# Integrazione analisi `docs/nis2/` → NIS2 Agile
> Data: 2026-05-29 (CEST) · Versione: v1.7.0 · Stato: **✅ DEPLOYATO ED ESEGUITO IN PRODUZIONE (Hetzner)**
## ✅ Eseguito in produzione (2026-05-29 ~17:06 CEST)
- **Codice**: live su `/var/www/nis2-agile` (stesso filesystem del container dev via bind mount → nessuno scp necessario). 5 nuovi endpoint verificati live (HTTP 401 auth, routing OK).
- **Migrazioni DB 020/021/022**: applicate e verificate (colonne assets/incidents + tabella `incident_pir` create).
- **Ingest KB**: **287 chunk** normativi indicizzati in Qdrant `nis2_kb` scope SYSTEM (171 NIS2 + 77 CER + 25 Det.333017 + 9 Det.164179 + 5 Ambiti). Retrieval verificato (query "preallarme CSIRT" → Direttiva NIS2; "settori alta criticità" → Ambiti Allegati I/II).
- **Backup**: `/root/backup_pre_v170_20260529_165447.sql`.
### ⚠️ Azione consigliata residua (richiede conferma — recreate container)
**Qdrant IP drift**: il container `nis2-qdrant` non ha IP statico in `docker-compose.yml` ed è driftato da `172.21.0.5``172.21.0.3`. Fallback in `VectorService.php` aggiornato a `.3` (live). Per evitare ricorrenze: in `docker/docker-compose.yml` assegnare `ipv4_address` statico al servizio `qdrant` e allineare `QDRANT_URL`, poi `docker compose up -d --force-recreate qdrant app`. NB: nota anche che `kb_uploaded_documents` non esiste su questo DB (migrazioni KB 012-014 non applicate qui) → il tracking MySQL dei doc KB è saltato (best-effort), ma la ricerca RAG legge da Qdrant e funziona.
---
Integrazione del materiale di analisi (mockup HTML + testi normativi PDF) nel prodotto NIS2 Agile.
Tutto il codice è scritto e lint-clean (`php -l` / `node --check`). **Le migrazioni DB e l'ingest KB
NON sono ancora stati eseguiti** (questo container dev non raggiunge il DB/Qdrant di produzione).
---
## Cosa è stato implementato
### Fase 1 — Asset Relevance Scoring NIS2 (GV.OC-04)
Metodologia di scoring 0-100 su 6 criteri pesati, soglia rilevanza ≥40, classi critico/alto/medio/basso/trascurabile.
- `docs/sql/020_asset_relevance.sql` — colonne `relevance_score`, `relevance_criteria` (JSON), `relevance_class`, `is_nis2_relevant`, `relevance_assessed_at/by` + indice
- `application/services/AssetScoringService.php` — logica pura + griglia ufficiale in costante
- `application/controllers/AssetController.php``GET scoringGrid`, `POST {id}/score`, `GET relevantSystems`, filtro `nis2_relevant`
- `public/assets.html` — colonna "Rilevanza NIS2" + modale di valutazione a 6 criteri con anteprima punteggio
- `public/js/api.js``getScoringGrid`, `scoreAsset`, `listRelevantSystems`, `deleteAsset`
- Verifica: esempio ERP del mockup = **91/100 → critico**
### Fase 2 — Tassonomia incidenti (Determina ACN 164179/2025)
- `docs/sql/021_incident_nis2_taxonomy.sql` — colonne `nis2_incident_type` ENUM(IS-1..IS-4), `entity_obligation` ENUM(essential/important)
- `application/controllers/IncidentController.php``create()` deriva il regime (Allegato 3 essenziali / Allegato 4 importanti) e blocca IS-4 per gli importanti
- `application/services/AIService.php``classifyIncident()` cita le fonti e restituisce `nis2_incident_type` + `notification_basis`
### Fase 3 — Post-Incident Review + metriche TTD/TTC/TTR
- `docs/sql/022_incident_metrics_pir.sql` — timestamp di fase (`triaged_at`, `contained_at`, `eradicated_at`, `recovered_at`) + tabella `incident_pir` (5-Whys, metriche, costo, lesson learned)
- `IncidentController.php``GET {id}/metrics`, `GET {id}/pir`, `POST {id}/pir`; `update()` timbra i timestamp di fase al cambio stato
- `public/js/api.js``getIncidentMetrics`, `getIncidentPir`, `saveIncidentPir`, `aiClassifyIncident`
### Fase 4 — Layer mapping NIST CSF 2.0 (reference, non invasivo)
- `application/controllers/AuditController.php``GET nistCsfMapping`: 43 controlli NIST CSF 2.0 → NIS2 Art.21/23 → modulo. **Nessuna migrazione**, nessuna modifica all'assessment esistente.
### Fonti normative certe (richiesta esplicita: AI + help citano fonti certe)
- `application/config/nis2_sources.php`**registry canonico citabile** (Dir. 2022/2555, Dir. 2022/2557, D.Lgs. 138/2024, Determina ACN 164179/2025, Determina ACN 333017/2025, Ambiti NIS2)
- `application/services/AIService.php``authoritativeSourcesBlock()` iniettato nei system prompt (default, RAG, classifyIncident): impone di citare le fonti e vieta riferimenti inventati
- `public/js/help.js` — riferimenti normativi italiani aggiunti a incidenti e asset
- `scripts/ingest-nis2-sources.php` — indicizza i 5 PDF normativi nella KB (Qdrant `nis2_kb`, scope SYSTEM) per il grounding RAG
### Report
- `ReportService::generateRelevantSystemsRegister()` + `GET /api/audit/relevantSystemsRegister` — registro formale "Sistemi Rilevanti NIS2" (GV.OC-04) HTML stampabile con citazioni.
---
## Deploy su Hetzner (da eseguire, in ordine — CHIEDERE CONFERMA UTENTE)
```bash
# 0) Backup pre-migrazione
ssh -i docs/credentials/hetzner_key root@135.181.149.254
mysqldump nis2_agile_db assets incidents > /root/backup_pre_v170_$(date +%F).sql
# 1) Deploy codice (bind mount: PHP live; verificare path reale di produzione)
cd /var/www/nis2-agile && git pull origin main # dopo push su Gitea
# 2) Migrazioni DB (additive, idempotenti). NB: usare host MySQL, non docker exec nis2-db
mysql -h localhost nis2_agile_db -e "source /var/www/nis2-agile/docs/sql/020_asset_relevance.sql"
mysql -h localhost nis2_agile_db -e "source /var/www/nis2-agile/docs/sql/021_incident_nis2_taxonomy.sql"
mysql -h localhost nis2_agile_db -e "source /var/www/nis2-agile/docs/sql/022_incident_metrics_pir.sql"
# 3) Ingest fonti normative nella KB (richiede Qdrant + Voyage attivi)
docker exec -i nis2-app php /var/www/nis2-agile/scripts/ingest-nis2-sources.php --dry-run # verifica
docker exec -i nis2-app php /var/www/nis2-agile/scripts/ingest-nis2-sources.php # esegui
# 4) Smoke test
curl -s https://nis2.agile.software/api/assets/scoringGrid -H "Authorization: Bearer <jwt>" | head
```
### Rollback
Ogni `.sql` contiene la sezione ROLLBACK in coda. Per la KB: cancellare i chunk scope=SYSTEM/source=normativa o ripristinare la collection.
---
## Note
- **Phase 4** è volutamente reference-only (nessuna tabella/migrazione) per non toccare l'assessment Art.21 consolidato.
- I PDF normativi restano in `docs/nis2/*.pdf` come libreria sorgente referenziata da `nis2_sources.php`.
- I file `*copy.html` e `incidente_r00/` dei mockup non sono stati usati (duplicati/superati).