Files
nis2-agile/docs/mappa-logica/16_settings.md
T
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

96 lines
12 KiB
Markdown

# MAPPA-LOGICA · Impostazioni
⟦ INIZIO · U-SETTINGS · Videata "Impostazioni" ⟧
File: public/settings.html · URL: /settings.html · Scopo: amministrazione completa di organizzazione (dati + classificazione NIS2 + piano), profilo utente, preferenze, membri, sicurezza (sessioni + audit), API Keys, Webhook e branding white-label · Profili: tutti gli utenti autenticati; gestione membri/org tipicamente org_admin; tab "Branding" visibile SOLO a super_admin e consultant (mostrata via /api/auth/me).
• U-SETTINGS.1 — Header + barra tab
Mostra: titolo "Impostazioni" e nome organizzazione corrente nell'header; 8 tab: Organizzazione (default), Profilo, Preferenze, Membri, Sicurezza, API Keys, Webhook, Branding (nascosta di default).
Azioni: click tab → `switchTab()` mostra il pannello e carica lazy i dati (members/security/apikeys/webhooks/preferences/branding).
Dati da: GET /api/auth/me (per decidere la visibilità della tab Branding: role super_admin o consultant).
Confine: `#header-org-name` (riga 208); `.settings-tabs` (riga 214); unico tab con id: `#tab-btn-branding` (riga 222).
• U-SETTINGS.2 — Tab Organizzazione: Classificazione NIS2
Mostra: badge entità calcolato automaticamente da settore/dipendenti/fatturato: "Essenziale" (rosso — supervisione proattiva, sanzioni fino a EUR 10M o 2% fatturato globale), "Importante" (ambra — supervisione reattiva, sanzioni fino a EUR 7M o 1,4%), "Non Applicabile" (grigio) o "Adesione Volontaria" (blu); descrizione del regime; per le entità Non Applicabile: checkbox "Adesione Volontaria alla NIS2".
Azioni: toggle adesione volontaria → `toggleVoluntaryCompliance()` → PUT immediato con voluntary_compliance 0/1 e ri-render del badge.
Dati da: GET organizzazione corrente via api.getCurrentOrg() (GET /api/organizations/current); PUT via api.updateOrganization(id, …) (PUT /api/organizations/{id}).
Confine: `#tab-org` (riga 226); `#entity-classification` (riga 232); checkbox dinamica `#org-voluntary` (template JS riga 954).
• U-SETTINGS.3 — Tab Organizzazione: Piano di Abbonamento
Mostra: badge del piano attivo: Free / Professional / Enterprise.
Azioni: nessuna (lettura).
Dati da: GET /api/organizations/current (campo subscription_plan).
Confine: `#subscription-plan` (riga 240).
• U-SETTINGS.4 — Tab Organizzazione: form Dati Organizzazione
Mostra: Nome Organizzazione*, Settore NIS2* (17 opzioni: Energia, Trasporti, Banche, Sanità, Acqua, Infrastrutture Digitali, Pubblica Amministrazione, Manifatturiero, Servizi Postali, Chimico, Alimentare, Rifiuti, Servizi ICT, Provider Digitali, Spazio, Ricerca, Altro), Partita IVA, Codice Fiscale, Numero Dipendenti, Fatturato Annuo (EUR), Paese, Città, Indirizzo, Sito Web, Email di Contatto, Telefono di Contatto.
Azioni: "Salva Modifiche" → `saveOrganization()` → PUT, poi ricarica i dati per aggiornare la classificazione NIS2 (dipendenti/fatturato/settore la determinano).
Dati da: GET /api/organizations/current (pre-compilazione); PUT /api/organizations/{id} (campi: name, sector, vat_number, fiscal_code, employee_count, annual_turnover_eur, country, city, address, website, contact_email, contact_phone).
Confine: `#org-form` (riga 249); campi `#org-name` (253), `#org-sector` (257), `#org-vat` (283), `#org-fiscal` (287), `#org-employees` (294), `#org-turnover` (298), `#org-country` (305), `#org-city` (309), `#org-address` (315), `#org-website` (321), `#org-email` (325), `#org-phone` (331); bottone `#btn-save-org` (334).
• U-SETTINGS.5 — Tab Profilo: Informazioni Personali
Mostra: Email (disabilitata — "L'email non può essere modificata"), Nome Completo*, Telefono, Lingua Preferita (Italiano/English).
Azioni: "Aggiorna Profilo" → `saveProfile()` → PUT.
Dati da: GET /api/auth/me (pre-compilazione); PUT /api/auth/profile (full_name, phone, preferred_language).
Confine: `#tab-profile` (riga 345); `#profile-form` (354), `#profile-email` (357), `#profile-name` (364), `#profile-phone` (368), `#profile-language` (374); bottone `#btn-save-profile` (380).
• U-SETTINGS.6 — Tab Profilo: Cambia Password
Mostra: Password Attuale*, Nuova Password* con indicatore di forza a 4 segmenti (Debole/Sufficiente/Buona/Forte, calcolato client-side su lunghezza, maiuscole/minuscole, numeri, simboli), Conferma Nuova Password*; avviso: dopo il cambio si viene disconnessi da tutte le sessioni.
Azioni: "Cambia Password" → `changePassword()` (validazioni: coincidenza e min 8 caratteri) → POST; al successo: logout e redirect a /login.html dopo 2s.
Dati da: POST /api/auth/change-password (current_password, new_password).
Confine: `#password-form` (riga 396); `#pw-current` (399), `#pw-new` (404), `#pw-confirm` (416), barra forza `#pw-strength-bar` + `#pw-seg-1..4` (405-409), `#pw-strength-text` (411); bottone `#btn-change-pw` (419).
• U-SETTINGS.7 — Tab Preferenze (utente)
Mostra: Lingua (Italiano/English/Français/Deutsch), Tema (Auto/Chiaro/Scuro), Timezone (8 opzioni, default Europe/Rome), checkbox "Ricevi notifiche via email (incidenti, deadline, training)", checkbox "Mostra notifiche in-app (badge sidebar)"; messaggio "✓ Salvato" temporaneo.
Azioni: "Salva preferenze" → PUT.
Dati da: GET /api/auth/preferences (pre-compilazione); PUT /api/auth/preferences (preferred_language, theme, timezone, notif_email, notif_inapp).
Confine: `#tab-preferences` (riga 430); `#preferences-form` (437), `#pref-lang` (440), `#pref-theme` (450), `#pref-tz` (459), `#pref-notif-email` (473), `#pref-notif-inapp` (480), `#pref-save-btn` (486), `#pref-saved-msg` (487).
• U-SETTINGS.8 — Tab Membri
Mostra: tabella membri dell'organizzazione: Nome, Email, Ruolo (badge: Amministratore, Compliance Manager, Membro CDA, Auditor, Dipendente), Data Ingresso, azione rimozione (icona cestino).
Azioni: "Invita Membro" → modale con Email* e Ruolo (l'utente deve essere già registrato sulla piattaforma) → POST invite; cestino → modale conferma "l'utente perderà l'accesso a tutti i dati" → DELETE.
Dati da: GET /api/organizations/{orgId}/members; POST /api/organizations/{orgId}/invite ({email, role}); DELETE /api/organizations/{orgId}/members/{userId}.
Confine: `#tab-members` (riga 494); `#members-container` (504); campi modale dinamici `#invite-email` e `#invite-role` (template JS righe 1252-1256).
• U-SETTINGS.9 — Tab Sicurezza: info account + Sessioni Attive + Registro Attività
Mostra: (a) card informative: "Autenticazione a Due Fattori (2FA)" con badge "Prossimamente", "Accesso API" con badge JWT; (b) "Sessioni Attive": per ogni dispositivo loggato: etichetta device, badge "Questo dispositivo" sulla sessione corrente, IP, ultimo accesso relativo, data login; (c) "Registro Attività Recenti": tabella Azione (etichette italiane: Accesso effettuato, Password modificata, Assessment completato, Policy approvata, ecc.), Tipo entità, Data — ultimi 20 eventi.
Azioni: "Disconnetti" su una sessione → DELETE singola; "Disconnetti gli altri" (visibile se >1 sessione) → DELETE di tutte le altre sessioni.
Dati da: GET /api/auth/sessions; DELETE /api/auth/sessions/{id}; DELETE /api/auth/sessions (tutte tranne la corrente); GET audit log via api.getAuditLogs({limit:20}) (GET /api/audit/logs).
Confine: `#tab-security` (riga 512); `#card-sessions` (536), `#sessions-container` (545), `#revoke-all-btn` (542), `#audit-log-container` (556).
• U-SETTINGS.10 — Tab API Keys
Mostra: tabella chiavi: Nome (+ "Creata da"), Prefisso (key_prefix...), Scopes (badge), Ultimo Uso, Scadenza, Stato (Attiva/Revocata), azione revoca; card "Scope Disponibili" con descrizione di ogni scope.
Azioni: "Nuova API Key" → modale con Nome*, checkbox scopes (read:all, read:compliance, read:risks, read:incidents, read:assets, read:supply_chain, read:policies, admin:licenses, admin:org, sso:login), Scadenza opzionale → POST; al successo modale one-time con la chiave in chiaro ("Salva questa chiave ora. Non sarà più visibile", uso: header X-API-Key); icona cestino → conferma → DELETE (revoca irreversibile).
Dati da: GET /api/webhooks/api-keys (api_keys[] + available_scopes); POST /api/webhooks/api-keys ({name, scopes[], expires_at}); DELETE /api/webhooks/api-keys/{id}.
Confine: `#tab-apikeys` (riga 564); `#apikeys-container` (579), `#available-scopes-container` (585); campi modale dinamici `#apikey-name` (1386), `#apikey-scopes-checkboxes` (1390), `#apikey-expires` (1401).
• U-SETTINGS.11 — Tab Webhook: subscriptions + Delivery Log
Mostra: tabella webhook: Nome (con warning "⚠ N errori" se failure_count ≥ 5), URL endpoint, Eventi sottoscritti (badge), conteggio Delivery (N✓ N✗), Stato (Attivo/Pausa), 3 azioni (Test Ping, abilita/disabilita, elimina); card "Delivery Log": tabella Evento, Webhook, Stato (delivered/retrying/failed), HTTP status, Tentativo (n/3), Data.
Azioni: "Nuovo Webhook" → modale con Nome*, URL Endpoint* (https), checkbox eventi (incident.created/updated/significant/deadline_warning, risk.high_created/updated, compliance.score_changed, policy.approved/created, supplier.risk_flagged, assessment.completed, whistleblowing.received, normative.update, webhook.test, * wildcard) → POST; al successo modale one-time con il secret HMAC (verifica header X-NIS2-Signature, firma sha256=HMAC_SHA256(body, secret)); Test Ping → POST test; toggle → PUT is_active; elimina → DELETE; "Aggiorna" → ricarica i delivery.
Dati da: GET /api/webhooks/subscriptions; POST /api/webhooks/subscriptions ({name, url, events[]}); POST /api/webhooks/subscriptions/{id}/test; PUT /api/webhooks/subscriptions/{id} ({is_active}); DELETE /api/webhooks/subscriptions/{id}; GET /api/webhooks/deliveries (opz. ?subscription_id=).
Confine: `#tab-webhooks` (riga 591); `#webhooks-container` (606), `#deliveries-container` (615); campi modale dinamici `#wh-name` (1503), `#wh-url` (1507).
• U-SETTINGS.12 — Tab Branding white-label (solo super_admin/consultant)
Mostra: "Nome prodotto custom (opzionale)" (es. Studio Rossi NIS2 Suite), "URL Logo (opzionale)", color picker "Colore primario" (default #1e40af), color picker "Colore secondario" (default #06b6d4); nota: visibile a tutti i clienti loggati dello studio; messaggio "✓ Salvato — ricarica per vedere".
Azioni: "Salva branding" → PUT.
Dati da: GET /api/branding/current (pre-compilazione); PUT /api/branding (custom_brand_name, logo_url, primary_color, secondary_color).
Confine: `#tab-branding` (riga 621); `#branding-form` (628), `#brand-name` (631), `#brand-logo` (636), `#brand-pri` (641), `#brand-sec` (646), `#brand-save-btn` (650), `#brand-saved-msg` (651).
⟦ FINE · U-SETTINGS ⟧
## ID STABILI MANCANTI (da aggiungere)
| Elemento | Riga | Id proposto |
|---|---|---|
| Tab "Organizzazione" | 215 | `nis2-settings-tab-btn-org` |
| Tab "Profilo" | 216 | `nis2-settings-tab-btn-profile` |
| Tab "Preferenze" | 217 | `nis2-settings-tab-btn-preferences` |
| Tab "Membri" | 218 | `nis2-settings-tab-btn-members` |
| Tab "Sicurezza" | 219 | `nis2-settings-tab-btn-security` |
| Tab "API Keys" | 220 | `nis2-settings-tab-btn-apikeys` |
| Tab "Webhook" | 221 | `nis2-settings-tab-btn-webhooks` |
| Bottone "Invita Membro" | 498 | `nis2-settings-btn-invite-member` |
| Bottone "Nuova API Key" | 573 | `nis2-settings-btn-new-apikey` |
| Bottone "Nuovo Webhook" | 600 | `nis2-settings-btn-new-webhook` |
| Bottone "Aggiorna" delivery log | 612 | `nis2-settings-btn-reload-deliveries` |
Nota: `switchTab()` (riga 711) seleziona i tab per indice posizionale (`document.querySelectorAll('.settings-tab')[tabMap[tab]]`) — l'aggiunta di id NON deve cambiare ordine/numero dei bottoni tab.