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>
7.1 KiB
MAPPA-LOGICA · Gestione Policy
⟦ INIZIO · U-POLICIES · Videata "Gestione Policy" ⟧ File: public/policies.html · URL: /policies.html · Scopo: gestione del ciclo di vita delle policy di sicurezza NIS2 (creazione, modifica, approvazione, generazione AI, template) richieste dall'Art. 21 NIS2 · Profili: tutti gli utenti autenticati dell'organizzazione (voce sidebar "Policy" visibile a tutti i ruoli); le azioni di scrittura/approvazione sono soggette ai permessi backend (org_admin, compliance_manager, consultant)
• U-POLICIES.1 — Intestazione pagina e azioni globali
Mostra: titolo "Gestione Policy"; due pulsanti in alto a destra: "Genera con AI" (icona scintille) e "+ Nuova Policy"
Azioni: "Genera con AI" → apre la modale di generazione AI (U-POLICIES.7); "+ Nuova Policy" → apre la modale di creazione (U-POLICIES.5)
Dati da: nessun endpoint (elementi statici)
Confine: header.content-header dentro main.main-content (riga ~248-257); i due pulsanti NON hanno id stabile (vedi sezione finale)
• U-POLICIES.2 — Tab di navigazione (Elenco Policy / Template)
Mostra: due tab: "Elenco Policy" (attivo di default) e "Template"
Azioni: click su tab → switchTab('list') mostra #tab-list; switchTab('templates') mostra #tab-templates e carica i template; il cambio tab nasconde la vista dettaglio
Dati da: nessun endpoint diretto (il tab Template innesca GET /api/policies/templates ad ogni click sul tab — loadTemplates() non usa cache)
Confine: div.tabs dentro #page-content (riga ~261-264); i singoli bottoni tab NON hanno id stabile
• U-POLICIES.3 — Tab "Elenco Policy": filtri e tabella
Mostra: barra filtri con 2 select: "Tutte le Categorie" (#filter-category: Sicurezza Informazioni, Controllo Accessi, Risposta Incidenti, Continuita' Operativa, Supply Chain, Crittografia, Sicurezza HR, Gestione Asset, Sicurezza Rete, Gestione Vulnerabilita') e "Tutti gli Stati" (#filter-status: Bozza, In Revisione, Approvata, Pubblicata, Archiviata). Tabella con colonne: Titolo (link), Categoria, Art. NIS2, Versione, Stato (badge colorato), Prossima Revisione, Azioni. Stato vuoto: "Nessuna policy trovata"
Azioni: cambio filtro → ricarica lista; click sul titolo o icona occhio → vista dettaglio (U-POLICIES.4); icona matita → modale modifica; icona spunta verde (solo per stato Bozza/In Revisione) → modale conferma approvazione; icona cestino → modale conferma eliminazione
Dati da: GET /api/policies/list?category=&status= (api.listPolicies(params))
Confine: #tab-list (riga ~267); filtri #filter-category (riga ~269) e #filter-status (riga ~282); tabella renderizzata in #policies-table (riga ~293)
• U-POLICIES.4 — Vista dettaglio policy
Mostra: link "← Torna all'elenco"; titolo policy; badge stato + eventuale badge "AI Generata"; se policy AI in stato bozza/revisione: banner arancione "Bozza AI — Revisione obbligatoria prima dell'approvazione" (chiudibile, id dinamico ai-draft-warning-{id}); pulsanti "Approva" (solo bozza/revisione) e "Modifica"; card "Contenuto Policy" (testo completo); card laterale "Informazioni" con righe: Categoria, Art. NIS2, Versione, Stato, Creata il, Aggiornata il, Prossima Revisione, e se approvata: Approvata da / Approvata il
Azioni: "Torna all'elenco" → backToList(); "Approva" → modale conferma → POST approve; "Modifica" → modale modifica
Dati da: GET /api/policies/{id} (api.getPolicy(id))
Confine: #policy-detail-view (riga ~318, contenuto renderizzato via JS renderPolicyDetail, righe ~517-618)
• U-POLICIES.5 — Modale "Nuova Policy" / "Modifica Policy"
Mostra: form #policy-form con campi: Titolo* (#form-title), Categoria* (#form-category, select 10 categorie), Articolo NIS2 (#form-nis2-article, es. "21.2.a"), Versione (#form-version, default 1.0), Prossima Revisione (#form-review-date, date), Contenuto (#form-content, textarea 12 righe con suggerimento struttura: Scopo, Ambito, Responsabilita', Procedure, Revisione)
Azioni: "Annulla" → chiude; "Crea Policy"/"Salva Modifiche" → savePolicy(id) con validazione titolo+categoria obbligatori
Dati da: POST /api/policies/create (api.createPolicy) per creazione; PUT /api/policies/{id} (api.updatePolicy) per modifica; in modifica precaricamento via GET /api/policies/{id}
Confine: modale generata da showModal() in #modal-overlay (id stabile creato da common.js); form #policy-form (riga ~654)
• U-POLICIES.6 — Modali di conferma (Approvazione / Eliminazione)
Mostra: "Conferma Approvazione": testo "Sei sicuro di voler approvare questa policy?" + avviso che lo stato diventa "Approvata" e l'operazione non e' annullabile. "Conferma Eliminazione": testo con titolo policy + avviso "Questa azione e' irreversibile"
Azioni: Approva → POST /api/policies/{id}/approve (api.approvePolicy); Elimina → DELETE /api/policies/{id} (api.del)
Dati da: POST /api/policies/{id}/approve · DELETE /api/policies/{id}
Confine: #modal-overlay (modale dinamica, funzioni approvePolicy() riga ~748 e confirmDeletePolicy() riga ~780); i pulsanti interni NON hanno id stabile
• U-POLICIES.7 — Modale "Genera Policy con AI"
Mostra: testo esplicativo; select "Categoria Policy" (#ai-category, 10 categorie); pulsante "Genera" (#ai-generate-btn); dopo generazione: anteprima con header "Policy Generata: {titolo}" e contenuto in #ai-preview-container; il footer cambia in "Salva come Bozza"
Azioni: "Genera" → doAIGenerate() (spinner durante la chiamata); "Salva come Bozza" → saveAIGeneratedPolicy() crea la policy con flag ai_generated: 1
Dati da: POST /api/policies/ai-generate (api.aiGeneratePolicy(category)); salvataggio via POST /api/policies/create
Confine: #modal-overlay; select #ai-category (riga ~824), contenitore anteprima #ai-preview-container (riga ~828), pulsante #ai-generate-btn (riga ~832)
• U-POLICIES.8 — Tab "Template": griglia template NIS2
Mostra: card "Template Policy NIS2" con griglia di card cliccabili; ogni card: titolo template, tag categoria, eventuale riferimento "Art. {nis2_article}". Stato vuoto: "Nessun template disponibile"
Azioni: click su una card → createFromTemplate() apre la modale Nuova Policy precompilata con titolo, categoria e articolo NIS2 del template (contenuto vuoto)
Dati da: GET /api/policies/templates (api.getPolicyTemplates())
Confine: #tab-templates (riga ~303); griglia renderizzata in #templates-grid (riga ~308); le singole card template NON hanno id stabile
⟦ FINE · U-POLICIES ⟧
ID STABILI MANCANTI (da aggiungere)
| Elemento | Riga | Id proposto |
|---|---|---|
| Pulsante "Genera con AI" (header) | 251 | nis2-policies-btn-ai-generate |
| Pulsante "+ Nuova Policy" (header) | 255 | nis2-policies-btn-new |
Contenitore tab bar div.tabs |
261 | nis2-policies-tabs |
| Bottone tab "Elenco Policy" | 262 | nis2-policies-tab-btn-list |
| Bottone tab "Template" | 263 | nis2-policies-tab-btn-templates |
| Pulsante "Approva" nella vista dettaglio (HTML dinamico) | 551 | nis2-policies-detail-btn-approve |
| Pulsante "Modifica" nella vista dettaglio (HTML dinamico) | 555 | nis2-policies-detail-btn-edit |