Evita la "sessione scaduta" e i deploy che restano invisibili all'utente.
- api.js: refresh PROATTIVO dell'access token ~2 min prima della scadenza
(scheduleTokenRefresh su exp del JWT, riprogrammato ad ogni setTokens) +
ensureFreshToken() per rinnovo immediato al ritorno sulla scheda. Con refresh
a 7gg l'utente resta loggato senza mai vedere il login.
- common.js: watch versione (poll version.json ogni 5 min + su visibilitychange)
→ banner "È disponibile una nuova versione — Aggiorna" (reload) quando cambia;
nudge service worker (registration.update); su visibilitychange chiama anche
api.ensureFreshToken(). Nessun hard-refresh manuale.
- Cache-buster api/common ?v=20260729b. version 1.25.12. Solo frontend.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Punto 1: la tabella 'Rischi dai requisiti del framework di sicurezza' e ora
un riquadro a scorrimento verticale (max-height 60vh, header sticky) invece di
allungare la pagina.
- Punto 2: elenca SOLO i requisiti applicabili alla classe del soggetto
(importante -> Allegato 1, essenziale -> Allegato 2, Det. ACN 164179/2025);
le righe non pertinenti non sono piu mostrate (prima solo attenuate).
- help.js allineato + cache-buster help.js?v=20260729b su 35 pagine; version.json 1.25.10.
- Punto 3 (rimozione sezione all-hazard) NON applicato: contraddice la decisione
documentata nel #500 (copertura multirischio art.24 D.Lgs.138/2024) -> escalato.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
companies.html diventa il cruscotto dello studio consulente: barra KPI (aziende,
compliance media, scadenze in ritardo/in arrivo), griglia aziende (compliance/
rischi/incidenti + badge ritardo, clic = entra nell'azienda) e sezione "Scadenze
generali" aggregata su TUTTE le aziende ordinata per data. Una sola chiamata
api.consultantPortfolio(). Voce menu V3 "Le mie aziende" (icona briefcase) gata a
consultant/super_admin. help.js + i18n (nav.studio + companies.*) aggiornati.
Cache-buster api/topnav-v3/i18n/help ?v=20260729. version 1.25.9.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Nella modale "Valuta" di un rischio-requisito non ancora valutato, Probabilità e
Impatto vengono pre-compilati in base allo stato (conforme→basso 1/2, parziale→
medio 3/3, non conforme→alto 4/4) con nota esplicita "Valori suggeriti … è solo
un suggerimento, modificabili". Se già valutato, usa i valori salvati. Idea
pre-avallata dal nis2-expert (precompilare l'asse dallo stato = rischio residuo).
Solo frontend (risks.html); nessun valore imposto (art.24 non prescrive metodo).
version 1.25.8.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Il supervisore autonomo (b5f936b) aveva RIMOSSO del tutto i tasti 'Nuovo Rischio'
e 'AI Suggerisci' applicando il ticket alla lettera. Decisione utente (Cristiano):
NON rimuoverli ma limitarli ai profili super_admin/org_admin — l'inserimento libero
serve a coprire i rischi all-hazard non legati a un singolo requisito (art.24
D.Lgs.138/2024, confermato nis2-expert). Ripristinato il gating (gateAdminActions):
i tasti compaiono solo agli admin, nascosti agli altri. version 1.25.6.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
I rischi in Gestione Rischi corrispondono ai requisiti del framework (Determinazione ACN 164179/2025);
niente inserimento manuale/AI. Reverte l'admin-gating: la spec del richiedente e il piano originale
prevedevano la rimozione dei tasti. La sezione 'Rischi aggiuntivi' resta come elenco in sola lettura.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
La pagina Gestione Rischi mostra come tabella primaria (read-only) i requisiti
del framework Lex&ISO come rischi, codice RSK-<misura>Com.N via /api/risks/derived,
filtrati per classe (importante All.1 / essenziale All.2). Framing normativo
(validato nis2-expert): ogni voce = "rischio derivante dal mancato/parziale
soddisfacimento del requisito", mai "requisito = rischio"; RSK e "92" NON come
codici/numeri ufficiali ACN; matrice = strumento di rappresentazione (art.24).
- Rischi CUSTOM mantenuti in sezione "Rischi aggiuntivi (all-hazard)".
- Tasti "Nuovo Rischio"/"AI Suggerisci" limitati a super_admin/org_admin (non
rimossi): l'inserimento libero serve al multirischio (art.24 D.Lgs.138/2024).
- api.js derivedRisks(); help.js + i18n aggiornati; version 1.25.4; SW v1.25.4.
- Cache-buster api/help/i18n ?v=20260727r. Backend/DB non toccati.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ticket #500 (Simon Fattori) - semplificazione pagina Gestione Rischi:
- matrice 5x5 ora sempre visibile sotto la tabella (rimosso bottone 'Matrice' e il view-toggle)
- rimosse le viste 'Quantitativo (FAIR)' e 'KRI' con relativi bottoni, blocchi HTML e JS
- help.js allineato (rimosse sezioni FAIR/KRI), cache-buster help.js -> 20260727a
- version.json -> 1.25.2
Rimandato a fase 2 (richiede modello dati): rischi derivati dai requisiti LEX&ISO
+ codifica RSK-<misura>Com.N + rimozione bottoni 'Nuovo Rischio'/'AI Suggerisci'.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bug segnalato da un tester "sono tornato su nis2 e non funziona più" (utente/
aziende "--", inventario bloccato su Caricamento, niente FAB segnalazioni).
Causa: un 401 su /auth/refresh (refresh token scaduto/invalido) rientrava nel
handler di refresh (la condizione non escludeva l'endpoint auth) → ricorsione:
doRefreshToken() non ritornava mai, quindi logout()/redirect a login non
scattava e la pagina restava rotta. Riprodotto con puppeteer (access scaduto +
refresh invalido → dashboard "--" identica allo screenshot).
Fix: escludi /auth/refresh e /auth/login dall'auto-refresh; inoltre un 401 senza
refresh token disponibile fa logout() → login. Ora un utente che torna dopo la
scadenza del token viene mandato a login (ri-accede) invece di vedere "--".
Bug PRE-ESISTENTE in api.js (non introdotto dal V3), critico ora col push tester.
Cache-buster api.js ?v=20260627u su tutte le pagine.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- aria-guide "Mostrami dov'è": ora aggancia le voci del menu IN ALTO V3
(data-nav aggiunto in topnav-v3.js su voci dirette + mega-link). Se la voce è
in un mega-menu, lo apre (.aria-guide-open) e ci punta lo spotlight; coach
"menu in alto". Fallback navigazione invariato. (Prima cercava .sidebar-nav V2.)
- segnala-anonimo.html: CSP font-src 'self' → 'self' data: (sbloccato il font
data: embeddato, niente più violazione CSP).
- Cache-buster: topnav-v3.js/common.js ?v=20260627t, aria-guide.js ?v=20260627t.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
La flotta V3 aveva messo data-i18n="mr.title"/"normative.title" sugli <h1> di
misure-requisiti e normative, ma le chiavi non erano in i18n.js → I18n.t()
ritorna la chiave → il titolo mostrava "mr.title"/"normative.title". Aggiunte
le 2 chiavi (it+en). Cache-buster i18n.js ?v=20260627p su tutte le pagine.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dopo il revamp V3, allineati i layer che descrivevano ancora la sidebar V2:
- topnav-v3.js: aggiunte le pagine orfane in nav (Matrice RACI → Struttura
interna, Scadenziario → Monitoraggio, Compliance Journey → Guida) + cablato
data-i18n su gruppi e voci del mega-menu (traduzione IT/EN come in V2).
- i18n.js: nuove chiavi nav V3 (gruppi mega-menu + connettori/whistleblowing/
normative/cross-analysis/kb/architettura/simulazione/integrazioni/workflow/
audit ACN/registra incidente).
- AIService.php navigationMapBlock: riscritta sul menu IN ALTO V3 (9 gruppi +
pulsante "Registra incidente"), sync con topnav-v3.js NAV_GROUPS; ARIA non
parla più di "barra laterale".
- help.js: corrette le 3 menzioni "sidebar" → barra/menu in alto.
- KB nis2_kb: nuovo docs/kb/V3_UI_NAVIGAZIONE.md + scripts/ingest-v3-ui-doc.php
(ingerito host-side: 3 chunk SYSTEM, rimossi i chunk V2; ARIA RAG ora guida
sul top-nav).
- Cache-buster ?v=20260627n sui 3 JS modificati su tutte le pagine.
Deploy: JS/HTML statici live via bind-mount; php-fpm reload (host + nis2-app)
per AIService.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Click su un'intestazione (Nome/Tipo/Categoria/Criticita/Rilevanza NIS2/Owner/Stato)
ordina l'inventario; secondo click inverte (freccia ▲/▼, aria-sort).
Criticita e Rilevanza ordinano per valore reale, non alfabetico.
Client-side sull'inventario gia' caricato (no paginazione su assets), si combina
coi filtri, accessibile da tastiera. Help aggiornato + cache-buster help.js.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nuovo pulsante "Esporta" in assets.html: scarica l'intero inventario
(tutte le pagine) in CSV con le stesse colonne riconosciute
dall'import (name, asset_type, criticality, data_classification,
internet_facing, dependencies_count, regulated, external_ref, vendor,
location). I criteri data_classification/internet_facing/
dependencies_count/regulated sono ricostruiti da relevance_criteria con
mappatura reversibile (round-trip stabile, verificato 100/100 casi).
Parser import reso quote-aware (RFC-style) per round-trip lossless di
nomi con virgola; retro-compatibile con CSV non quotato.
help.js + cache-buster (?v=20260625b) su tutte le pagine. version 1.24.14.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Completa i 2 punti rimandati dal supervisore:
- help.js sezione Inventario: documentate le nuove funzioni che il supervisore ha
aggiunto (commit 9c36604) → "Mappa Dipendenze" con il campo Dipendenze per popolarla;
"Elimina bene" (cestino, org_admin) distinto dallo stato "dismesso".
- AIService::navigationMapBlock: 2 regole nuove → (5) NON citare nomi file .html/URL
interni; (6) NON inventare pulsanti/funzioni/passi inesistenti, usare solo le funzioni
della guida/contesto della pagina. Elimina l'allucinazione "rischi.html" e simili.
Smoke: ARIA cita Elimina + Mappa Dipendenze, zero nomi-file, "Gestione > Rischi".
Cache-buster help.js -> 20260625a. php-fpm reload.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Porting del pattern TRPG (CHANGE_aria_voice_pointer.md) sulla sidebar V2:
- public/js/aria-guide.js (nuovo): DESTINATIONS (26 voci menu → keyword IT),
matchDestination(question), pointTo(nav,label) = overlay + spotlight pulsante +
puntatore animato + coach-mark "Vai →"; Esc/click per chiudere; fallback navigate
se la voce non è visibile; rispetta prefers-reduced-motion; self-contained, no inline-CSS.
- common-bi.js: data-nav="<href senza .html>" sulle voci sidebar (aggancio puntatore).
- common.js: inietta aria-guide.js dopo login; dopo ogni risposta ARIA, se la domanda
combacia con una destinazione mostra il bottone "📍 Mostrami dov'è: <voce>".
Frontend-only, additivo. Cache-buster common.js/common-bi.js -> 20260624f.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lamentela: "AI non allineata con help online e contesto". Causa: ARIA e Help
erano due fonti separate (Help=help.js, ARIA=KB) → divergevano.
Fix (fonte unica = help.js, zero duplicazione):
- help.js: getContextText(pageId) (testo piano dell'help della pagina) + detectPageId().
- common.js: invia page_id (canonico) + page_help (stesso testo del pannello "?") a /api/ai/ask.
- AiController: passa page_id/page_help in userContext.
- AIService::askWithRag: inietta "GUIDA CONTESTUALE DELLA PAGINA" nel system prompt
(ARIA si allinea all'help mostrato all'utente, non lo contraddice) + usa page_id
per il trigger relevanceGrid (più robusto del title).
Smoke: ARIA cita "registro dei rischi" dall'help + "Gestione > Rischi". Cache-buster
common.js/help.js -> 20260624e (39 pagine).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
La colonna operative_summary lato ticket-ms e' VARCHAR(2000): descrizioni
lunghe causavano l'errore SQL grezzo a video. Aggiunto maxlength + contatore
live + guard al submit nel widget locale public/js/bug-reporter.js.
Cache-buster: bug-reporter.js?v=20260624 in common.js + common.js?v=20260624
su tutte le pagine. Causa radice (dimensione colonna) inoltrata ad AgileHub.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ARIA citava voci di menu inesistenti (es. 'A4 - Analisi e Valutazione
del Rischio' / 'Fase 4.1 - Inventario') non corrispondenti alla barra
laterale, e non sapeva da quale pagina scrivesse l'utente.
- AIService::askWithRag: iniettata la mappa REALE della sidebar
(navigationMapBlock, sincronizzata con common-bi.js) con regole che
vietano di inventare menu/fasi/codici; aggiunto contesto pagina utente.
- AiController::ask: accetta e passa il campo 'page' dal frontend.
- common.js (ARIA FAB): invia la pagina corrente in /api/ai/ask.
- Cache-buster common.js 20260623->20260623h su tutte le pagine.
NB: questo commit include anche il fix#419 gia' applicato e live in
common.js (email bug-reporter recuperata via api.getMe quando assente
nelle claims JWT), finora non committato — incluso come backup.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Risolve #418/#420 (ARIA sembrava non rispondere / serviva riaprire il pannello):
l'attesa della risposta /api/ai/ask (RAG+Claude, alcuni secondi) non mostrava
alcun indicatore -> ora compare 'ARIA sta scrivendo...' con input disabilitato
(anti doppio-invio). Indicatore rispetta prefers-reduced-motion (AGID/WCAG).
Risolve #425: il campo di scrittura era <input> a riga singola -> ora <textarea>
con Invio=invia, Shift+Invio=a capo, auto-crescita e aria-label.
common.js e' statico (no PHP/USR2): bump cache-buster ?v=20260623 su 39 pagine
(public + admin) + version.json 1.24.6.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Colonna 'Procedura (default)' -> 'Policy (default)' in misure-requisiti.html;
colonna/dettaglio/campo modale 'Art./Articolo NIS2' -> 'Requisito NIS2' in policies.html;
testi descrittivi pagina Misure e Requisiti + guida help.js allineati al lessico 'policy'.
Cache-buster help.js?v= 20260631 -> 20260618p1 su 28 pagine. version.json 1.23.2 -> 1.23.3.
Punti 2/3/5/6 del ticket restano in lavorazione a fasi.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
La modale 'Modifica Policy' (e ogni modale con form legacy .form-label) mostrava
l'etichetta sovrapposta al valore: BI definisce .form-group label{position:absolute}
(spec. 0,1,1) che vinceva sulla .form-label legacy. Aggiunto override
.form-group .form-label{position:static} (spec. 0,2,0). Bumpato ?v= di style.css
su 38 pagine. version.json -> 1.23.2.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
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>
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>
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>
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>
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>
Flotta di verifica (14 agenti): sicurezza pulita, fedeltà del dato perfetta (codifica
Simon intatta, 0 scostamenti). Corretti i 6 finding confermati:
- MAJOR: PolicyController::ensureFrameworkProcedures ora in transazione + SELECT...FOR UPDATE
sulla riga org -> no procedure duplicate su fallimento parziale (rollback) o richieste concorrenti.
- MINOR: importer idempotente committato application/cli/seed_framework.php (DDL + upsert da
nis2_framework_seed.json) -> re-seed riproducibile/versionato (verificato 2 run = 0 duplicati).
- MINOR: allineato '92 requisiti' importanti (dato autoritativo Simon) in help.js + nis2_sources.php
(era 87, contraddizione interna); coerente '24 requisiti aggiuntivi essenziali' (116-92).
- MINOR (UI): troncamento anteprima valutazione sul RAW prima di esc() (no entita HTML spezzate).
- MINOR (UI a11y/AGID): modale valutazione con focus iniziale, ripristino focus, focus-trap.
Cache-buster ?v=20260623, version 1.18.2, SW nis2-shell-v1.18.2.
NB residuo da verificare: data esatta Determinazione 333017/2025 (mese senza giorno) in nis2_sources.php.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- help.js 'misure-requisiti': sezione 'Valutazione e stato di conformità' (stato per
requisito, valutazione del rischio che parte vuota, copia procedure di default) + nota.
- KB AI: doc SYSTEM su valutazione conformità + procedure/rischi di default (uuid 92979c05).
- Cache-buster ?v=20260622 (35 pagine), version.json 1.18.1, SW cache nis2-shell-v1.18.1.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 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>
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.)
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.