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>
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>
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>
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>
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.
Harness same-origin temp sul sottodominio + headless chrome: ready -> highlight #compliance-gauge ->
classe nis2-demo-hl applicata, 0 errori. Il SPA esegue i comandi del widget in un browser vero.
Resta solo il giro completo 10 step col widget AgileHub live (conferma di produzione).
Sottodominio nis2.dimostrazione.agile.software live (reverse-proxy). DEMO_BASE allineato (3e8a90f).
Punto coordinamento #2 (same-origin) marcato RISOLTO via sottodominio. Collaudo E2E in corso.
Stato punti 1,2,3,4,6,7,8 = FATTI/deployati/collaudati. Da coordinare: HMAC canonical messaggio,
ops same-origin dimostrazione.agile.software, data-demo-action anchors, sweep 132 id (non bloccante).
Ancorata a tassonomia + mappe-logiche, risposte fondate su FONTI CERTE (Allegati 3/4, IS-4 solo
essenziali, ciclo 24h/72h/1mese, SoA 111 controlli, soglia rilevanza asset 40, ecc.). Formato per
motore quiz (esame soglia 80%). Esercizi pratici eseguibili nella sandbox org 996002.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
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>
Riscrittura completa: istruzioni concrete (login, registrazione 3 step, onboarding
4 step con campi reali, navigazione), per ogni modulo "cosa trovi e come si usa"
estratto dall'help contestuale del prodotto (help.js), FAQ, glossario. Rimosse le
interruzioni di pagina che lasciavano pagine vuote. Generatore self-contained
(estrae i contenuti da public/js/help.js via node).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CONTEXT/runbook aggiornati con le conclusioni 2026-06-10 sera:
- L'app HTTP (php-fpm) usa il MySQL HOST via UNIX SOCKET (localhost), NON il container
(la "scoperta container" precedente era basata sul path CLI = falso positivo).
- TLS su socket non si applica e rompe (outage rientrato: rm flag + USR2).
- Switch socket→TCP via vault-net (172.30.0.1): CLI(root) OK ma fpm(www-data) esce con
source=gateway → masquerade → 135.x → 1045. Switch NON eseguito (sarebbe outage).
- Lezione: validare SEMPRE sul path fpm reale (diag servito da php-fpm), mai CLI/docker exec.
- Pre-equip codice resta committato e inerte (flag OFF); attivabile quando il path TCP
fpm sarà grantabile (bind 172.21 in finestra con restart MySQL).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
database.php: Database::sslOptions() — TLS verso MySQL gated (env DB_SSL=true o
flag-file application/config/.db_ssl_on), DEFAULT OFF. PDO::MYSQL_ATTR_SSL_CA +
VERIFY_SERVER_CERT=false; fail-safe se CA assente (resta in chiaro + log: un
VERIFY=false senza CA connetterebbe in chiaro silenziosamente). Merge con '+'
(preserva chiavi-intere PDO). Default-OFF provato inerte (base + [] === base).
Validato da 2 agenti: runtime app coperto 100% da Database::getInstance (0 raw PDO
in application/); review adversariale = SICURO default-OFF, nessun bug.
.gitignore: flag-file + db-ca.pem. Runbook: docs/TLS_DB_PREEQUIP_NIS2.md.
NB topologia verificata: l'app usa il DB CONTAINER (db->172.21.0.4, 8.0.45), non il
MySQL host -> CA + enforce vanno sul container db (a cura VIGILE).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
#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>