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>
5.3 KiB
MAPPA-LOGICA · AI Cross-Analysis
⟦ INIZIO · U-XA · Videata "AI Cross-Analysis" ⟧ File: public/cross-analysis.html · URL: /cross-analysis.html · Scopo: analisi AI conversazionale sui dati aggregati e anonimizzati del portfolio clienti di un consulente (gap comuni, rischio medio, categorie NIS2 deboli, benchmark), con storico delle analisi e vista dati portfolio · Profili: SOLO consultant e super_admin — il backend risponde error_code INSUFFICIENT_ROLE agli altri ruoli e la pagina mostra "Funzione riservata a Consulenti e Super Admin".
• U-XA.1 — Header pagina + badge privacy/ruolo
Mostra: titolo "AI Cross-Analysis" con badge verde "Dati aggregati — privacy garantita" e badge viola "Solo Consulenti & Admin".
Azioni: nessuna (informativo).
Dati da: statico (HTML).
Confine: header.content-header (riga 280) — nessun id sugli elementi badge.
• U-XA.2 — Header portfolio (banner viola)
Mostra: "Il tuo portfolio — N organizzazioni monitorate" + 4 statistiche: Compliance medio (%), Rischi aperti, Formazione media (%), Organizzazioni. Se ruolo insufficiente: lucchetto + "Funzione riservata a Consulenti e Super Admin". Se errore: "Errore caricamento portfolio".
Azioni: nessuna (lettura, caricata al boot da loadPortfolio()).
Dati da: GET /api/cross-analysis/portfolio (risposta: data.org_count, data.aggregated.{avg_compliance_score, risks.total_open, training.avg_completion_rate, by_sector, score_distribution, assessments.avg_by_category}).
Confine: #portfolio-header (riga 298).
• U-XA.3 — Barra tab (Chat AI / Storico / Portfolio dati)
Mostra: 3 tab con icone: "Chat AI", "Storico", "Portfolio dati"; tab attiva sottolineata viola.
Azioni: click tab → switchTab() mostra il pannello corrispondente; la tab Storico carica lazy lo storico (U-XA.6).
Dati da: nessuno (navigazione client-side).
Confine: .tab-bar[role="tablist"] (riga 307); bottoni .tab-btn senza id ma con aria-controls="tab-chat|tab-history|tab-portfolio" (righe 308-315).
• U-XA.4 — Tab Chat AI: domande rapide + input
Mostra: empty state iniziale "Analisi AI del tuo portfolio clienti — Fai una domanda sui dati aggregati delle tue organizzazioni"; 6 chip di domande rapide: "Gap più frequenti", "Livello di rischio medio", "Categorie NIS2 deboli", "Intervento urgente", "Stato formazione", "Benchmark NIS2" (ognuna pre-compila una domanda in italiano); textarea domanda con invio via Enter (Shift+Enter per newline); bottone invio; nota privacy: "Dati anonimizzati e aggregati — nessun nome organizzazione inviato all'AI".
Azioni: chip → setQuestion() pre-compila l'input; invio → sendMessage() aggiunge la bolla utente, mostra l'indicatore "thinking" animato, poi POST all'AI.
Dati da: POST /api/cross-analysis/analyze (body: {question}; risposta: data.result + data.org_count).
Confine: #tab-chat (riga 320); #chat-messages (322), #chat-empty (323), #quick-qs (330), #chat-input (340), #btn-send (342).
• U-XA.5 — Risposta AI strutturata (bolla chat)
Mostra: risposta testuale (answer); sezioni opzionali: "Risultati chiave" (key_findings, elenco), "Raccomandazioni" (recommendations, elenco), "Aree di attenzione" (risk_areas, elenco), box viola benchmark (benchmark_note), box ambra nota privacy (privacy_note); footer "Basato su N organizzazioni anonimizzate" + orario. In caso di errore: bolla rossa con il messaggio.
Azioni: nessuna (output).
Dati da: risposta di POST /api/cross-analysis/analyze (result.{answer, key_findings[], recommendations[], risk_areas[], benchmark_note, privacy_note}).
Confine: bolle generate via JS dentro #chat-messages; indicatore thinking con id dinamico #think-<timestamp>.
• U-XA.6 — Tab Storico
Mostra: lista delle ultime 20 analisi: data/ora (it-IT), domanda (prompt_summary, ripulita dal prefisso "CROSS_ORG [...]"), sintesi risposta (response_summary); "Nessuna analisi precedente." se vuoto.
Azioni: caricata al click sulla tab (lazy via loadHistory()).
Dati da: GET /api/cross-analysis/history?limit=20 (risposta: data.history[]).
Confine: #tab-history (riga 355), #history-content (riga 356).
• U-XA.7 — Tab Portfolio dati
Mostra: card "Distribuzione Settoriale" (settore, conteggio, % con barra viola); card "Distribuzione Score Compliance" (fasce 0-20% … 81-100% colorate dal rosso al verde, conteggio org per fascia); card "Score Medio per Categoria NIS2 (dal più basso)" — fino a 5 categorie con % colorata (rosso <30, ambra <60, verde altrimenti) e mini progress bar.
Azioni: nessuna (lettura, renderizzata da renderPortfolioTab() con i dati già caricati al boot).
Dati da: GET /api/cross-analysis/portfolio (stessa chiamata di U-XA.2: aggregated.by_sector, aggregated.score_distribution, aggregated.assessments.avg_by_category).
Confine: #tab-portfolio (riga 362), #portfolio-content (riga 363).
⟦ FINE · U-XA ⟧
ID STABILI MANCANTI (da aggiungere)
| Elemento | Riga | Id proposto |
|---|---|---|
| Tab "Chat AI" | 308 | nis2-xa-tab-btn-chat |
| Tab "Storico" | 311 | nis2-xa-tab-btn-history |
| Tab "Portfolio dati" | 314 | nis2-xa-tab-btn-portfolio |
| Badge privacy header | 284 | nis2-xa-privacy-badge |
| Badge "Solo Consulenti & Admin" | 289 | nis2-xa-role-badge |
| Chip domande rapide (6) | 331-336 | nis2-xa-quickq-1 … nis2-xa-quickq-6 (o data-quickq) |