- Supervisore autonomo ticket: prompt operativo + dry-run (scripts/), DRAFT rimosso; gate normativo gia' committato - docs/CONTEXT_LAST_SESSION.md: sessione 2026-06-14 (supervisore LIVE, run#1/#2, rotazione Anthropic rinviata) - docs/sql/039_integrity_keys.sql: migrazione integrita' DB (PK/UNIQUE/FK) gia' applicata in prod 12/6 - docs/MIGRATION_UI_V2.md: piano migrazione UI V2 - docs/nis2/incidente_r00/: 2 mockup incidente (gateway+dashboard) - .gitignore: versiona public/vendor/ (asset Bootstrap Italia self-hosted) - Fix accumulati: EmailService (kill-switch email), Incident/Onboarding/Organization/Services controllers, questionnaire, ReportService, CLAUDE.md standard Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
14 KiB
NIS2 Agile — Piano Realizzativo Migrazione UI V2 (Dark Mode · Inter · Standard SaaS AGI)
Data: 2026-06-10 | Autore: Claude (sessione UI V2, analisi frontend completa) Fonte standard:
lg231-agile/docs/MIGRATION_UI_V2.md(231 Agile, sessione 18, 10 agenti) — stesso design system già adottato da TRPG, ALLTAX, AgileHub. Principio cardine: zero modifiche backend — solo CSS, layout HTML, font, colori nei widget JS. Nessuna modifica a controller PHP, route, schema DB, logicaapi.js. Obiettivo: V2 certificabile, completa e migliore della V1 in ogni funzionalità (lettura, scrittura, stampe/report, accessibilità).
0. Perché V2 e perché ora
La V2 non è un restyling cosmetico: è un cambio di design system allineato allo standard AGI cross-suite (dark mode + glassmorphism + Inter + token semantici) già implementato da 231 Agile, TRPG, ALLTAX, AgileHub. Allinearsi adesso significa:
- Coerenza di suite: un consulente che usa NIS2 + 231 + ALLTAX vede la stessa lingua visiva.
- Certificabilità: design system a token documentato, contrasto WCAG AA verificato, nessun colore hardcoded fuori controllo.
- Leggibilità: Inter sostituisce il system font; dark mode riduce l'affaticamento per operatori compliance/CISO che restano in app per ore.
- Scalabilità: nuovi moduli (Gap ACN, supplier portal, ecc.) nascono già V2.
1. Stato attuale (V1) — fotografia tecnica
| Aspetto | Valore V1 |
|---|---|
| Architettura frontend | Multi-page (36 file .html standalone, non SPA) |
| CSS condiviso | public/css/style.css (~2399 righe, light mode) |
| Sidebar/Topbar | JS-injected da public/js/common.js → loadSidebar() (centralizzato; le pagine hanno solo <aside class="sidebar" id="sidebar"></aside>) |
| Pagine app (con sidebar) | ~20 (dashboard, assessment, risks, incidents, policies, supply-chain, training, assets, reports, settings, acn-gap, normative, whistleblowing, kb, companies, cross-analysis, integrations, service-continuity, supplier-assessment, workflow…) |
| Pagine standalone (no sidebar) | index.html (landing), login.html, register.html, onboarding.html, forgot-password.html, reset-password.html, index-en.html, presentation.html |
<style> per-pagina |
quasi ogni pagina app ha 1 blocco <style> inline con CSS specifico |
Inline style= attr |
abbondanti: settings 101, supply-chain 74, whistleblowing 52, risks 51, assessment 50, reports 41, companies 40, normative 31, incidents 30 |
| JS con colori hardcoded | bug-reporter.js (80), ai-assistant.js (30), common.js (30), help.js (11), kb.js (6), feedback.js (5), auth-gate.js (4) |
| Chart.js | solo supply-chain.html |
| Font | system font (-apple-system, Segoe UI, Roboto…), nessun Google Font |
| Mobile | mobile-conversion.css (189 righe) + mobile-conversion.js |
| Versione | 1.13.0 (public/version.json) |
Palette V1 (:root)
--primary: #1a73e8(Google blue),--primary-light: #4a9af5,--primary-dark: #1557b0--secondary: #34a853(verde),--warning: #fbbc04,--danger: #ea4335,--info: #4285f4- Neutrals
--gray-50…900,--content-bg: #f1f5f9,--card-bg: #ffffff - Sidebar già dark:
--sidebar-bg: #1e293b
2. Delta Design System V1 → V2
2.1 Colori — mapping completo
| Token | V1 (light) | V2 (dark) | Note |
|---|---|---|---|
--bg / --content-bg |
#f1f5f9 |
#0F172A |
Sfondo principale |
--surface / --card-bg |
#FFFFFF |
#1E293B |
Card, modal, sidebar |
--card |
#FFFFFF |
rgba(30,41,59,0.85) |
Glassmorphism |
--border |
#e2e8f0 |
rgba(255,255,255,0.08) |
Bordi standard |
--border-subtle |
— | rgba(255,255,255,0.04) |
Bordi sottili |
--text |
#1e293b |
#F8FAFC |
Testo primario |
--light (text-secondary) |
#475569 |
#CBD5E1 |
Testo secondario |
--muted |
#64748b |
#94A3B8 |
Hint/disabled |
--primary (brand) |
#1a73e8 |
vedi §2.2 decisione brand | Identità NIS2 |
--blue (interattivo) |
#1a73e8 |
#3B82F6 |
Link, focus, btn |
--secondary/--success |
#34a853 |
#10B981 |
Verde |
--warning |
#fbbc04 |
#F59E0B |
Amber |
--danger |
#ea4335 |
#EF4444 |
Rosso |
--info |
#4285f4 |
#3B82F6 |
Info/link |
--accent |
— | #6366F1 |
Indigo secondario |
--purple |
— | #8B5CF6 |
Accent terziario |
--sidebar-bg |
#1e293b |
#0B1929 |
Più profondo (coerente suite) |
--code-bg |
— | #0D1117 |
Nuovo |
2.2 DECISIONE BRAND — ✅ CONFERMATA (2026-06-10)
Accent/brand interattivo V2 = Suite blue #3B82F6 (hover #2563EB, focus ring rgba(59,130,246,.2)). Scelta per massima uniformità con 231/TRPG/ALLTAX/AgileHub. Il resto della palette (bg/surface/semantic) è identico alla suite.
2.3 Tipografia
| Aspetto | V1 | V2 |
|---|---|---|
| Font UI | system stack | 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif |
| Monospace | SF Mono/Fira | 'JetBrains Mono', monospace |
| Base size | 16px html | 15px body |
| Weights | 400/600/700/800 | 400/500/600/700/800/900 |
| Google Fonts | nessuno | Inter:wght@400..900 + JetBrains Mono:wght@400;500;600 |
2.4 Componenti — delta visivo
Identico al delta lg231 (card glassmorphism radius 12 + blur 8, btn solido no-gradient radius 8, badge semitrasparenti radius 20, table header uppercase 11px letter-spacing, input dark rgba(255,255,255,.05), label uppercase 11px muted, modal overlay rgba(0,0,0,.7) + blur, alert border 1px + bg rgba). Vedi lg231-agile/docs/MIGRATION_UI_V2.md §5 per il CSS definitivo da riusare 1:1.
3. File coinvolti
Da modificare (zero backend)
public/css/style.css ← RESET :root + design system V2 completo (CUORE)
public/mobile-conversion.css ← allineamento token dark
public/js/common.js ← sidebar/topbar injected + 30 colori hardcoded → token
public/js/bug-reporter.js ← 80 colori hardcoded → token/dark (widget FAB)
public/js/ai-assistant.js ← 30 colori → dark (widget chat ARIA)
public/js/help.js ← 11 colori → token (help contestuale)
public/js/feedback.js, kb.js, auth-gate.js ← colori residui
public/*.html (app, ~20) ← <style> per-pagina + inline style= → token V2
public/login.html register.html onboarding.html ← redesign dark standalone
public/index.html index-en.html ← landing (palette/font V2, non full dark — vedi §6)
public/forgot-password.html reset-password.html presentation.html
public/version.json ← bump MINOR → 1.14.0 (a fine, NON manuale durante apply)
NON toccare
application/** (PHP), public/index.php, public/js/api.js, public/js/i18n.js (solo stringhe colore se presenti), docs/sql/**, docker/**, .env.
4. Partizione 10 Agenti + 10 QA (esecuzione background)
Ogni agente realizzatore è accoppiato a un agente QA di controllo qualità che, a valle, verifica: (a) nessun colore V1 hardcoded residuo nel suo ambito, (b) contrasto WCAG AA su dark, (c) nessuna regressione funzionale (markup/classi intatti, JS non rotto), (d) coerenza con i token V2. Il QA produce un verdetto PASS/FAIL + findings; un FAIL rimanda l'item all'agente realizzatore.
Concorrenza & isolamento: gli agenti che scrivono
style.csslavorano su sezioni disgiunte dello stesso file → per evitare conflitti di scrittura concorrente, la FASE 1 (style.css) è sequenziale per file ma parallela per QA; le fasi su file distinti (HTML pagine, JS widget) sono pienamente parallele. In alternativa worktree isolati + merge.
| # | Agente realizzatore | File/ambito | QA verifica |
|---|---|---|---|
| 1 | CSS Base | style.css :root tokens V2 + Inter import + body/reset + utility classes (.mono, .text-success/-warning/-danger/-primary/-info/-muted) |
token completi, font caricato, no var orfane |
| 2 | Sidebar + Topbar | style.css sezione sidebar/topbar + common.js loadSidebar() colori |
active state visibile, glassmorphism topbar, brand color |
| 3 | Main + Layout | style.css main-content, view, section-header, grid responsive |
contrasto, responsive (fix grid hardcoded), densità |
| 4 | Card + KPI | style.css card glassmorphism, kpi-card/value/icon/trend |
radius 12, blur, leggibilità valori |
| 5 | Tabelle + Badge | style.css table header/body/hover, status-badge tutte le varianti |
badge semitrasparenti, contrasto righe |
| 6 | Form + Button | style.css form-control, label, focus ring, btn-primary/secondary, upload-area |
focus ring accent, select option bg, input visibili |
| 7 | Modal + Alert + Progress | style.css modal overlay/box/header/footer, alert, progress-bar, score-ring |
overlay scuro+blur, modal leggibile |
| 8 | Componenti speciali | style.css risk matrix 5×5, heatmap, workflow nodes, timeline, accordion guida, Chart.js in supply-chain.html (grid/tick color dark) |
chart visibili su dark, matrice leggibile |
| 9 | Pagine standalone | login.html, register.html, onboarding.html, forgot/reset-password.html (CSS inline → dark V2) |
login funzionante dark, step indicator V2 |
| 10 | Pagine app + widget JS + landing | <style>/inline di ~20 pagine app → token; bug-reporter.js/ai-assistant.js/help.js/feedback.js/kb.js colori → dark; index.html/index-en.html landing palette V2 |
no inline V1 residuo, widget dark, landing coerente |
L'Agente 10 è il più pesante (20 pagine + 5 widget): in esecuzione reale va splittato in sub-task (pagine app per gruppi + widget separati) mantenendo 1 QA per gruppo, restando entro il cap di 10 coppie attive.
5. Pattern di sostituzione inline (HTML + JS)
| Pattern V1 | Sostituzione V2 |
|---|---|
#1a73e8 / #4285f4 |
var(--blue) o brand accent |
color:#34a853 |
var(--success) (#10B981) |
color:#ea4335 |
var(--danger) (#EF4444) |
color:#fbbc04 |
var(--warning) (#F59E0B) |
background:#fff / #ffffff |
var(--surface) |
background:#f1f5f9 / #f8fafc |
var(--bg) o rgba(255,255,255,.03) |
border:1px solid #e2e8f0 |
border:1px solid var(--border) |
bg pastello chiaro (#e6f4ea, #fce8e6, #fef7e0, #e8f0fe) |
rgba(<sem>,.1) semitrasparente |
color:#1e293b / #0f172a (testo) |
var(--text) |
color:#475569 / #64748b |
var(--light) / var(--muted) |
6. Note critiche (da lg231, valide per NIS2)
- Chart.js dark (supply-chain.html): impostare esplicitamente
scales.*.ticks.color:'#94A3B8'egrid.color:'rgba(255,255,255,.08)', altrimenti assi invisibili su dark. - Landing pubblica (
index.html): può restare con accent brand distinto (cyan NIS2) e non full-dark se si preferisce marketing chiaro — decisione §2.2. Coerenza font/btn comunque V2. - Backdrop-filter: fallback
--surfacesolido per Firefox<103/Safari<15.4 (già nella variabile). - Stampe/Report (
reports.html,ReportServiceHTML esecutivo): le print styles restano light (carta bianca) — la V2 dark NON deve rompere@media print. QA Agente 8/10 verifica che il report stampato resti leggibile su carta. --text-secondary→--muted: mantenere alias backward-compat in:rootper il JS che genera HTML inline (evita regressioni).- Hot-reload: CSS/HTML live via bind-mount; per i
.php(nessuno qui) servirebbekill -USR2 1. Per CSS/HTML basta hard-refresh (cache-bust?v=1.14.0sui<link>consigliato).
7. Strategia di rilascio — IN-PLACE vs PARALLELA (da confermare)
- In-place (come lg231): si riscrive
style.csslive. Impatto immediato su produzione per tutti gli utenti. Rollback =git revert. - Parallela (più certificabile): si costruisce
css/style-v2.css+ si verifica su un sottoinsieme/branch, poi si commuta il<link>di tutte le pagine. Permette QA completa prima del go-live.
Trattandosi di produzione live (
nis2.agile.software, bind-mount istantaneo, 36 pagine), si consiglia la parallela con commit su branch dedicato + verifica, poi switch.
✅ DECISIONE CONFERMATA (2026-06-10): PARALLELA. La V2 è costruita in un git worktree isolato fuori dal path servito: /tmp/nis2-ui-v2 su branch ui-v2. La produzione (/projects/nis2-agile == bind-mount /var/www/nis2-agile, ramo main) resta intatta finché l'utente non approva il merge/go-live. Backup V1: /tmp/nis2-ui-v2/.backups/ui_v2_20260610/style.css.v1.
8. Checklist verifica post-migrazione (certificazione)
- Tutte le ~20 view app rese senza errori JS, leggibili dark
- Login/Register/Onboarding funzionanti dark
- Chart supply-chain visibile su dark
- Tabelle/badge contrasto ≥ 4.5:1 (WCAG AA)
- Form input visibili, focus ring accent
- Modal overlay/header/footer dark ok (tutti i modal)
- Sidebar JS-injected: active/hover/brand corretti
- Mobile drawer +
mobile-conversion.csscoerenti - Google Font Inter caricato (no fallback)
- Widget FAB (bug-reporter), chat ARIA (ai-assistant), help contestuale: dark coerente
- Stampe/report:
@media printresta leggibile su carta bianca - Nessun colore V1 hardcoded residuo (
#1a73e8,#34a853,#ea4335,#fbbc04,#fffin stili critici) version.json→1.14.0- i18n IT/EN intatto, help.js intatto
9. Governance (CLAUDE.md)
- Modifica file = conferma utente (questo doc è la proposta). Live via bind-mount.
- Commit immediato post-smoke + push via host se cache token vuota.
- Backup pre-migrazione:
public/css/style.css→.backups/ui_v2_<ts>/. - A fine sessione aggiornare
docs/CONTEXT_LAST_SESSION.mdeCLAUDE.mdse cambia architettura UI.