Files
nis2-agile/docs/DESIGN_AUDIT_INTERNI_RIESAME_DIREZIONE.md
T

12 KiB
Raw Blame History

Design + Stima — Moduli "Audit Interni" (9.2) e "Riesame di Direzione" (9.3)

Proposta progettuale (NON ancora implementata) · 2026-06-17 · obiettivo: chiudere i 2 gap gestionali emersi dalla valutazione ISO 27001 (docs/Agile 27000/VALUTAZIONE_COPERTURA_NIS2AGILE_vs_ISO27001.md) e rendere NIS2 Agile audit-ready end-to-end sul lato SGSI (clausole 4–10 complete). Vale anche per NIS2: il riesame periodico e gli audit interni sono buona prassi di governance (GV.PO-02/DE).

Perché questi due

La valutazione ha mostrato che il software copre bene SoA, rischi, NC/CAPA, formazione, asset, evidenze e audit-trail, ma lascia scoperti due output formali che l'auditor chiede sempre:

  • 9.2 Audit interni — manca il ciclo programma → checklist → report.
  • 9.3 Riesame di direzione — il software pianifica la scadenza (review_schedule) ma non produce il verbale con input/output. Entrambi sono gestionali (non controlli tecnici), quindi pienamente realizzabili in-app.

MODULO A — Audit Interni (ISO 27001 §9.2)

Cosa deve produrre (richiesta auditor)

Procedura audit interni (documento) + programma annuale + checklist di conduzione + report con esiti, il tutto come registrazioni tracciate. Le non conformità rilevate confluiscono nel modulo NC/CAPA esistente.

Modello dati (mig.055, additivo, runner-safe)

  • internal_audits: id, organization_id, code (AUD-NNN), title, scope (TEXT), criteria (TEXT: es. "ISO 27001:2022 cl.4-10 + Annex A"), planned_date, executed_date, status ENUM('planned','in_progress','completed','cancelled'), lead_auditor_user_id NULL, lead_auditor_role_id NULL (org_roles), conclusion TEXT, created_by, ts.
  • internal_audit_items (checklist): id, audit_id FK CASCADE, ref_type ENUM('clause','annex_control','nis2_measure','custom'), ref_code VARCHAR (es. '9.2', 'A.8.13', 'ID.AM-01'), checkpoint TEXT, result ENUM('conforme','non_conforme','osservazione','opportunita','non_applicabile','da_verificare') DEFAULT 'da_verificare', note TEXT, ord INT.
  • Riuso: evidenze su evidence_files (entity_type='internal_audit'); finding NC → crea riga non_conformities con source_entity_type='internal_audit_item' + source_entity_id (polimorfico già esistente, 004); calendario → riga review_schedule (estendo ENUM con internal_audit).

Seed checklist (valore chiave: "checklist pronta")

Al create di un audit con criteria ISO, pre-popolare gli item da:

  • clausole 4–10 (28 punti) — lista statica in config,
  • controlli Annex A applicabili dal SoA dell'org (isms_soa dove applicable=1) — riuso del dataset 038. Così l'auditor interno parte con la checklist già compilabile, non da foglio bianco.

Endpoint — InternalAuditController (slug internal-audits)

  • GET list · GET {id} (con item) · POST create (genera code + seed checklist) · PUT {id} · DELETE {id}
  • GET {id}/items · PUT {id}/items/{subId} (esito/note) · POST {id}/items (item custom)
  • POST {id}/items/{subId}/raise-ncr (finding → NC/CAPA)
  • GET {id}/report (report HTML stampabile via ReportService)
  • Ruoli scrittura: org_admin/compliance_manager/auditor. Anti-IDOR + audit log (hash-chain).

Frontend — internal-audits.html

Lista programma (con stato/scadenza dal calendario) + dettaglio audit: intestazione (scope/criteri/auditor), checklist raggruppata per area (clausole / Annex A / NIS2) con esito per riga, pulsante "apri NC" sui non-conformi, export report. Voce sidebar in common-bi.js + common.js (sezione Audit & Report o Gestione). Help/i18n/KB.


MODULO B — Riesame di Direzione (ISO 27001 §9.3)

Cosa deve produrre

Il verbale del riesame, ad intervalli pianificati, con INPUT e OUTPUT previsti dalla norma. Punto di forza possibile: aggregare automaticamente gli input dai moduli esistenti (enorme risparmio + coerenza).

Modello dati (mig.056, additivo)

  • management_reviews: id, organization_id, code (RD-AAAA-NN), review_date, period_label, chair_user_id, attendees (JSON), status ENUM('draft','approved'), approved_by NULL, approved_at NULL, snapshot (JSON: gli input aggregati congelati al momento del verbale), conclusions TEXT, created_by, ts.
  • management_review_decisions: id, review_id FK CASCADE, decision TEXT, owner_role_id NULL, due_date NULL, status ENUM('open','in_progress','done'), capa_id NULL (link a capa_actions se diventa azione), ord.
  • Riuso: decisioni con scadenza → riga review_schedule e/o capa_actions; export via ReportService; immutabilità via audit-log all'approve.

Aggregazione automatica degli input (il valore vero)

GET /api/management-reviews/gather raccoglie e propone (l'utente rivede/edita prima di congelare nello snapshot):

  1. stato azioni dal riesame precedente (management_review_decisions + CAPA);
  2. cambiamenti contesto/parti interessate (ISMS context + stakeholder);
  3. risultati audit interni (Modulo A);
  4. stato NC/azioni correttive (non_conformities/capa_actions);
  5. risultati monitoraggio/KPI (dashboard score, SoA implementation_pct);
  6. raggiungimento obiettivi SGSI (isms_objectives);
  7. risultati valutazione rischi e stato trattamento (Risk + treatments);
  8. feedback parti interessate (attività stakeholder/feedback);
  9. aggiornamenti normativi e ACK (normative_*);
  10. opportunità di miglioramento. OUTPUT: decisioni → diventano azioni (CAPA) e/o scadenze (calendario).

Endpoint — ManagementReviewController (slug management-reviews)

  • GET list · GET {id} · POST create · PUT {id} · GET gather (input aggregati) · POST {id}/decisions · PUT {id}/decisions/{subId} · POST {id}/approve (congela snapshot + audit log) · GET {id}/report (verbale stampabile).
  • Ruoli: org_admin/compliance_manager (approve: org_admin).

Frontend — management-review.html

Form/wizard del verbale: sezioni INPUT pre-compilate da gather (editabili), tabella DECISIONI (con owner/scadenza→calendario), stato draft→approvato, export verbale. Sidebar + help/i18n/KB.


Integrazione e principi

  • Config-driven dove sensato (checklist clausole 4–10 in config/JSON di sistema; controlli da SoA org).
  • Riuso massimo: NC/CAPA, review_schedule (ENUM += internal_audit, management_review), evidence_files, ReportService, AuditService (hash-chain), ISMS SoA/objectives, dashboard score.
  • Convenzioni note: migrazioni runner-safe (CREATE IF NOT EXISTS + FK inline), deploy via host SSH + reload php-fpm host (il prod gira su fpm host), cache-buster, version bump, smoke su org 151 con cleanup, giro help/i18n/KB.
  • Chiude i gap #1 e #2 della valutazione; gli altri (#3 A.8 tecnici, #4 A.7 fisici, #5 KPI/6.3) restano per natura fuori software (resta lo slot SoA+evidenza).

Fasi e stima (riferimento: C5.1/C5.2a già fatti, complessità simile)

Fase Contenuto Stima
A1 mig.055 + InternalAuditController + seed checklist + router/api ~0,5 sessione
A2 internal-audits.html (programma+checklist+report) + sidebar/help/i18n/KB + deploy+smoke ~0,5 sessione
B1 mig.056 + ManagementReviewController + gather (aggregazione input) + router/api ~0,5–1 sessione (il gather è il pezzo ricco)
B2 management-review.html (verbale + decisioni + export) + sidebar/help/i18n/KB + deploy+smoke ~0,5 sessione
V verifica flotta multi-agente + correzioni + doc ~0,5 sessione
Totale due moduli completi, deployati, collaudati ~2,5–3 sessioni

Ogni fase è committata+pushata e LIVE in autonomia (1 sola istanza L1). Prossima migrazione libera: 055.

Esito atteso

Con questi due moduli l'auditor ISO troverebbe in-app: SoA, rischi, NC/CAPA, formazione, asset, evidenze, programma+report audit interni e verbale del riesame — cioè tutte le registrazioni gestionali delle clausole 4–10. Resterebbe solo da dimostrare i controlli tecnici A.7/A.8 sull'infrastruttura reale (non delegabili ad alcun software).


MODULO C — Calendario unico delle scadenze (richiesta utente 2026-06-17)

Obiettivo

Una vista calendario unica che raccoglie ogni scadenza del sistema in un solo posto (griglia mensile + lista + filtri), con stato (in ritardo / in scadenza / futura) e link diretto all'elemento. Oggi le scadenze sono sparse in molti moduli e aggregate solo in parte (dashboard "prossime scadenze" a 30 gg + Scadenziario revisioni periodiche): manca la vista d'insieme completa.

Analisi — sorgenti di scadenza già presenti (verificate nel codice/DB)

Sorgente Campo data Modulo
Incidenti Art.23 early_warning_due / notification_due / final_report_due (calcolati) incidents
Revisione policy/procedure policies.next_review_date Policy
Trattamenti rischio risk_treatments.due_date Rischi
Revisione controlli compliance_controls.next_review_date Audit/Controlli
Non conformità / azioni non_conformities.target_close_date, capa_actions.due_date NCR/CAPA
Formazione training_assignments.due_date Formazione
Attività stakeholder stk_activities.due_date / planned_date Stakeholder (C5)
Scadenziario revisioni review_schedule.next_review_date (ricorrenti) Scadenziario (A4 4.4)
Audit interni (nuovo) internal_audits.planned_date Modulo A
Decisioni riesame (nuovo) management_review_decisions.due_date Modulo B

Esistente da riusare: DashboardController::deadlines (union incidenti/policy/trattamenti/formazione a 30 gg) — ne generalizzo il pattern. review_schedule resta per le revisioni ricorrenti (ha frequency_months); il calendario lo include come una delle sorgenti.

Decisione architetturale — aggregatore READ-ONLY (nessuna tabella nuova)

Le scadenze vivono già nei moduli sorgente, ciascuna col proprio ciclo di vita: duplicarle in una tabella calendario creerebbe disallineamenti. Quindi: endpoint aggregatore in sola lettura che fa UNION live di tutte le sorgenti e normalizza gli eventi. Niente migrazione per il calendario (mig. solo per A/B). Vantaggi: sempre coerente, additivo, zero rischio dato.

Endpoint — CalendarController (slug calendar)

  • GET /api/calendar/events?from=YYYY-MM-DD&to=YYYY-MM-DD&types=... → lista eventi normalizzati: { source, type, title, date, status (overdue|due_soon|upcoming|done), severity, entity_type, entity_id, link }. org-scoped, anti-IDOR (filtro organization_id su ogni sorgente), stato calcolato live (come review_schedule).
  • GET /api/calendar/summary → conteggi per stato/tipo (per badge dashboard).
  • Riusa/centralizza la logica di DashboardController::deadlines (che può poi delegare a questo).
  • Sola lettura → requireOrgAccess().

Frontend — calendario.html

  • Griglia mensile (HTML/CSS puro, dependency-free) con pallini colorati per tipo + navigazione mese prec./succ.; vista lista alternativa (ordinata per data, in ritardo in cima); filtri per tipo (incidenti, policy, rischi, formazione, NC/CAPA, stakeholder, audit, riesame, revisioni) e per stato.
  • Click su evento → deep-link al modulo sorgente (es. incidente, policy, audit…).
  • Legenda + badge "in ritardo / in scadenza". Voce sidebar ("Calendario") in common-bi.js+common.js; help/i18n/KB.
  • La dashboard mostra già "prossime scadenze": aggiungere un link "Apri calendario".

Ancoraggio

Strumento operativo trasversale; supporta direttamente la buona prassi di monitoraggio scadenze e revisioni periodiche (ISO 9.1/9.3, NIS2 GV.PO-02/GV.SC-07/DE.CM). Non è un obbligo specifico: è gestione.

Stima Modulo C

Fase Contenuto Stima
C1 CalendarController (aggregatore union tutte le sorgenti + summary) + router/api ~0,5 sessione
C2 calendario.html (griglia mensile + lista + filtri + deep-link) + sidebar/help/i18n/KB + deploy+smoke ~0,5–1 sessione

Nessuna migrazione per C (solo lettura). Le scadenze di A e B vi confluiscono automaticamente.

Stima complessiva aggiornata (A + B + C)

  • Modulo A (Audit interni): ~1 sessione · Modulo B (Riesame): ~1–1,5 · Modulo C (Calendario): ~1 · Verifica flotta finale: ~0,5.
  • Totale ~3,5–4 sessioni, tutto additivo/runner-safe, committato e LIVE a fasi.

Ordine consigliato

A → B → C: il calendario (C) per ultimo così ingloba subito anche le scadenze di Audit interni e Riesame. In alternativa C si può fare per primo come quick-win trasversale (aggrega già tutto l'esistente) e poi A/B vi si agganciano.