[REVISIONE] Progetto revisione conformità+UI + 2 agenti esperti + correzioni R3 (audit NIS2/ISO)

Progetto di revisione unificato (docs/PROGETTO_REVISIONE_NIS2.md) che fonde:
- docs/PRINCIPI_AI_E_CONFORMITA_NORMATIVA.md (cyber + AI Act/GDPR/L.132 + principi AI)
- docs/VERIFICA_GAP_UI_AGID_BOOTSTRAP_ITALIA.md (gap UI vs AGID/Bootstrap Italia)
Agenti esperti: .claude/agents/nis2-expert.md + iso-27001-expert.md (read-only/advisory).

Audit R1 (NIS2) + R2 (ISO SGSI) = conformi, riserve minori. Correzioni R3 applicate
(lint + login reale OK, app su container TLS):
- IncidentController: final_report_due +30gg fissi -> +1 mese calendario, ancorato alla
  notifica reale in sendNotification (Art.23.4 lett.d).
- AIService prompt "report 30d" -> "1 mese dalla notifica 72h".
- help.js: GV.SC Allegato 2 -> Allegati 1 e 2 (Art.21.2(d)).
- nis2_sources.php: esplicitato Allegato 3=importanti / 4=essenziali.
- IsmsModelController export: nota PII.* = codifica interna (non numeri ufficiali 27018).
A4 (label whistleblowing "Art.32") DEFERITO: cita Art.32 D.Lgs.138/2024, da verificare sul testo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
DevEnv nis2-agile
2026-06-12 09:54:14 +02:00
co-authored by Claude Opus 4.8
parent ae7bb072d7
commit 06c94b3c05
10 changed files with 424 additions and 7 deletions
@@ -94,7 +94,7 @@ class IncidentController extends BaseController
$detectedTime = strtotime($detectedAt);
$data['early_warning_due'] = date('Y-m-d H:i:s', $detectedTime + 24 * 3600); // +24h
$data['notification_due'] = date('Y-m-d H:i:s', $detectedTime + 72 * 3600); // +72h
$data['final_report_due'] = date('Y-m-d H:i:s', $detectedTime + 72 * 3600 + 30 * 86400); // 1 mese dalla notifica (Art.23.4 lett.d)
$data['final_report_due'] = date('Y-m-d H:i:s', strtotime('+1 month', $detectedTime + 72 * 3600)); // 1 mese (calendario) dalla notifica 72h — provvisorio; ricalcolato dalla notifica reale in sendNotification (Art.23.4 lett.d)
}
$incidentId = Database::insert('incidents', $data);
@@ -222,7 +222,7 @@ class IncidentController extends BaseController
$detectedTime = strtotime($incident['detected_at']);
$updates['early_warning_due'] = date('Y-m-d H:i:s', $detectedTime + 24 * 3600);
$updates['notification_due'] = date('Y-m-d H:i:s', $detectedTime + 72 * 3600);
$updates['final_report_due'] = date('Y-m-d H:i:s', $detectedTime + 72 * 3600 + 30 * 86400); // 1 mese dalla notifica (Art.23.4 lett.d)
$updates['final_report_due'] = date('Y-m-d H:i:s', strtotime('+1 month', $detectedTime + 72 * 3600)); // 1 mese (calendario) dalla notifica 72h — provvisorio (Art.23.4 lett.d)
}
if (!empty($updates)) {
@@ -306,8 +306,12 @@ class IncidentController extends BaseController
{
$this->requireOrgRole(['org_admin', 'compliance_manager']);
// La relazione finale è dovuta entro 1 mese DALLA notifica completa reale (Art.23.4 lett.d):
// ancoriamo final_report_due al momento effettivo di invio della notifica, non al detected.
$nowTs = time();
Database::update('incidents', [
'notification_sent_at' => date('Y-m-d H:i:s'),
'notification_sent_at' => date('Y-m-d H:i:s', $nowTs),
'final_report_due' => date('Y-m-d H:i:s', strtotime('+1 month', $nowTs)),
], 'id = ? AND organization_id = ?', [$id, $this->getCurrentOrgId()]);
Database::insert('incident_timeline', [
@@ -456,7 +456,7 @@ class IsmsModelController extends BaseController
'documents' => $docs,
'stats' => $this->soaStats($model['id']),
'generated_at' => date('c'),
'disclaimer' => 'Documento di supporto/pre-audit. Non costituisce certificazione ISO 27001 ne parere professionale vincolante.',
'disclaimer' => 'Documento di supporto/pre-audit. Non costituisce certificazione ISO 27001 ne parere professionale vincolante. Nota: i codici A.5/A.6/A.7/A.8 seguono ISO/IEC 27001:2022 Annex A e i CLD.* la ISO/IEC 27017; i codici PII.* sono una codifica interna di indice (i numeri di controllo ufficiali della ISO/IEC 27018 differiscono).',
]);
}