Commit Graph
153 Commits
Author SHA1 Message Date
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 dcbce3de5c [FIX] Help online: rimossa icona FontAwesome morta (fa-comment-alt) post-swap V2
- public/js/help.js: rimossa unica occorrenza <i class="fas fa-comment-alt"></i>
  (residuo non renderizzato dopo lo swap a Bootstrap Italia V2) + collassato lo
  spazio ridondante, nella guida "Come aprire una segnalazione".
- Cache-buster mirato: help.js?v=20260613 -> 20260614 su 35 pagine public/*.html
  (sibling common-bi.js/i18n.js/common.js/api.js/style.css lasciati invariati).
- public/version.json: 1.14.0 -> 1.14.1.
- Nessuna modifica a dati o schema DB. Ticket #367 (collaudo release supervisore).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 13:33:29 +02:00
DevEnv nis2-agile ad3532a90a [FIX] Pannello ARIA: chiusura (X+Esc) robusta + niente sovrapposizione ai pallini (stile TRPG)
Aprendo il pannello ARIA ora si nascondono nx-bar (campana/supporto) + ai-chat-fab -> niente overlap;
la X e Esc chiudono e ripristinano i pallini. Prima la X era fragile e il pannello copriva i bottoni.
Bump common.js?v=20260613d. (TRPG usa ai-assistant.js con stesso pattern toggle/hide.)
2026-06-14 08:56:08 +02:00
DevEnv nis2-agile 4341d86c4c [UI] Allineato a TRPG/AgileHub: rimosso auto-inject feedback.js (doppione) -> solo bug-reporter
NIS2 aveva DUE sistemi feedback: feedback.js (pill cyan 'Segnala/Feedback' + modale scuro) + bug-reporter
AgileHub (campana+supporto). TRPG/ALLTAX usano solo bug-reporter (verificato: trpg ha app/js/bug-reporter.js,
nessun feedback.js). Rimosso l'auto-inject di feedback.js da common.js -> resta il trittico pallini
(notifiche + supporto + ARIA) come la suite. Verificato headless: feedback-fab assente, nx-bell/nx-bug/ai-chat
presenti. Bump common.js?v=20260613c (auto-refetch). feedback.js/api restano nel repo, non iniettati.
2026-06-14 08:33:13 +02:00
DevEnv nis2-agile 30cac8479a [FIX] Modali showModal() invisibili su V2 (solo sfondo grigio): conflitto .modal con Bootstrap Italia
BI introduce .modal{display:none;position:fixed} che nascondeva i nostri modali custom (help, genera-AI,
conferme, crea-rischio...) -> si vedeva solo il backdrop grigio. Aggiunto override scoped
'.modal-overlay .modal{display:block;position:relative;...}' in style.css (specificità > BI, caricato dopo).
Verificato headless: modale help display:block height:765 visible:true. Bump style.css?v=20260613b (auto-refetch).
2026-06-14 08:00:13 +02:00
DevEnv nis2-agile 959ede968d [FIX] Feedback widget: cablata X-API-Key NIS2 (nis2_ak_dev_...) in common.js + bump common.js?v=20260613b
Risolve il 401 del bug-reporter ('Header X-API-Key o Authorization Bearer richiesto'): il widget ora
manda X-API-Key -> gateway ticket AgileHub OK (tenant 7, provenance corretta). Chiave fornita da AgileHub
(full tenant-key, va nel JS pubblico = stesso compromesso TRPG/ALLTAX; debito 'token low-priv' rimandato).
Bump versione common.js -> auto-refetch senza hard-refresh.
2026-06-13 19:21:56 +02:00
DevEnv nis2-agile 3c484fe604 [FIX] Cache-buster ?v=20260613 sui JS/CSS modificati (help/common/common-bi/i18n/feedback/style/demo) + bump bug-reporter + demo assets
Risolve 'le modifiche non si vedono': /js/help.js era senza ?v -> browser serviva la versione cached
vecchia. 281 ref su 57 pagine + injection demo/bug-reporter aggiornate.
2026-06-13 19:17:59 +02:00
DevEnv nis2-agile b49044c57f [FIX] FAB segnalazione/ARIA: icone FontAwesome -> SVG inline (regressione swap BI) + slot data-api-key
Icone: bug-reporter.js (nx-bell fa-bell, nx-bug fa-life-ring) + common.js ai-chat-fab/header/send
(fa-wand-magic-sparkles, fa-paper-plane) erano FA, rimosso dallo swap BI -> cerchi vuoti. Sostituite con
SVG inline (currentColor, self-contained). Verificato headless: 3 FAB renderizzano svg.
Auth widget: cablato s.dataset.apiKey <- window.NEXUS_WIDGET_API_KEY (X-API-Key gateway AgileHub, era
assente -> 401). _detectUser ora legge anche nis2_access_token. SERVE la chiave X-API-Key da AgileHub.
2026-06-13 18:49:49 +02:00
DevEnv nis2-agile 8c0074aa5d [DEMO] Polish step 9: cross-analysis (gate consultant) -> Assets/GV.OC-04 (visibile al demo-user)
cross-analysis e gate-ato consultant/super_admin: per il demo-user (compliance_manager) renderizza
'riservata ai Consulenti/INSUFFICIENT_ROLE' e NON costruisce #chat-input/#quick-qs/#tab-chat -> highlight
impossibili. Sostituito con Assets (relevance scoring GV.OC-04): feature distintiva NIS2, pienamente
visibile, gia nel dataset 996001. Highlight #asset-stats + #assets-container verificati in browser reale
(ok:true, errs:[]). L'AI resta dimostrata da ARIA-narratore + AI gap analysis (step 2).
RICHIEDE re-tag RAG lato AgileHub: step9 -> mappa 08_assets (era 15_cross-analysis).
2026-06-13 13:02:34 +02:00
DevEnv nis2-agile 3ef69dfd74 [DEMO] Run 10-step browser reale: fix manifest step 9 (cross-analysis -> #portfolio-header)
Harness same-origin sui 10 step ha trovato 1 difetto reale: step 9 puntava a #quick-qs/#chat-input che
il JS non renderizza (tab chat non-default, assenti nel DOM) -> ri-ancorato a #portfolio-header (presente,
highlightApplied:true confermato). Gli altri 'NOT_FOUND' erano artefatti --virtual-time-budget: incidents
#crit-*, policies #ai-*, supply-chain #assessment-live-score sono presenti nel DOM renderizzato (dump 7s),
il vero avatar li trova al loro at_ms. 10/10 step ora risolvibili.
2026-06-13 12:51:07 +02:00
DevEnv nis2-agile fcf8b0963b [DEMO] Fix 2 bug SPA-side trovati al collaudo browser headless (auth in-memory + boot seed)
Il collaudo curl validava il backend ma non l'esecuzione JS nel browser. Con google-chrome --dump-dom:
1) common-bi.js: sync api.token/orgId IN-MEMORY (api.js crea l'istanza prima leggendo localStorage vuoto
   → checkAuth vedeva token null → redirect a login). Ora la SPA si auto-autentica.
2) demo-mode.js boot(): non bloccare sul seed quando HMAC_ENFORCE=false (cross-origin il seed non arriva;
   non serve, HMAC off) → il runtime (banner/listener/ready) ora parte.
Verificato headless su dashboard/risks/incidents: login:0, banner+nis2-demo-on presenti.
2026-06-13 11:30:55 +02:00
DevEnv nis2-agile 3e8a90f969 [DEMO] Sottodominio: DEMO_BASE -> nis2.dimostrazione.agile.software + origin allowlist postMessage
AgileHub ha consegnato il reverse-proxy nis2.dimostrazione.agile.software -> nis2.agile.software.
- DemoController.DEMO_BASE default = sottodominio (spa_iframe_url/manifest/credentials lì); env DEMO_BASE_URL override.
- demo-mode.js: origin-check ora ALLOWLIST (dimostrazione + nis2.dimostrazione) robusto alla topologia widget;
  outbound postMessage mirato all'origin reale del parent (ancestorOrigins/captured).
2026-06-13 10:31:46 +02:00
DevEnv nis2-agile 460d435a47 [DEMO] Auto-auth SPA demo: demo_jwt nel fragment spa_iframe_url + bootstrap token sincrono in common-bi.js
Chiude il gap auth: la SPA demo si auto-autentica col demo_jwt (token API nis2_access_token + org dal
payload) PRIMA di checkAuth, cross-origin (niente sessionStorage same-origin). spa_iframe_url ora atterra
su /dashboard.html?demo=..#djwt=... DemoController.DEMO_BASE override via env DEMO_BASE_URL (switch a
sottodominio senza codice). USR2 richiesto per DemoController.
2026-06-13 10:00:28 +02:00
DevEnv nis2-agile a851caf669 [DEMO] HMAC per-messaggio OFF: canale runtime-avatar e origin-verified (chiarimento AgileHub 2026-06-13)
Il postMessage widget->SPA e il canale runtime avatar (non external/v1): server-to-server usa
X-Internal-Key (gia su reset-dataset), il postMessage si fida di ev.origin (same-origin). HMAC verify
resta flag-gated (HMAC_ENFORCE=false) da riaccendere solo se al collaudo il widget firma.
2026-06-13 09:39:05 +02:00
DevEnv nis2-agileandClaude Opus 4.8 d6d61885b4 [DEMO] Manifest tour (punto 4): nis2-tour-2026.json — 10 step ancorati a id reali verificati
Steps: dashboard/assessment/acn-gap/risks/incidents/policies/supply-chain/isms/cross-analysis/reports.
Highlight su selettori ESISTENTI verificati dalle mappe (non i 132 da-aggiungere). Narrazione senza
numeri inventati (ARIA usa RAG sul dataset 996001). express_subset [1,4,5,9]. Servito da GET /api/demo/manifest.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 09:00:04 +02:00
DevEnv nis2-agileandClaude Opus 4.8 d16fdd2c02 [DEMO] Frontend demo-mode (punto 4): demo-mode.js + demo-selectors.js + demo.css + hook ?demo=
Avatar di prodotto, product-demo-protocol v1.0.1 (NIS2 multi-page):
- public/js/demo-mode.js: runtime canale postMessage (inbound navigate/highlight/scroll_to/
  trigger_action/open_tab/...; outbound ready/spa_state_changed/step_animation_done/...),
  verifica origin+HMAC (chiave SHA-256(jwt:seed:demo-control-channel))+idempotency, banner read-only.
- public/js/demo-selectors.js: whitelist 17 viste (view->url) + azioni read-only sicure.
- public/css/demo.css: highlight pulse-blue/halo + banner.
- common-bi.js: hook che inietta gli asset SOLO con ?demo= (no-op per utenti normali).

NOTE: (a) HMAC canonical del MESSAGGIO da riconciliare con AgileHub al collaudo (canonicalize()).
(b) manca il manifest (steps+selettori) — dipende dagli id stabili in corso.
node --check OK su tutti.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 08:56:36 +02:00
DevEnv nis2-agileandClaude Opus 4.8 4dfab2a391 [FORMAZIONE] Avatar di prodotto — mappa-logica COMPLETA (22 viste) + SELETTORI_DEMO + tassonomia corso + fix kb.js
Deliverable formazione-first (DESIGN_AVATAR_FORMAZIONE / product-demo-complete):
- docs/mappa-logica/01..22_*.md: tutte le viste app V2 mappate (formato canonico standard §2),
  selettori VERIFICATI sul DOM reale, endpoint verificati su api.js/script, gate ruolo dai controller
- docs/mappa-logica/SELETTORI_DEMO.md: registry canonico (22 viste, 131 visualizzazione + 89 azioni)
  + worklist consolidata 132 id stabili da aggiungere (modifiche chirurgiche future)
- docs/formazione/TASSONOMIA_CORSO_NIS2.{md,json}: 10 moduli / 28 lezioni / ~7h45, prerequisiti+durate,
  esame con soglia 80%, sandbox 'prova tu' org 996002
- fix kb.js: ingest scope=ORG ora invia organization_id (prima 422 KB_ORG_REQUIRED) — bug trovato da A2

Prodotto con 4 trittici di agenti (A1 esecutore -> A2 revisore -> A3 controllore avversariale):
A2: ~14 correzioni (cross-ref, gate ruolo, comportamenti); A3 PASS: 38 selettori campionati 0 rotti,
18 endpoint reali, 0 violazioni normative (Allegati 3/4, IS-4, '1 mese', PII.* interna), 9 claim verificati.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 18:50:19 +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-agileandClaude Opus 4.8 1c64211685 [UI] SWAP V2: Bootstrap Italia ora UFFICIALE su 27 pagine app (kill della vecchia UI)
Promosse le pagine -bi a nomi ufficiali (contenuto BI), link -bi->plain, titoli '(BI)' rimossi.
La vecchia UI delle pagine app e sostituita. Backup: git (commit 36967f9) + /tmp/nis2-v1-backup.

Promosse (27): auth (login/register/onboarding/forgot/reset) + app (dashboard/assessment/
risks/incidents/policies/supply-chain/training/assets/reports/settings/isms/acn-gap/normative/
whistleblowing/kb/cross-analysis/service-continuity/guida/companies) + admin (index/orgs/users).
common-bi.js: sidebar BI ora linka le pagine ufficiali.

ESCLUSA: index.html (landing marketing 1298 righe) -> conversione dedicata a parte (la -bi
era 557 righe, rischio perdita contenuti). Pagine marketing/demo (presentation/simulate/
workflow/architecture/index-en) restano vecchio stile (fuori scope app autenticata).

Verifica produzione: 27/27 servite 200 con BI, 0 link -bi residui, 0 '(BI)' nei titoli,
auth intatta (401 su pwd errata), common-bi.js node --check OK.

Rollback: git revert HEAD  (oppure ripristino da /tmp/nis2-v1-backup).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 14:49:15 +02:00
DevEnv nis2-agileandClaude Opus 4.8 36967f9452 [UI] V2 completezza Bootstrap Italia: 11 pagine app -bi mancanti + companies + help.js + KB doc
Completa la copertura V2 al 100% delle pagine app autenticate (pre-swap).
Additivo: nessun file live HTML promosso ancora (lo swap e separato).

- 9 pagine app -bi: isms, acn-gap, normative, whistleblowing, kb, cross-analysis,
  service-continuity (doc standalone), guida, companies
- admin/{index,organizations,users}-bi.html (path corretti, common-bi.js)
- help.js: +89 righe help contestuale pagine V2 (vincolo fonti certe)
- docs/kb/V2_UI_NAVIGAZIONE.md: doc UI/navigazione V2 per la KB AI (ARIA)
- Verifica: tutte servite 200, 0 CDN/FontAwesome, sprite validi, parita ID

Prodotto via Workflow a trittici (run wf_c4962fbe-93f) + fix manuale companies/sprite.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 14:46:37 +02:00
DevEnv nis2-agileandClaude Opus 4.8 4d676f2e21 [UI] Bootstrap Italia rollout (Opzione B) — vendor self-hostato + 16 pagine -bi + sidebar BI
Pipeline a trittici (Esecutore->Revisore->Controllore avversariale), 6 trittici T1-T6.
Tutto ADDITIVO: nessuna pagina/JS live modificata, produzione intatta. Swap non incluso.

- public/vendor/bootstrap-italia/ : BI v2.18.1 self-hostato (CSS+JS bundle+16 woff2+sprite), MAI CDN
- 16 pagine *-bi.html (login/register/onboarding/forgot/reset/index + dashboard/assessment/
  risks/incidents/policies/supply-chain/training/assets/reports/settings)
- public/js/common-bi.js : sidebar/topbar in markup BI (additivo, riusa stessi ID + common.js)
- Verifica sul path servito reale: 16/16 -> 200, 0 CDN, 0 FontAwesome residui, parita ID/hook completa, WCAG AA
- docs/SISTEMA_TRITTICI_AGENTI.md : design del sistema a trittici

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 13:31:53 +02:00
DevEnv nis2-agileandClaude Opus 4.8 06c94b3c05 [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>
2026-06-12 09:54:14 +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 5785ba516d [FIX] Landing: checkbox consenso largo 100% (causa vera del testo incolonnato)
La regola .form-group input {width:100%} si applicava ANCHE al checkbox del
consenso, gonfiandolo a tutta la riga e spingendo il testo a capo parola per
parola. Aggiunto override .consent-label input[type=checkbox] {width:16px}.
Ora testo in linea su 2 righe, colore normale, link Privacy policy + asterisco cyan.

Verificato con render headless Chrome.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 14:43:34 +02:00
DevEnv nis2-agileandClaude Opus 4.8 847e28b8cf [FIX] Landing: testo consenso GDPR incolonnato e tutto rosso nel form
Due bug nel form 'Richiedi accesso':
1. La regola generica .form-group label span {color:red} (pensata per l'asterisco
   obbligatorio) coloravadi rosso TUTTO il testo del consenso.
2. Lo <span> dentro il label flex non aveva larghezza -> andava a capo parola per
   parola (incolonnato verticalmente).
Fix: classe dedicata .consent-label con span flex:1 + min-width:0 + colore normale;
l'asterisco resta cyan. Testo ora in linea accanto al checkbox.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 14:33:06 +02:00
DevEnv nis2-agileandClaude Opus 4.8 68346fec05 [DOCS] Presentation: rimossi riferimenti a costi/abbonamento
Slide 9 (ex 'Modello commerciale') -> 'Edizioni': tolto 'abbonamento annuale /
nessun costo per utente', i 3 tier descrivono solo perimetro funzionale per
profilo (PMI/Enterprise/Consulente). Contatti: 'Pricing: abbonamento annuale'
-> 'Attivazione: su richiesta, offerta personalizzata'. Niente accenni a prezzi
o gratuita.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 14:20:32 +02:00
DevEnv nis2-agileandClaude Opus 4.8 8aa1f8f9c1 [DOCS] Landing: rimosso riferimento a carta di credito/gratuita nel CTA
"Nessuna carta di credito richiesta" suggeriva erroneamente che il servizio
sia gratuito. Sostituito con messaggio neutro su accesso controllato + rapidita
operativa, senza accennare a costi o modalita di pagamento.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 14:11:19 +02:00
DevEnv nis2-agileandClaude Opus 4.8 8dd5bccba7 [DOCS] Landing: aggiornata alle reali funzionalita, valorizzati elementi distintivi
Linguaggio tecnico ma chiaro, allineato al prodotto reale (v1.13.0):
- Hero: subtitle con doppia gap analysis (Art.21 + misure di base ACN) + AI consulente;
  stats -> 116 requisiti ACN mappati, 12 moduli, Art.23, RAG su fonti certe.
- Moduli (8 -> 12): NUOVA card "Gap Analysis ACN" in evidenza (37/87 importanti,
  43/116 essenziali, Framework Nazionale GV/ID/PR/DE/RS/RC); Gap Analysis Art.21
  separata; Supply Chain con Portale Fornitori (OTP/magic-link, campagne ricorrenti);
  AI Consulente RAG (203 requisiti, no allucinazioni normative); Knowledge Base
  multi-livello (vendor/studio/org con isolamento).
- Step "come funziona", meta description e trust-items allineati.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 13:57:26 +02:00
DevEnv nis2-agileandClaude Opus 4.8 d6924a30c1 [FIX] Gap Analysis ACN: bug da review avversariale (4 agenti)
#1 CRITICO aiAnalyze: askWithRag ritorna ['answer','sources','rag_used'], non
   una stringa. Ora estrae 'answer' (ai_summary) e salva 'sources' in
   ai_recommendations. Prima salvava il JSON intero in ai_summary.
#2 ALTO corpus RAG: acn_requirements.json aveva 188/203 testi TRONCATI alla
   prima riga PDF (es. GV.PO-01#1: 84 char invece di 838). Rigenerato dai testi
   INTEGRALI di acn_measures.json (87+116, zero troncamenti). Ri-ingest Qdrant.
#3 MEDIO catalog(): org non classificata dava entity_level=null + warning PHP
   $totals[null] + TypeError frontend. Ora 422 ENTITY_LEVEL_REQUIRED come create().
#4 MEDIO guida cap-5 GV.RR-04: "figure chiave dell'organigramma" era errato e
   auto-contraddittorio -> "personale autorizzato + amministratori di sistema,
   valutazione esperienza/capacita/affidabilita" (allineato testo ACN).
#5 BASSI: openAcn try/catch (no unhandled rejection su Riprendi); badge
   importante/essenziale IT/EN; overall_score=null (non 0.0) se tutti N/A.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 12:18:25 +02:00
DevEnv nis2-agileandClaude Opus 4.8 035df49e07 [DOCS] Gate Gap Analysis ACN: guida cap-5b + help + i18n IT/EN + version 1.13.0
- guida.html: nuovo cap-5b "Gap Analysis ACN" (importanti vs essenziali con
  tabella 37/87 e 43/116, 6 funzioni FW, scoring, piano d'azione, quale-uso-quando).
- help.js: voce contestuale 'acn' + mappature page->help->guida (cap-5b).
- i18n.js: nav.acn_gap + 15 chiavi acn.* IT/EN.
- version.json -> 1.13.0.
- AI/KB: gia a posto — nis2_sources.php cita Allegati 1/2 (37/87, 43/116) con
  GV.RR-04/GV.PO-01; 203 requisiti ACN gia in Qdrant per il grounding.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 08:18:40 +02:00
DevEnv nis2-agileandClaude Opus 4.8 91043d7391 [FEAT] Gap Analysis ACN: frontend (acn-gap.html + sidebar + api.js)
- public/acn-gap.html: catalogo requisiti consultabile, wizard per funzione FW
  con accordion misure/requisiti, opzioni attuato/parziale/non attuato/N.A.,
  autosave batch debounce, risultati con punteggio per funzione + piano d'azione
  gap + analisi AI. Badge livello soggetto (importante/essenziale). IT/EN inline.
- api.js: metodi acn* (catalog/list/create/requirements/respond/complete/report/
  aiAnalyze) che spacchettano l'envelope e lanciano errore su success=false.
- common.js: voce sidebar "Gap Analysis ACN".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 08:10:50 +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 2dced3f9b9 [DOCS] Gate Fasi 2-4: guida + help + version per campagne/portale fornitori
- guida.html cap-9: sezioni "Campagne, scadenze e promemoria automatici" e
  "Portale fornitori (accesso senza password)" + nota privacy GDPR Art.28.
- help.js supply-chain: voce "Campagne, scadenze e portale fornitori".
- version.json -> 1.12.0 (modulo questionari fornitori completo Fasi 2-4 +
  203 requisiti ACN nella KB AI).

HTML guida bilanciato, help.js node --check OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 17:44:16 +02:00
DevEnv nis2-agileandClaude Opus 4.8 78dcb412ad [FEAT] Fase 3+4 frontend: supplier-portal.html (OTP/magic-link + compilazione)
Portale fornitore pubblico self-contained (CSS+JS inline, noindex):
- Auth: richiesta OTP (risposta opaca), verifica codice con errori specifici +
  countdown reinvio 60s, magic-link da ?magic= (consumo su click), sessione
  JWT supplier in sessionStorage (4h).
- Dashboard: 1 questionario aperto -> diretto, multi -> lista con badge scadenza.
- Compilazione (Fase 4): tutti i tipi domanda (yes_no_partial, single/multi_choice,
  scale_1_5 con etichette estremi, number, text, file) + "Non applicabile";
  progress bar, badge scadenza sticky, help_text + nis2_ref visibili.
- Autosave PATCH debounce 800ms + "bozza salvata"; salva bozza vs invia definitivo
  con conferma + validazione obbligatorie client.
- Ricevuta: conferma + score solo se show_score. Footer GDPR Art.28.
- a11y: input nativi, OTP autocomplete=one-time-code inputmode=numeric, target >=44px.

Inline JS validato (node --check). File statico -> live via nginx.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 17:42:23 +02:00
DevEnv nis2-agileandClaude Opus 4.8 de09af6d7e [FEAT] Fase 3 backend: portale fornitore OTP/magic-link (SupplierPortalController)
Auth fornitore SEPARATA dagli utenti interni (supplier_users/otp/sessions, mig 034):
- SUPPLIER_JWT_SECRET dedicato, aud=supplier-portal, claim sp_uid/supplier_id/org_id
  (mai user_id); requireSupplierSession() verifica jti in supplier_sessions
  (revocabile), non tocca users/active_sessions.
- OTP 8 cifre SHA-256, 15min, lockout persistente (attempts+locked_until),
  invalidazione OTP precedenti, hash_equals, rate-limit email+IP.
- magic-link 32B hashed single-use (consumo atomico solo su verify).
- request-otp risposta opaca anti-enumerazione.
- OTP via EmailService::sendViaTemplate (/api/emails/send, fuori da email_log).
- Endpoint: requestOtp/verifyOtp (no auth) + me/getQuestionnaire/saveAnswers
  (PATCH autosave)/submitQuestionnaire. Ownership campaign.supplier_id==session (no IDOR).
- Scoring per-vulnerabilita (Art.21.3), snapshot domande immutabile.
- config: SUPPLIER_JWT_SECRET + PATCH in CORS_ALLOWED_METHODS.
- routes: controllerMap + actionMap supplier-portal.

php -l OK su tutti. Tabelle 034 gia' applicate su host.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 17:40:20 +02:00
DevEnv nis2-agileandClaude Opus 4.8 7baa596b37 [FEAT] Fase 2 backend: campagne questionario (questionnaire_campaigns) + scadenze/ricorrenze
- createCampaign(supplierId): invia un template a un fornitore via questionnaire_campaigns
  (token sq_ retrocompat, scadenza/ricorrenza/reminder_offsets configurabili, crea
  supplier_user per accesso OTP, email invito col link al portale). Migrazioni 034+035
  applicate su host.
- campaigns(): cruscotto con semaforo scadenze (success/warning<=7gg/danger scaduto)
  + answers_count per campagna.
- computeNextReminder(): helper per il prossimo reminder dagli offset.
- Route: GET:campaigns, POST:{id}/campaigns. api.js: getQuestionnaireCampaigns,
  createQuestionnaireCampaign.

Smoke: rotte 401 (router+auth ok). php -l + node --check OK. USR2 applicato.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 17:14:24 +02:00
DevEnv nis2-agileandClaude Opus 4.8 43a7180957 [DOCS] Help: HelpSystem.init su normative + companies (edit prima falliti)
Nel commit 3e5b75b gli edit a normative.html e companies.html erano falliti
(file-not-read / string-not-found): il pulsante '?' non partiva. Ora corretti.
Verificato: tutte e 4 le pagine (whistleblowing/normative/companies/kb) hanno
help.js + HelpSystem.init=1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 16:42:08 +02:00
DevEnv nis2-agileandClaude Opus 4.8 3e5b75bd35 [DOCS] Help contestuale cablato su whistleblowing/normative/companies/kb
Completata la rifinitura help: i 4 moduli che avevano contenuto (commit c1d3328)
ma non il pulsante '?' ora chiamano HelpSystem.init().
- whistleblowing/normative: aggiunto HelpSystem.init() (help.js gia' incluso).
- companies: aggiunti include i18n.js + help.js + HelpSystem.init().
- kb: aggiunto include help.js + HelpSystem.init().

Ora ogni modulo della piattaforma ha aiuto contestuale. version 1.11.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 16:40:57 +02:00
DevEnv nis2-agileandClaude Opus 4.8 c1d3328408 [DOCS] Help contestuale: aggiunti 4 moduli (whistleblowing, normative, kb, companies)
Contenuto help per i 4 moduli che ne erano privi (sezioni + references a fonti reali:
D.Lgs.24/2023 per whistleblowing, Art.20-21 per normative, RAG per kb, multi-tenant
per companies). Aggiunte voci in _pageMap e _guideAnchor. Verificato eseguendo help.js
con node: getAvailablePages() = 16 (12 + 4 nuovi), tutti e 4 presenti, sintassi valida.

NOTA: il cablaggio di help.js nelle 4 pagine HTML (script include + HelpSystem.init)
e' ancora da fare per rendere visibile il pulsante '?' su quelle pagine.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 16:38:30 +02:00
DevEnv nis2-agileandClaude Opus 4.8 e269fb108f [SEC] Redatta chiave API mktg esposta in pagine pubbliche (F1 security audit)
La chiave di produzione nis2_mktg_... (scope admin:licenses) era in chiaro in
mktg-api-doc.html e integrazioniext.html, servite pubblicamente -> chiunque poteva
ottenere una chiave di gestione licenze B2B. Sostituita con placeholder
nis2_mktg_xxxxx in entrambe le pagine (6 occorrenze totali).

NOTA: la chiave reale va ANCORA RUOTATA nel DB (api_keys) in coordinamento con
mktg-agile, poiche' resta nella history git e potenzialmente nota. Questo commit
elimina solo l'esposizione web continua.

Trovato da audit sicurezza multi-agente (F1, priorita' top).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 16:16:53 +02:00
DevEnv nis2-agileandClaude Opus 4.8 54a9c0987f [FIX] Precisione normativa: relazione finale +1 mese DALLA NOTIFICA + guida allineata
Da test multi-agente (aderenza normativa):
- IncidentController: final_report_due calcolato come detected+72h+1mese (= 1 mese
  dalla notifica, Art.23.4 lett.d), non detected+30gg. Allineato create() e update().
- guida.html: "40+ domande" -> "26 domande GV.SC" (numero reale del template NIS2 base);
  etichetta "Report Finale (30gg)" -> "(1 mese dalla notifica)".

Esito review 10 agenti: app solida (0 SQLi/IDOR/XSS cross-tenant, JWT/refresh ok,
DB integro 032/033 applicate, 0 citazioni normative inventate, Allegato 3/4 corretto).

php -l OK. version 1.10.7.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 16:13:21 +02:00
DevEnv nis2-agileandClaude Opus 4.8 8a55194b2f [FIX] Knowledge Base: token key errata (access_token->nis2_access_token) + init mancante
Bug CRITICO da test multi-agente: kb.js::getJwt() leggeva localStorage 'access_token'
ma l'app salva il JWT sotto 'nis2_access_token' -> ogni chiamata KB inviava
Authorization: Bearer (vuoto) -> 401 -> pagina KB completamente inutilizzabile
(upload/list/search/delete). Stesso pattern del bug this.delete.
Inoltre kb.html non aveva il blocco init (checkAuth/loadSidebar/I18n.init) presente
in tutte le altre pagine -> sidebar vuota e nessun redirect a login.

Fix: kb.js usa nis2_access_token; kb.html aggiunge i18n.js + init auth/chrome.
node --check OK. version 1.10.6.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 15:11:37 +02:00
DevEnv nis2-agileandClaude Opus 4.8 4ab549fc0c [FIX] AI P0 da test multi-agente: anonimizzazione + grounding + dim 512
- suggestRisks: usa employeeRange() invece di employee_count esatto nel prompt
  (coerenza anonimizzazione con gli altri metodi verso Anthropic).
- crossOrgAnalysis: era l'unico metodo con affermazioni normative senza il blocco
  fonti certe nel system prompt -> ora lo inietta (regole 1-5, no invenzioni,
  orientamento non vincolante).
- EmbedService: commenti "1024 dim" -> 512 (il codice forza output_dimension=512,
  coerente con la collection nis2_kb size=512).
- VectorService::ensureCollection default 1024 -> 512: rischio latente di creare
  una collection incompatibile se chiamato senza argomenti.

php -l OK su tutti e 3. version 1.10.5.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 15:04:33 +02:00
DevEnv nis2-agileandClaude Opus 4.8 c134a2d52a [FIX] Auth CRITICI da test multi-agente: register senza jti + revoca sessione singola
CRITICO #2 — register() generava il token SENZA jti, ma requireAuth lo rifiuta
(JWT_NO_JTI): l'utente appena registrato veniva sbattuto fuori al primo
getMe/completeOnboarding e doveva rifare login. Ora register crea una riga
active_sessions con jti e genera access+refresh token col jti, come login().

CRITICO #1 — DELETE /auth/sessions/<jti> (revoca sessione singola) tornava 404:
il jti è esadecimale (non numerico), il router cadeva nel ramo "nome composto"
e generava solo {action}/{camelResource}, mai {action}/{id}. Aggiunto fallback
{action}/{id} con id passato come STRINGA (revokeSession(string $id) lo accetta).
Il candidato composito resta primo, quindi evidence/upload ecc. non si rompono.

php -l OK su entrambi. version 1.10.4.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 15:01:22 +02:00
DevEnv nis2-agileandClaude Opus 4.8 2037cecaba [FIX] Test multi-agente: dashboard gauge + risks backToList/loadFair
- dashboard: complianceScore ora ritorna 'score' (overall_score ultimo assessment);
  la gauge usa avg_implementation se >0, altrimenti il punteggio assessment.
  Prima mostrava 0% per org con gap analysis ma senza modulo controlli (H2).
- risks.html backToList(): ripristina la vista corrente tra le 4 (table/matrix/fair/kri),
  prima cadeva sempre su table/matrix (H1); renderDetail nasconde tutte e 4.
- risks.html loadFair(): legge risksRes.data.items (endpoint paginato), prima
  risksRes.data.risks era undefined e il dropdown FAIR restava vuoto (M1).

php -l + node --check OK. version 1.10.3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 14:56:10 +02:00
DevEnv nis2-agileandClaude Opus 4.8 4d9153b36f [FIX] supply-chain: selettore modale errato (#app-modal -> #modal-overlay)
Bug live introdotto in v1.10.0: le viste Categorie e Template usavano
querySelector('#app-modal .modal-body') ma showModal (common.js) crea l'overlay
con id='modal-overlay'. Il selettore restituiva null -> le modali non si
popolavano (lista template/categorie vuota dopo il loading). Corretto a
'#modal-overlay .modal-body' (5 occorrenze). Trovato durante il test multi-agente.

Inline JS validato. version 1.10.2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 14:40:03 +02:00
DevEnv nis2-agileandClaude Opus 4.8 b7f361b87c [FEAT] Supply chain UI: i18n sp.* IT/EN + import mostra errors[] dettaglio righe scartate
- public/js/i18n.js: +38 chiavi sp.* (IT+EN) per pulsanti header, categorie, template, import.
- supply-chain.html: data-i18n sui 4 pulsanti header; l'import CSV ora mostra il
  dettaglio delle righe scartate (d.errors[] dal backend) in un <details> e tiene
  aperta la modale se ci sono errori (prima si chiudeva sempre, errori invisibili).
- version 1.10.1.

Inline JS validato (node --check). File statici -> live via nginx.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 14:37:22 +02:00
DevEnv nis2-agileandClaude Opus 4.8 ce0387ed4f [FEAT] Supply chain UI: dropdown categoria + gestione categorie + vista template GV.SC
Colma il gap UI confermato dalla review (backend Fase 1 c'era, UI no):
- Form fornitore: dropdown "Categoria fornitore" alimentato da getSupplierCategories
  (ensureCategories con cache); category_id ora salvato (backend gia' fixato 9fbf72a).
- Pulsante "Categorie": modale con lista preset+custom, CRUD sulle custom
  (preset non modificabili), gestione errore CATEGORY_IN_USE.
- Pulsante "Template": modale lista template + vista dettaglio domande read-only
  con badge nis2_ref/tipo/peso/obbligatoria — mostra le 26 domande GV.SC del DB.
- Target modale via querySelector('#app-modal .modal-body') (showModal usa class).

Inline JS validato (node --check exit 0). File statici -> live via nginx. version 1.10.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 14:30:20 +02:00
DevEnv nis2-agileandClaude Opus 4.8 d103e9d88e [FIX] api.js deleteAsset: this.delete() -> this.del() (metodo inesistente)
Bug trovato da review: il client HTTP base definisce del(), non delete().
deleteAsset chiamava this.delete() -> TypeError, eliminazione asset falliva.
Era l'ultimo this.delete() residuo (i metodi nuovi Fase 1 gia' usano del()).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:28:52 +02:00
DevEnv nis2-agileandClaude Opus 4.8 60793111a2 [FIX] Coerenza normativa AI/help: Allegato 3/4 invertiti + decorrenza relazione finale + disclaimer non-parere-legale
Review coerenza multi-agente tra AI/help/guida (forte adesione normativa):

CONTRADDIZIONE B (la piu' rischiosa) — inversione Allegato 3/4 incidenti.
Verificato sulla fonte certa (docs/nis2/allegati_acn/Allegato3.txt e 4.txt):
  Allegato 3 = soggetti IMPORTANTI, Allegato 4 = soggetti ESSENZIALI.
AIService::classifyIncident e help.js dicevano l'inverso -> CORRETTI.
(La guida era gia' corretta.) Cambiava quali obblighi si applicano a chi.

CONTRADDIZIONE A — decorrenza relazione finale.
AIService diceva generico "30 giorni"; ora esplicito "entro 1 mese DALLA NOTIFICA
delle 72h (non dalla data dell'incidente)", allineato all'Art.23 e alla guida.

DISCLAIMER non-parere-legale (gap: la guida ce l'ha, l'AI no).
authoritativeSourcesText: +regola 4 (orientamento NON vincolante, valutazioni da
confermare con compliance/legale, art.22 GDPR) e +regola 5 (ENISA/NIST/ISO = best
practice non vincolanti; obblighi da Dir.2022/2555 + D.Lgs.138/2024 + Determine ACN).
Iniettato in tutti i prompt che usano il blocco fonti certe.

php -l OK, help.js node --check OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:24:07 +02:00