Commit Graph
54 Commits
Author SHA1 Message Date
DevEnv nis2-agileandClaude Opus 4.8 4fdeae7cee [FEAT] Modulo Controlli periodici (control monitoring §9.1/A.8.16) — v1.23.0
Registro controlli ricorrenti (owner/frequenza/metodo/controllo SoA-NIS2 collegato)
+ registro esecuzioni come EVIDENZA (data/esito/note) con avanzamento automatico
della scadenza; da esito non conforme generazione NC o NC+azione correttiva
(riuso non_conformities/capa_actions, nuova source 'monitoring'); report
scheda+storico stampabile; scadenze nel Calendario unico.

mig.057: periodic_controls + periodic_control_executions (FK CASCADE, UNIQUE
(organization_id, code)). PeriodicControlController (slug periodic-controls) +
controlli-periodici.html + CalendarController.srcPeriodicControls.

Fix da flotta di verifica avversariale (9 finding confermati):
- advance(): correzione overflow strtotime '+1 month' (31/01 -> 28/02, no salto
  mese) via DateTimeImmutable con clamp all'ultimo giorno valido (mensile/
  trimestrale/semestrale/annuale); giornaliero/settimanale/custom invariati.
- create(): retry-on-duplicate del codice CTL-NNN con UNIQUE (org_id, code).
- update(): array_key_exists per azzerare owner_role_id / next_due_date.
- delete(): rimossa cleanup morta su review_schedule (il calendario legge diretto).
- CalendarController.srcReviewSchedule: esclude internal_audit/stakeholder_activity
  (gia' con sorgente diretta) -> fix doppia comparsa nel calendario.
- calendario.html: TYPE_META 'periodic_control' (chip filtro + label + colore).

Additivo. Cache-buster ?v= bump (sidebar) + sw cache nis2-shell-v1.23.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 09:21:03 +02:00
DevEnv nis2-agileandClaude Opus 4.8 79ca72fba9 [FEAT] ISO-readiness: Audit interni (§9.2) + Riesame Direzione (§9.3) + Calendario scadenze (mig.055-056, v1.22.0)
Rilascio unico (3 moduli) costruito in flotta parallela + verifica avversariale.

MODULO A — Audit interni (ISO 27001 §9.2, mig.055): internal_audits + internal_audit_items;
codice AUD-NNN; checklist pre-popolata (clausole 4-10 + Annex A applicabili dal SoA);
esiti per riga; apertura non conformità collegata a NCR/CAPA (source polimorfico);
report HTML stampabile. InternalAuditController + internal-audits.html.

MODULO B — Riesame di Direzione (ISO 27001 §9.3, mig.056): management_reviews +
management_review_decisions; codice RD-AAAA-NN; INPUT aggregati automaticamente dai
moduli (gather: NC/CAPA, audit interni, rischi+trattamenti, KPI/score, obiettivi, formazione,
stakeholder, normative, scadenze), congelati nello snapshot all'approvazione; decisioni;
verbale stampabile. ManagementReviewController + management-review.html.

MODULO C — Calendario unico scadenze: aggregatore SOLA LETTURA (nessuna migrazione) di tutte
le scadenze (incidenti/policy/rischi/NC-CAPA/formazione/stakeholder/audit/riesame/review_schedule),
griglia mensile + lista + filtri + deep-link. CalendarController + calendario.html.

Integrazione: router (3 controller+actionMap), api.js, sidebar V2+legacy, help.js (3 sezioni),
i18n (IT+EN), review_schedule ENUM += internal_audit. v1.22.0 + sw cache + cache-buster 20260630.

Verifica flotta (28 agenti, 4 dim + avversariale): 9 finding confermati, TUTTI corretti —
MAJOR gatherRisks (risk_treatments.organization_id inesistente → JOIN risks); nextCode numerico
(no dup >99/anno); footer report audit con etichetta "ISO buona prassi, non obbligo"; help 24→25
clausole; ARIA tab/calendario; focus modali; tasti su celle calendario; rimossi helper api morti.

Smoke prod OK (calendario 18 eventi, audit AUD-001 25 item + report + audit→NCR + audit→calendario,
riesame gather/decisione/approve/report, gatherRisks ora available); org 151 ripulita. Additivo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 07:48:49 +02:00
DevEnv nis2-agileandClaude Opus 4.8 b917d2da14 [FIX] Epic C / C5 hardening — esiti flotta di verifica multi-agente (mig.054)
Corretti i finding confermati dalla verifica multi-agente (5 major + minori):

SICUREZZA
- Stored XSS allegati: da blocklist a ALLOWLIST di estensioni innocue (no html/svg/js
  renderizzabili same-origin) in StakeholderPortalController::attachment e
  StakeholderActivityController::storeUpload; nome file randomizzato (random_bytes).
- Magic-link: scadenza (mig.054 stk_activity_targets.token_expires_at; send() imposta
  scadenza attività+30gg o +90gg; resolveTarget() → 410 TOKEN_EXPIRED se scaduto);
  rate-limit per-IP sugli endpoint del portale; comment/attachment bloccati su attività chiusa.

CORRETTEZZA
- send(): NON rigenera token né azzera lo stato dei destinatari già responded/acknowledged
  (prima ne perdeva l'esito); imposta token_expires_at.
- assign individuale: semantica "replace" (rimuove i deselezionati non ancora conclusi) +
  guard su lista vuota (evita 'IN ()').
- update(): conserva assign_mode esistente quando si modifica solo stak_code.

UI/UX/A11Y
- Editor opzioni per domande a scelta singola/multipla (prima degradavano a testo nel portale).
- Etichette stato/tipo localizzate; risposte mostrate inline (no alert()); escAttr nel portale
  (escape virgolette negli attributi); ARIA su modali/tab; voce sidebar anche in common.js.

OPEN ITEM (NON regressione C5, pre-esistente e ambientale): l'upload allegati restituisce
UPLOAD_ERROR in prod — move_uploaded_file/is_uploaded_file fallisce nella topologia
proxy→fastcgi (stesso pattern di evidence_files/AuditController, mai funzionato: la dir
uploads/evidence non esiste). rename/copy come www-data funzionano. Da investigare lato infra.
Il resto di C5 (questionari, firma-lettura, commenti, calendario, portale) è pienamente operativo.

Smoke prod OK: allowlist (.html→422, struttura ok), opzioni scelta nel portale, send no-reset,
replace individuale, token_expires_at presente. Additivo. v1.21.1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 22:52:31 +02:00
DevEnv nis2-agileandClaude Opus 4.8 4f386faae5 [FEAT] Epic C / C5.2b — Portale esterno stakeholder + sotto-dashboard feedback (mig.053)
Completa C5 (Epic C). Gli stakeholder rispondono in self-service tramite magic-link
(token SHA-256 per destinatario, NESSUN account/JWT); il compliance manager vede gli
esiti, i commenti e gli allegati nel dettaglio dell'attività.

- StakeholderPortalController (non-JWT, token-only): access / respond (questionario) /
  acknowledge (firma di avvenuta lettura) / comment / attachment. Submit one-shot (409),
  validazione risposte obbligatorie, anti-IDOR (un token = un solo destinatario),
  auto-completamento attività quando tutti hanno risposto/firmato.
- StakeholderActivityController: feedback (risposte per destinatario), comments
  (GET/POST), attachments (upload interno + lista; riuso evidence_files entity_type=
  'stk_activity', file sotto public/uploads/stk_activity/{org}/).
- mig.053: stk_activity_responses (answers JSON / acknowledged_at), stk_activity_comments
  (interni/esterni). Estende il seeder idempotente.
- Frontend: stk-portal.html (pagina pubblica dependency-free: questionario per tipo di
  domanda o testo+firma, commento, upload); dettaglio attività in stakeholder-activities.html
  con esiti, thread commenti e allegati.

Email disattivate (kill-switch) → i magic-link si condividono manualmente. Smoke prod OK
(access no-auth, respond+required+409, acknowledge+WRONG_TYPE, comment esterno/interno,
bad-token 404, feedback interno, auto-complete; cleanup org 151 pulita). Additivo. v1.21.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 22:20:14 +02:00
DevEnv nis2-agileandClaude Opus 4.8 a5ff29e0da [FEAT] Epic C / C5.2a — Attività stakeholder: questionari tipo + attività + calendario (mig.052)
Fondazione delle attività verso gli stakeholder (Simon C5 §4):
- Questionari tipo (template): tipo questionario-da-compilare / firma-di-avvenuta-lettura,
  domande (JSON) + collegamento m2m a procedure (policies) E a misure/requisiti del
  framework (cfg_nis2_misure/requisiti).
- Attività: basate (opz.) su un template, assegnabili a un CODICE stakeholder (tutti
  quelli di quel tipo) o a singoli stakeholder; pianificabili con data e scadenza.
- Calendario NIS2: review_schedule esteso (ENUM entity_type += 'stakeholder_activity');
  su create/update con scadenza la riga di calendario viene sincronizzata.
- Invio: genera un magic-link per destinatario (token SHA-256) per il portale esterno
  (C5.2b). Email disattivate (kill-switch) -> i link si condividono manualmente.

mig.052: stk_questionnaire_templates, stk_template_(procedures|misure|requisiti),
stk_activities, stk_activity_targets, stk_activity_procedures + ALTER review_schedule.
StakeholderActivityController + /api/stakeholder-activities/*; stakeholder-activities.html
(2 tab: attività / questionari tipo + dettaglio invio); voce sidebar V2; help/i18n.
Smoke prod OK (template m2m, attività by_code+calendario, assign, send magic-link,
anti-IDOR individual, negativi 422; cleanup org 151 pulita). Additivo. v1.20.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 22:12:11 +02:00
DevEnv nis2-agileandClaude Opus 4.8 c782aa54fa [FEAT] Epic C / C5.1 — Modulo Stakeholder: registro + matrice di Mendelow (mig.051)
Registro dedicato degli stakeholder (tabella `stakeholders`, NON una colonna su
suppliers: gli interni non sono fornitori; gli esterni si COLLEGANO opzionalmente
a un supplier esistente senza duplicare il dato).

- mig.051: cfg_stakeholder_types (30 di sistema Stak.01-30 + org-added da Stak.31),
  cfg_stakeholder_quadrants (4, range corretti: Q4 potere 0-2), stakeholders,
  stakeholder_procedures (m2m -> policies). Seeder idempotente seed_stakeholders.php.
- StakeholderController: list/create/update/delete + types/addType + quadrants + pickers.
  Quadrante CALCOLATO a read-time dai range config. Anti-IDOR su org_role/supplier/
  policy/tipo; coerenza kind (interni->organigramma, esterni->fornitore); punteggi 0-5.
- api.js: metodi stk*. stakeholders.html riscritta: registro + matrice di Mendelow
  in SVG dependency-free + modali (stakeholder, nuovo tipo). Voce sidebar V2 (common-bi.js).
- Help aggiornato; cache-buster ?v=20260626 su tutte le pagine; version 1.19.0; sw cache v1.19.0.

Ancoraggio GV.SC-02 (obbligo, art. 24 D.Lgs. 138/2024). La matrice di Mendelow e'
etichettata come BUONA PRASSI, non obbligo NIS2 (regola fonti-certe). Additivo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 20:54:57 +02:00
DevEnv nis2-agileandClaude Opus 4.8 30f4614b37 [FEAT] Epic C / C4 — inventario a 2 voci + sottoclassi configurabili (mig.050)
Simon C4: nell'inventario DUE sole voci principali; le sottoclassi le crea l'utente.
Riconduzione concordata (no perdita di dettaglio): hardware/network/facility -> ID.AM-01;
software/service/data -> ID.AM-02; personnel -> Organigramma (0 asset personnel presenti).

- Config: cfg_inventory_voci (2: ID.AM-01 Hardware, ID.AM-02 Software/Servizi/Sistemi),
  inventory_subclassi (12 default di sistema org NULL + sottoclassi org-scoped).
- assets.voce_code + subclass_id (FK). 20 asset esistenti MIGRATI (5 ID.AM-01 / 15 ID.AM-02).
- AssetController: list con label voce/sottoclasse; create/update validati (voce in whitelist,
  sottoclasse appartenente a org/default+voce); GET/POST /assets/subclasses; import (bulkUpsert)
  deriva la voce dal tipo legacy. asset_type resta come campo legacy (viste secondarie).
- assets.html: filtro per voce, form con selettore Voce + Sottoclasse (+ '+ aggiungi'),
  lista/dettaglio mostrano 'voce · sottoclasse', stat-chips per voce.
- FIX bug pre-esistente: apostrofo non escapato ('l'inventario') che ROMPEVA tutto il JS
  della pagina Inventario. + cache-buster common-bi.js (era a v=20260618, non bumpato dal fix C3).
Help + KB + i18n. Verifiche prod: subclasses 200, create voce/legacy OK, validazione 422,
JS valido (node --check), migrazione idempotente. version 1.18.4.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 19:59:35 +02:00
DevEnv nis2-agileandClaude Opus 4.8 e281aa4970 [FEAT] Epic C / C3 — rimosso modulo 'Analisi GAP ACN' (superato da C1)
Simon C3: l'analisi gap ACN non è un artefatto normativo e va eliminata; la conformità
emerge da C1 (elenco Misure/Requisiti + valutazione per requisito in org_requisito_state).

Ricognizione → migrazione → backup → rimozione (sicuro, 0 perdite):
- Tabelle acn_assessments/acn_assessment_responses VUOTE (0 righe) -> droppate (mig.049,
  guard anti-drop se >0 righe). Ricreabili da 036. Nessun dato utente perso.
- Integrazione lg231: /api/services/gap-analysis legge 'assessments' generale, NON il modulo
  ACN -> intatta. Verificato.
- RaciController ripuntato su cfg_nis2_misure (fonte canonica) al posto di acn_measures.json
  (rimosso); validazione measure_code verificata (/raci/objects?type=measure -> 43 misure).
Rimossi: AcnAssessmentController, public/acn-gap.html, application/data/acn_measures.json,
routing acn-gap, voci sidebar (common.js + common-bi.js), metodi api.js acn*, sezione help 'acn',
chiavi i18n acn.*, mapping demo-selectors. Tour demo step 3 RIPUNTATO su misure-requisiti
(no step rotto, 10 step). Sidebar BI ora mostra 'Misure e Requisiti' (gap di common-bi.js sanato).
Verifiche prod: /acn-gap.html 404, /api/acn-gap/* 404, /misure-requisiti 200, RaciController OK.
Cache-buster ?v=20260624, version 1.18.3, SW v1.18.3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 19:24:29 +02:00
DevEnv nis2-agileandClaude Opus 4.8 4570ce3ba1 [FEAT] Epic C / C1 operativo — copia procedure di default al 1° accesso (mig.048)
PolicyController::list ora, al primo accesso al modulo Procedure di un'org reale,
copia le 42 procedure di default (cfg_nis2_procedure) in policies come contenuto
editabile/cancellabile (decisione utente: copia per-org al 1° accesso).
- organizations.framework_procedures_seeded_at = idempotenza (no ri-copia).
- categoria policies assegnata da mappa famiglia NIST->ENUM; nis2_article=misura;
  content riporta misure coperte + nota 'personalizzabile e cancellabile'.
- Salta org demo/sandbox (isDemo) per non inquinare il dataset dimostrativo.
- Best-effort: errore nel seed NON blocca la lista (log + return).
Smoke prod: org 151 3->45 policy (42 default, 10 categorie), idempotente al 2° accesso,
golden 151 poi ripristinato (cleanup). Additivo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 18:18:28 +02:00
DevEnv nis2-agileandClaude Opus 4.8 b34bf3f9f6 [FEAT] Epic C / C1 operativo — valutazione/stato di conformità per requisito (mig.047)
org_requisito_state (org x requisito -> stato + valutazione del rischio + note),
la valutazione 'parte vuota'. È da qui che emerge lo stato di conformità (sostituirà il Gap ACN, C3).
- FrameworkController: catalog ora include lo stato per-org di ogni requisito (risoluzione org
  OPZIONALE con verifica accesso = anti-IDOR); nuovo POST /framework/state (upsert, requireOrgRole
  org_admin/compliance_manager, validazione stato + requisito esistente).
- misure-requisiti.html: colonna Stato/Valutazione (se org) + modale di valutazione (stato,
  valutazione del rischio, note). api.frameworkSetState.
Smoke prod: catalog has_org/org_class OK; upsert non_conforme persistito e riletto; ISOLAMENTO
multi-tenant verificato (org 152 non visibile a org 151). Additivo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 17:41:16 +02:00
DevEnv nis2-agileandClaude Opus 4.8 d37047987f [FEAT] Epic C / C1 — tabelle di configurazione framework NIS2 (mig.046)
Fondazione data-driven (direttiva utente: configurabile via DB, no JSON hardcoded).
Fonte autoritativa: docs/simon/C1_Misure_Requisiti.xlsx + Vista (codifica Simon NON variata).

Tabelle system-level, sola-lettura per l'utente, configurabili da super_admin:
- cfg_nis2_ambiti (18 categorie NIST GV/ID/PR/DE/RS/RC)
- cfg_nis2_misure (43 misure; 6 solo-essenziali; area politica a..p, applies_important/essential)
- cfg_nis2_requisiti (116 requisiti; 92 importanti / 116 essenziali; ord N immutabile; FK misura/proc/risk)
- cfg_nis2_procedure (42 procedure di default Proc.01-42)
- cfg_nis2_rischi (84 rischi di default Risk.01-85)

Seed via application/data/nis2_framework_seed.json (import-only; runtime legge le cfg_*).
Applicato su prod (additivo, reversibile via DROP). Runner temp self-contained gia rimosso.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 17:07:12 +02:00
DevEnv nis2-agileandClaude Opus 4.8 c5b00ccd96 [FEAT] A4 Fasi 4.4 + 4.5 (A4 COMPLETA 5/5): scadenziario centralizzato review_schedule (mig.044; ReviewScheduleController list/create/update/delete/complete/sync) + stakeholder estesi clienti/partner GV.SC-02 (mig.045 suppliers.stakeholder_type, SupplyChainController::stakeholderMap). Pagine review-schedule.html + stakeholders.html (Bootstrap Italia/AGID). Workflow build+review adversariale (3 major risolti: 045 da DELIMITER -> ALTER bare runner-safe). help GV.SC-04/05 allineati al titolo canonico ACN. Cache-buster ?v=20260620.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 23:10:28 +02:00
DevEnv nis2-agileandClaude Opus 4.8 b4d47d58a2 [FEAT] A4 Fase 4.3 — Matrice RACI + link m2m: raci_assignments + procedure_inventory/procedure_risk/inventory_risk/risk_measure (mig.043), RaciController org-scoped (anti-IDOR, validazione object/measure), raci.html+raci.js (Bootstrap Italia/AGID), routing+sidebar+api+help+i18n. Build+review adversariale via workflow (0 finding critical/major). Cache-buster ?v=20260619.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 22:44:08 +02:00
DevEnv nis2-agileandClaude Opus 4.8 5368b0a61c [FEAT] A4 Fase 4.2 — Competenze (skill/requisiti ruolo/gap) + alert→azione NCR+CAPA
Secondo modulo del modello relazionale A4 (docs/DESIGN_A4_RELATIONAL.md).

Backend:
- Migration 042 (docs/sql/042_competences.sql) + runner aggiornato (scripts/migrate-a4.php).
  4 tabelle additive/idempotenti: skills (org-owned o globali), role_skills
  (competenze richieste dal ruolo, UNIQUE role+skill), user_skills (possedute,
  UNIQUE org+user+skill), skill_course_map. APPLICATA su prod (nis2-db v8.0.45,
  TLSv1.3).
- CompetenceController (route 'competences'): catalog, skills CRUD, roleSkills,
  userSkills, skillCourses (map/unmap), gapGrid (richiesto−posseduto per ruolo
  con titolare), openAction. Multi-tenancy + anti-IDOR + livelli 1-5; competenze
  globali in sola lettura per gli utenti org.
- alert→azione: openAction RIUSA il workflow NCR/CAPA reale (la tabella azioni è
  capa_actions figlia di non_conformities, NON 'corrective_actions' che non
  esiste): crea NCR (source='management_review', source_entity_type='competence_gap',
  source_entity_id=role_skills.id) + capa_actions figlia. Anti-duplicato sul gap.
  Zero ALTER alle tabelle esistenti. Ancoraggio PR.AT-01/02, GV.RR-04, art.24 D.Lgs.

Frontend:
- competenze.html (4 schede: Catalogo, Requisiti per ruolo, Competenze persone,
  Gap & azioni) + js/competenze.js. Bootstrap Italia V2. CTA "Assegna corso"
  (riuso /training/assign) e "Apri non conformità".
- Voce sidebar "Competenze" (common.js + common-bi.js + BI_PAGES) + nav.competences
  i18n IT/EN. api.js: metodi comp* + assignTraining.

Help/KB/PWA:
- help.js: guida contestuale 'competences' (schede, calcolo gap, PR.AT-01/02,
  GV.RR-04, art.24 D.Lgs., disclaimer no-parere-legale) + mappa pagina.
- sw.js: nome cache nis2-shell-v1.17.0 (allineamento PWA).
- Design doc corretto (rettifica capa_actions vs corrective_actions) + avanzamento 4.1/4.2.

Cache-buster: ?v=20260618 dei 5 JS condivisi su 32 HTML. version.json 1.16.0 -> 1.17.0.
Smoke E2E su prod (fpm reale): catalogo, requisito, competenza, gap=2, openAction
(NCR+CAPA), anti-dup 409, mappatura corso — tutti verdi; dati di test ripuliti.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 19:01:32 +02:00
DevEnv nis2-agileandClaude Opus 4.8 8540b53cb2 [FEAT] A4 Fase 4.1 — Organigramma (org_roles): ruoli/gerarchia + nodo governance Art.23
Primo modulo del modello relazionale A4 (docs/DESIGN_A4_RELATIONAL.md).

Backend:
- Migration 041 (docs/sql/041_org_roles.sql) + runner scripts/migrate-a4.php.
  Tabella org_roles additiva/idempotente: gerarchia self-FK (parent_role_id),
  titolare (holder_user_id), is_governance_body (organi amministrazione/direttivi
  Art.23 D.Lgs.138/2024), description (GV.RR-02). APPLICATA su prod (container
  nis2-db v8.0.45, TLSv1.3, 11 col, 4 FK).
- OrgRoleController: list (flat+tree arricchiti), get, create, update, delete,
  assignableUsers. Multi-tenancy ancorata a getCurrentOrgId(), anti-IDOR
  (id+organization_id), prevenzione cicli nella gerarchia, holder = membro org,
  delete bloccato se ha figli (409). Route registrate in public/index.php.

Frontend:
- public/organigramma.html + js/organigramma.js: vista ad albero (badge governance,
  titolare/vacante), editor crea/modifica/elimina con select padre anti-ciclo,
  "crea struttura di base". Bootstrap Italia V2.
- Voce sidebar "Organigramma" (common.js + common-bi.js) + nav.org_chart i18n IT/EN.
- api.js: metodi orgRole* (wrapper _acn).

Help/KB:
- help.js: guida contestuale 'org' (cosa rappresenta, nodo Art.23, come si usa,
  fonti certe D.Lgs.138/2024 art.23 + GV.RR-02 best practice, disclaimer no-parere-legale).

Cache-buster: bump ?v=20260617 dei 5 JS condivisi su tutte le 32 HTML referenti.
version.json 1.15.2 -> 1.16.0. Smoke E2E su prod (fpm reale): login, CRUD, tree,
anti-ciclo (422), delete-con-figli (409), cleanup tutti verdi.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 18:05:56 +02:00
DevEnv nis2-agileandClaude Opus 4.8 b2f47c0a47 [FEAT] A2 migration 040: organizations += classificazione NIS2 (bilancio, autonomia, size-independent c.5, criteri c.9 b/c/d, mission, designation_basis, self_assessment preliminary) — applicata+verificata prod
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 16:56:56 +02:00
DevEnv nis2-agileandClaude Opus 4.8 b80bf2361c [BACKUP] Sessione 2026-06-14: supervisore autonomo + contesto + mig.039 + UI V2 plan
- Supervisore autonomo ticket: prompt operativo + dry-run (scripts/), DRAFT rimosso; gate normativo gia' committato
- docs/CONTEXT_LAST_SESSION.md: sessione 2026-06-14 (supervisore LIVE, run#1/#2, rotazione Anthropic rinviata)
- docs/sql/039_integrity_keys.sql: migrazione integrita' DB (PK/UNIQUE/FK) gia' applicata in prod 12/6
- docs/MIGRATION_UI_V2.md: piano migrazione UI V2
- docs/nis2/incidente_r00/: 2 mockup incidente (gateway+dashboard)
- .gitignore: versiona public/vendor/ (asset Bootstrap Italia self-hosted)
- Fix accumulati: EmailService (kill-switch email), Incident/Onboarding/Organization/Services controllers, questionnaire, ReportService, CLAUDE.md standard

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 16:35:41 +02:00
DevEnv nis2-agileandClaude Opus 4.8 e1ab0b3ea0 [DEMO] Avatar di prodotto Fase 1 — fondazione backend (5 endpoint /api/demo/*)
product-demo-protocol v1.0.1, Modalita A. Additivo (zero impatto endpoint esistenti).

- DemoController: session-start, manifest, event, credentials, reset-dataset
  * demo_jwt scope=demo:read-only, org_id 996001 (range demo 996000-996999), TTL 30m
  * hmac_key_seed base64 44ch, rate-limit 5/min+50/h per IP, eventi idempotenti
- Migration 040: tabelle demo_sessions + demo_events
- Rotte 'demo' in index.php (chiavi camelCase: router camelCasa il segmento URL)
- docs/DEMO_AVATAR_NIS2.md: piano Fase1/Fase2, decisioni, punti integrazione AgileHub, gap protocollo

Smoke prod OK: session-start 201, manifest 200, credentials 200, event 204, reset 401(no key).
TODO Fase 1: read-only guard in requireAuth, dataset demo 996001, frontend demo-mode, manifest+mappe.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 18:15:37 +02:00
DevEnv nis2-agile 3f74165531 [FEAT] Modello Organizzativo SGSI (ISO 27001/27017/27018) + SoA pre-popolato da NIS2
Nuovo modulo guidato in 6 step (cl. 4-10 + Statement of Applicability):
- migration 037 (isms_models/roles/soa/documents) + 038 (dataset 111 controlli:
  93 Annex A:2022 + 7 CLD/27017 + 11 PII/27018) + runner scripts/migrate-isms.php
- IsmsModelController (16 endpoint) registrato in index.php
- SoA pre-popolato dalle risposte Gap Analysis NIS2 (mapping iso27001_control)
- estensioni cloud condizionali 27017/27018 via flag uses_public_cloud/
  is_cloud_provider/processes_pii_in_cloud
- AIService::generateIsmsDocument + fonti ISO in nis2_sources.php
- frontend isms.html/isms.js + api client + sidebar + help + i18n IT/EN
- ingest KB ISO (scope SYSTEM, solo titoli/sintesi: no testo coperto da copyright)
- version.json 1.14.0; doc studio + deploy handoff

Strumento di supporto/pre-audit (non certificazione). Migration DA APPLICARE su host.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 11:32:42 +02:00
DevEnv nis2-agileandClaude Opus 4.8 ea2a291325 [FEAT] Gap Analysis ACN: assessment misure/requisiti Det. 164179/2025 (backend)
Assessment di SECONDO LIVELLO sulla Determinazione ACN 164179/2025 (non le 10
lettere generiche Art.21, gia coperte). Distingue soggetti importanti/essenziali:
- IMPORTANTI (All.1): 37 misure, 87 requisiti
- ESSENZIALI (All.2): 43 misure, 116 requisiti

- application/data/acn_measures.json: dataset canonico estratto dai testi
  UFFICIALI ACN (Allegati 1+2), testi requisiti INTEGRALI (no troncamenti),
  flag per-requisito importante/essenziale. Validato 37/87 + 43/116, zero
  discrepanze vs codici di riferimento.
- AcnAssessmentController: catalog/list/create/get/requirements/respond/complete/
  report/aiAnalyze. Pre-popola requisiti applicabili per entity_level, scoring
  per funzione FW (GOVERN/IDENTIFY/PROTECT/DETECT/RESPOND/RECOVER), grounding AI
  sui 203 requisiti ACN gia in KB. Anti-IDOR, snapshot testo immutabile.
- Migrazione 036: acn_assessments + acn_assessment_responses (APPLICATA su host).
- Router: acn-gap controllerMap + actionMap.

Origine: finding revisore (la Gap Analysis Art.21 non e l'autovalutazione ACN).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 08:02:59 +02:00
DevEnv nis2-agileandClaude Opus 4.8 5c7ed9abcb [FIX] Import fornitori: valida scope org di category_id + allinea header migrazioni 032/033
- bulkUpsertSuppliers: il ramo category_id esplicito (import API/CSV) ora verifica
  che la categoria sia un preset (org 0) o della stessa org, come gia' fa il ramo
  category_slug. Evita di scrivere suppliers.category_id di un'altra org (dato sporco
  cross-org). Finding review multi-agente (MINORE, correttezza dati).
- docs/sql/032,033: header "PROPOSTA DI DESIGN (NON applicata)" -> "APPLICATA su
  produzione 2026-05-31" (sono effettivamente applicate). Evita confusione operativa.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:16:43 +02:00
DevEnv nis2-agileandClaude Opus 4.8 aa2db4c6c2 [DOCS] Design modulo questionari fornitori + portale OTP + AI consulente normativo
Pacchetto di design completo (nessun codice applicato, nessuna migrazione eseguita):
- DESIGN aggiornato con 5 review agenti + 3 decisioni utente + pilastro AI consulente (sez. 12-14)
- docs/supplier-portal/template-nis2-base.questions.json: 26 domande GV.SC (Allegato 2 ACN) con nis2_ref/vuln_flag e fonti certe verbatim
- docs/supplier-portal/AI_CONSULENTE_NORMATIVO.md: corpus normativo aggiornato + persona consulente (modello TRPG)
- docs/supplier-portal/UX_MINI_SPEC.md: mini-spec portale fornitore (stati/copy/autosave/mobile/a11y/editor no-code)
- docs/sql/032-035: migrazioni idempotenti proposte (modulo, suppliers, portale auth, migrazione 027->campaigns)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 09:53:07 +02:00
DevEnv nis2-agileandClaude Opus 4.8 59205d05fb [FEAT] Gap Analysis estesa ai requisiti ACN (specifiche di base 164179/2025)
Allinea il PRODOTTO alla guida/normativa portando la compliance dal livello 10 misure Art.21
al livello operativo dei requisiti ACN (Framework Nazionale 2025).
- Migrazione 031: acn_requirements (catalogo) + org_acn_requirement_status (stato per-org)
- Seed da Allegati 1-2 ACN (fonte certa, parsing verificato): 87 importanti + 116 essenziali = 203 requisiti reali
- AuditController: acnRequirements (GET, per entity_type org: importanti 87 / essenziali 116, summary per funzione GV/ID/PR/DE/RS/RC, % compliance) + updateAcnRequirement (PUT stato+evidenza)
- Route audit/acnRequirements GET/PUT
- guida.html: fix refuso cap-5 (residuo 'otto categorie...no' -> '10 categorie x 8, quattro modalita')
E2E prod: org importante -> 87 req; PUT implemented -> compliance aggiornata.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 08:07:38 +02:00
DevEnv nis2-agileandClaude Opus 4.8 5413730b00 [FIX] Policy: UNIQUE(policy_id,version) + diff LCS posizionale (findings review)
- Migrazione 030: UNIQUE uq_policy_version su policy_versions (de-dup prima, idempotente).
  approve() ora usa INSERT ... ON DUPLICATE KEY UPDATE -> riapprovare la stessa versione
  aggiorna lo snapshot invece di duplicarlo. Verificato E2E: 2x approve v1.0 -> 1 sola riga.
- diff(): sostituito il confronto set-based (falsi negativi su righe duplicate/riordino) con
  un vero diff LCS line-by-line con posizioni. Verificato E2E: bump v1->v2 -> added 2, removed 1 corretti.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 11:39:38 +02:00
DevEnv nis2-agileandClaude Opus 4.8 0dc2a11040 [FEAT] Connettori per-azienda nella card cliente (Evidence Automation) - config in DB, secret nel vault
Richiesta utente: 'le credenziali si configurano nella card per ogni azienda cliente'.
- Migrazione 029: tabella org_connectors (config NON segreta + vault_key_alias + secret_status). NESSUN segreto nel DB.
- OrganizationController: listConnectors/saveConnector/deleteConnector + connectorOrgGuard (org_admin/compliance_manager propria org, o firm che la gestisce, o super_admin)
- Difesa: i campi segreti (client_secret/api_key/...) inviati vengono STRIPPATI prima del salvataggio (verificato E2E: non finiscono nel DB)
- saveConnector ritorna cli_hint col comando vault-cli per caricare il segreto (write-path vault = solo CLI admin, confermato leggendo server.js: solo GET /v1/credentials/*)
- UI: pannello 'Connettori' nella card di companies.html (8 tipi, tenant/client id, toggle attivo, stato segreto, modal)
- Route organizations/{id}/connectors GET/PUT/DELETE (type nel body)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 10:51:44 +02:00
DevEnv nis2-agileandClaude Opus 4.8 14c06c8881 [FEAT] Policy attestation + versioning/diff (P3 policy management)
- Migrazione 028: policy_versions (snapshot per diff/storico) + policy_attestations (presa visione per versione)
- approve() crea snapshot versione automaticamente
- attest (dipendente prende visione versione corrente), attestations (copertura % membri), pendingAttestations
- versions (storico), diff?from&to (added/removed line-by-line)
- Attestation version-aware: un nuovo bump versione richiede ri-attestazione (verificato E2E)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 10:20:59 +02:00
DevEnv nis2-agileandClaude Opus 4.8 1a5db30073 [FEAT] Self-assessment fornitori (P3 supply chain) - portale pubblico con token
- Migrazione 027: tabella supplier_questionnaires (token hash, risposte, score, risk_level, scadenza)
- SupplyChainController: sendQuestionnaire (JWT, genera link 30gg), publicQuestionnaire + submitPublicQuestionnaire (NO auth, token), questionnaireStatus
- 8 domande sicurezza Art.21.2.d (ISO27001/MFA/patching/backup/incident/access/encryption/subfornitori) pesate -> score 0-100 -> risk_level + aggiornamento suppliers.risk_score
- public/supplier-assessment.html: portale standalone (no login) per il fornitore
- Pulito route map supplychain (rimossi duplicati + entry malformata PueT + metodi inesistenti)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 10:19:01 +02:00
DevEnv nis2-agileandClaude Opus 4.8 1be3bd01a4 [FEAT] Risk quantitativo FAIR + KRI dashboard (P2)
Competizione coi GRC enterprise sul risk management quantitativo:
- FairService: simulazione Monte Carlo FAIR (PERT su TEF e Loss Magnitude),
  ALE in EUR con percentili P10/P50/P90 + istogramma, deterministico (seed da input)
- RiskController::computeFair -> POST /risks/{id}/fair (persiste parametri+ALE)
- RiskController::fairRegister -> GET /risks/fairRegister (portfolio ALE EUR)
- KRI: listKri/createKri/updateKri (GET/POST /risks/kri, PUT /risks/kri/{id})
  con stato semaforo green/amber/red su soglie+direzione
- Migrazione 026: risks += parametri FAIR + ale_min/ml/max/mean; nuova tabella kri

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 09:25:46 +02:00
DevEnv nis2-agileandClaude Opus 4.8 4924075142 [FEAT] Asset import CMDB/cloud + scoring automatico GV.OC-04 (P2)
- AssetScoringService::inferCriteria: euristica 6 criteri da campi CMDB
  (criticality, data_classification, internet_facing, dependencies, regulated)
- AssetController::import (JWT org_admin/compliance_manager) + bulkUpsert condiviso:
  upsert dedup su external_ref, scoring auto GV.OC-04, max 1000 asset/batch
- ServicesController::ingestAssets -> POST /services/assets-ingest (scope ingest:assets) per connettori CMDB/cloud
- Migrazione 025: assets += external_ref + discovery_source + indice univoco dedup
- Route POST:assetsIngest (services) + POST:import (assets)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 09:14:12 +02:00
DevEnv nis2-agileandClaude Opus 4.8 307993fbad [FEAT] Evidence Automation + Continuous Control Monitoring (P1)
Colma il gap competitivo vs Vanta/Drata (compliance automation):
- ServicesController::ingestEvidence -> POST /services/evidence-ingest (scope ingest:evidence)
  raccolta evidenze automatiche dai connettori (M365/Google/AWS/Azure/IdP/EDR/SIEM), batch fino a 200, upsert idempotente su external_ref
- recomputeControlMonitoring: ricalcolo monitoring_status (healthy/warning/stale/failing) per freschezza+esito
- controlsMonitoring -> GET /services/controls-monitoring (scope read:compliance): coverage + summary semafori
- Migrazione 024: tabella control_evidence_auto + compliance_controls.{monitoring_status,last_checked_at,freshness_days}
- Route POST:evidenceIngest, GET:controlsMonitoring

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 08:55:26 +02:00
DevEnv nis2-agileandClaude Opus 4.8 21909994c2 [FEAT] Ingestion incidenti SIEM/SOC/EDR (P1) -> endpoint /services/incidents-ingest
- ServicesController::ingestIncident: crea incidente Art.23 da alert esterno (scope ingest:incidents)
- Dedup su external_ref (org+ref), mapSeverity (CVSS/P1-P5/stringhe -> enum)
- Classificazione AI best-effort (classifyIncident: IS-1..4, severity, significativita)
- Deadline Art.23 (24h/72h/30g) su incidenti significativi + webhook dispatch
- Migrazione 023: incidents += source/source_system/external_ref + indice univoco dedup
- Route POST:incidentsIngest in index.php

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 08:41:57 +02:00
DevEnv nis2-agileandClaude Opus 4.8 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
DevEnv nis2-agileandClaude Opus 4.8 a7a21faa82 [FEAT] Knowledge Base RAG multi-livello (SYSTEM/FIRM/ORG) + Qdrant + Voyage
- KnowledgeBaseController: ingest, list, firmOrgs, search, delete
- VectorService (Qdrant + buildAuthzFilter), EmbedService (Voyage), RagService (pipeline)
- AIService::askWithRag con fallback graceful
- docker-compose: servizio qdrant + env Voyage (chiave da .env/vault, no hardcoded)
- SQL 012 consulting_firms, 013 firm_assignments + kb_uploaded_documents
- public/kb.html + kb.js (upload, lista, search preview)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 15:44:13 +02:00
DevEnv nis2-agileandClaude Opus 4.8 9b53ca3ba1 [FEAT] MktgLead getJsonBody + script import-feedback-to-nexus + seed demo agile-tech
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 15:42:05 +02:00
DevEnv nis2-agileandClaude Opus 4.7 e4f9e9179e [FEAT] Allineamento NIS2 ↔ TRPG (Fasi 1-5): SSO + Sessions + Reset + Impersonate + Branding
Implementazione completa del progetto allineamento alla suite Evix (TRPG/lg231),
basato sul doc canonico docs/GAP_TRPG_NIS2_ALIGNMENT.md (5 fasi, 18 gap).

Version 1.0.0 → 1.5.0

Fase 1 — SSO Federation (v1.1.0)
- Migration 015_sso_columns: users.sso_identity_id + password_version
- application/services/SsoHelper.php (client SSO dual-mode, cURL nativo, zero deps)
- AuthController::login() + changePassword() conditional SSO (SSO_MODE=local default)

Fase 2 — Multi-device Sessions (v1.2.0)
- Migration 016_active_sessions: tabella + refresh_tokens.session_jti
- BaseController::requireAuth() verifica jti + last_activity throttle + parseDeviceLabel
- login() genera jti, logout/changePassword revoca selettiva
- GET/DELETE /auth/sessions[/{id}]
- UI settings.html tab Sicurezza con lista device + revoca

Fase 3 — Password Reset + Tenant Switcher (v1.3.0)
- Migration 017_password_reset_tokens (TTL 30min, single-use)
- POST /auth/forgot-password (risposta opaca) + reset-password
- Pagine forgot-password.html + reset-password.html (con strength bar)
- EmailService::sendPasswordReset
- POST /auth/switchContext con rotazione JWT + organization_id claim
- Dropdown tenant in sidebar esposto a tutti gli utenti con ≥2 org

Fase 4 — Impersonate + Preferences + Versioning UI (v1.4.0)
- POST /auth/impersonate (super_admin o consulente stesso firm, TTL 1h, audit)
- Migration 018_user_preferences: users.theme/timezone/notif_email/notif_inapp
- GET/PUT /auth/preferences
- Sidebar footer mostra versione + changelog modal su click

Fase 5 — Branding white-label + Auth-gate (v1.5.0)
- Migration 019_firm_branding (logo/colori/brand_name per consulting firm)
- BrandingController GET /branding/current (auth opzionale) + PUT
- common.js auto-applica CSS variables al boot
- public/js/auth-gate.js (gate password client-side per docs riservati, da TRPG)

Skip motivati:
- G15 demo login: simulator esistenti coprono
- G18 refactor controllers: rinviato (~5gg, valore tecnico solo)

Cron sync SSO: AgileHub Ticket #220 aperto a team AGILEHUB per estendere
sso-password-sync.sh al DB nis2_agile_db. Prerequisito per switch SSO_MODE=dual.

Backup files: tutti i file modificati hanno .bak.pre-{fase}-{ts} sia in DEV
sia in /var/www/nis2-agile/.backups/ su Hetzner (rollback ready).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 13:18:35 +02:00
DevEnv nis2-agileandClaude Sonnet 4.6 1382530189 [FEAT] Sistema Segnalazioni & Risoluzione AI (feedback)
Adattato da alltax.it — il sistema più maturo testato con utenti reali.

Backend:
- FeedbackController: 6 endpoint (submit, mine, list, show, update, resolve)
- FeedbackService: createReport + classifyWithAI + broadcastResolution
- AIService::classifyFeedback() — 10s timeout, 500 token, JSON puro
- EmailService::sendFeedbackResolved() — broadcast email org
- DB migration 014: tabella feedback_reports

Frontend:
- feedback.js: FAB rosso #EF4444, modal 2 fasi (form → AI → password gate)
- Tab "Le mie segnalazioni" con badge status
- Auto-init su tutte le pagine autenticate (common.js::checkAuth)
- api.js: 6 metodi client; style.css: stili completi

Worker:
- scripts/feedback-worker.php: cron ogni 30 min
  → docker exec nis2-agile-devenv + Claude Code CLI
  → risoluzione autonoma con POST /api/feedback/{id}/resolve

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 08:51:52 +01:00
DevEnv nis2-agileandClaude Sonnet 4.6 4be541e9b5 [FIX] reset-demo.sql: gestione trigger audit_log + drop/recreate
Il trigger prevent_audit_log_delete blocca DELETE e interrompe lo script.
Fix: drop triggers prima di DELETE audit_logs, poi ricrea.
Richiede esecuzione con utente root MySQL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 09:51:40 +01:00
DevEnv nis2-agileandClaude Sonnet 4.6 eddc2fe79d [FIX] reset-demo.sql: adatta a struttura reale DB (incident_timeline, capa_actions, email_log, users)
- incident_timeline: join su incidents (no organization_id diretto)
- corrective_actions → capa_actions, non_conformity_id → ncr_id
- email_log: filtra per recipient LIKE '%.demo%' (no organization_id)
- users INSERT: first_name/last_name/status → full_name/is_active

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 09:04:48 +01:00
DevEnv nis2-agileandClaude Sonnet 4.6 c906a6eff3 [DB] Fix migration 013: MySQL 8.0 compat + script deploy idempotente
- Rimosso ADD COLUMN IF NOT EXISTS (non supportato MySQL 8.0 standard)
- Aggiunto deploy_013.sh: script bash idempotente con check information_schema

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 16:48:53 +01:00
DevEnv nis2-agileandClaude Sonnet 4.6 cb0988da27 [LICENSE] Gestione licenze marketing + campi commerciali estesi
- licenseExt.html: dashboard marketing per generare/gestire licenze
  Login JWT super_admin, stats strip (totali/usate/orgs/utenti),
  form genera con label/piano/durata/max-aziende/max-utenti/prezzo/reseller,
  lista paginata con filtri stato+canale, dettaglio modale, revoca/rigenera,
  export CSV e copia token/URL
- Migration 013: invites +max_users_per_org, +price_eur, +reseller_name
  organizations +license_max_users (da provisioning)
- InviteController::create() gestisce nuovi campi, validate() espone max_users_per_org
- ServicesController::provision() salva license_max_users nell'org

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 15:34:38 +01:00
DevEnv nis2-agileandClaude Sonnet 4.6 612befd66d [INVITE] Sistema inviti/licenze B2B + provisioning con invite_token
- InviteController: CRUD inviti (gen, list, show, revoke, rigenera, validate)
- Token inv_* sha256-hashed, one-shot o multi-use, canali, scadenza
- ServicesController::provision() accetta invite_token al posto di X-Provision-Secret
  Piano e durata forzati dall'invito, markUsed() chiaamto dopo provisioning riuscito
- index.php: routing /api/invites/* aggiunto (controller + action map)
- integrazioniext.html: nuovo tab "Inviti & Licenze" con flow completo, endpoints,
  esempi curl/php, guida lg231 aggiornata con sezione provisioning automatico

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 15:22:25 +01:00
DevEnv nis2-agileandClaude Sonnet 4.6 6933e1d3fb [INTEG] Provisioning B2B automatico + fix JWT helpers
- POST /api/services/provision: onboarding automatico tenant da lg231
  - X-Provision-Secret auth (master secret, non org-specific)
  - Crea org (con tutti i dati lg231: P.IVA, ATECO, sede, PEC, fatturato)
  - Crea admin user con password temporanea (must_change_password=1)
  - Genera API Key scope [read:all, write:all, admin:org, sso:login]
  - Emette JWT 2h per apertura immediata UI
  - Callback webhook a lg231 con api_key
  - Idempotent: stessa P.IVA → restituisce org esistente
  - Audit: org.provisioned severity=critical
- config.php: PROVISION_SECRET (env var)
- BaseController: base64UrlEncode/Decode da private → protected
- Migration 011: colonne provisioning + must_change_password + indexes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 15:02:11 +01:00
DevEnv nis2-agileandClaude Sonnet 4.6 3321509d02 [TEST] Bottone ⚡ Reset+Simula+Testa Tutto + preserva admin Benassati
- test-runner.php: bottone verde scuro in cima al tab Test che esegue
  reset DB → simulazioni → smoke test in sequenza
- reset-demo.sql: INSERT ON DUPLICATE KEY per cristiano.benassati@gmail.com
  (super_admin, Silvia1978!@) — sopravvive a qualsiasi reset
- Tab Credenziali: admin permanente in cima alla tabella

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 14:35:20 +01:00
DevEnv nis2-agileandClaude Sonnet 4.6 874eabb6fc [FEAT] Simulazioni Demo + Audit Trail Certificato SHA-256
- 5 scenari reali: Onboarding, Ransomware Art.23, Data Breach Supply Chain,
  Whistleblowing SCADA, Audit Hash Chain Verification
- simulate-nis2.php: 3 aziende (DataCore/MedClinic/EnerNet), 10 fasi, CLI+SSE
- AuditService.php: hash chain SHA-256 stile lg231 (prev_hash+entry_hash)
- Migration 010: prev_hash, entry_hash, severity, performed_by su audit_logs
- AuditController: GET chain-verify + GET export-certified
- reset-demo.sql: reset dati demo idempotente
- public/simulate.html: web runner SSE con console dark-theme
- Sidebar: link Simulazione Demo + Integrazioni

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 13:56:53 +01:00
DevEnv nis2-agileandClaude Sonnet 4.6 a8ef41dc35 [FIX] Migration SQL: INT NOT NULL per FK verso organizations/users (signed)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 13:22:08 +01:00
DevEnv nis2-agileandClaude Sonnet 4.6 86e9bdded2 [FEAT] Services API, Webhook, Whistleblowing, Normative + integrazioni
Sprint completo — prodotto presentation-ready:

Services API (read-only, API Key + scope):
- GET /api/services/status|compliance-summary|risks-feed|incidents-feed
- GET /api/services/controls-status|assets-critical|suppliers-risk|policies-approved
- GET /api/services/openapi (spec OpenAPI 3.0.3 JSON)

Webhook Outbound (Stripe-like HMAC-SHA256):
- CRUD api_keys + webhook_subscriptions (Settings → 2 nuovi tab)
- WebhookService: retry 3x backoff (0s/5min/30min), delivery log
- Trigger auto in IncidentController, RiskController, PolicyController
- Delivery log, test ping, processRetry

Nuovi moduli:
- WhistleblowingController (Art.32 NIS2): anonimato garantito, timeline, token tracking
- NormativeController: feed NIS2/ACN/DORA con ACK tracciato per audit

Frontend:
- whistleblowing.html: form submit anonimo/firmato + gestione CISO
- normative.html: feed con presa visione documentata + progress bar ACK
- public/docs/api.html: documentazione API dark theme (Swagger-like)
- settings.html: tab API Keys + tab Webhook
- integrations/: guide per lg231, SustainAI, AllRisk, SIEM (widget + codice)
- Sidebar: Segnalazioni + Normative aggiunte a common.js

DB: migration 007 (api_keys, webhook_subscriptions, webhook_deliveries),
    008 (whistleblowing_reports + timeline),
    009 (normative_updates + normative_ack + seed NIS2/ACN/DORA/ISO)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 13:20:24 +01:00
DevEnv nis2-agileandClaude Sonnet 4.6 f5884b32d3 [FIX] Migration 006: usa stored procedure per indici condizionali
Compatibilita' MySQL 8.0: rimosso CREATE INDEX IF NOT EXISTS,
rimosso DELIMITER per trigger (incompatibile con pipe stdin).
Migration semplificata con solo CREATE INDEX e ALTER TABLE IF NOT EXISTS.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 12:08:44 +01:00
DevEnv nis2-agileandClaude Sonnet 4.6 a5eb84108a [FIX] Migration 006: usa stored procedure per indici condizionali
Compatibilita' MySQL 8.0: CREATE INDEX IF NOT EXISTS non supportato,
uso procedura helper con check su information_schema.statistics

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 12:05:04 +01:00
DevEnv nis2-agileandClaude Sonnet 4.6 18dec35380 [FIX] Migration 006: fix sintassi CREATE INDEX per MySQL 8.0
Sostituito ALTER TABLE ADD INDEX IF NOT EXISTS con CREATE INDEX IF NOT EXISTS
per compatibilita' MySQL 8.0.x

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 12:04:16 +01:00
DevEnv nis2-agileandClaude Sonnet 4.6 782389849f [SEC+UX] Hardening sicurezza + miglioramenti UX pre-audit
SICUREZZA:
- index.php: rimosso CORS wildcard in debug mode (solo origini autorizzate)
- AuthController: getClientIP() con X-Forwarded-For sicuro (proxy-aware)
- AuthController: refresh token con SELECT FOR UPDATE in transazione atomica
- AIService: anonimizzazione dati org nei prompt Anthropic API (no nome/fatturato)

UX AUDIT-READY:
- dashboard.html: gauge rinominato 'Avanzamento implementazione misure Art.21'
- incidents.html: decision tree Art.23 con 5 criteri per 'Is Significant?'
- policies.html: banner warning obbligatorio su bozze generate da AI
- risks.html: tooltip dettagliati scala Likelihood/Impact (ISO 27005)
- assessment.html: progress bar % completamento risposta domande

DB:
- migration 006: indici performance + audit_log immutabile (trigger) + soft delete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 12:01:33 +01:00