- 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>
200 lines
14 KiB
Markdown
200 lines
14 KiB
Markdown
# 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, logica `api.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.css` lavorano 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)
|
||
|
||
1. **Chart.js dark** (supply-chain.html): impostare esplicitamente `scales.*.ticks.color:'#94A3B8'` e `grid.color:'rgba(255,255,255,.08)'`, altrimenti assi invisibili su dark.
|
||
2. **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.
|
||
3. **Backdrop-filter**: fallback `--surface` solido per Firefox<103/Safari<15.4 (già nella variabile).
|
||
4. **Stampe/Report** (`reports.html`, `ReportService` HTML 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.
|
||
5. **`--text-secondary` → `--muted`**: mantenere alias backward-compat in `:root` per il JS che genera HTML inline (evita regressioni).
|
||
6. **Hot-reload**: CSS/HTML live via bind-mount; per i `.php` (nessuno qui) servirebbe `kill -USR2 1`. Per CSS/HTML basta hard-refresh (cache-bust `?v=1.14.0` sui `<link>` consigliato).
|
||
|
||
---
|
||
|
||
## 7. Strategia di rilascio — IN-PLACE vs PARALLELA (da confermare)
|
||
|
||
- **In-place** (come lg231): si riscrive `style.css` live. 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.css` coerenti
|
||
- [ ] Google Font Inter caricato (no fallback)
|
||
- [ ] Widget FAB (bug-reporter), chat ARIA (ai-assistant), help contestuale: dark coerente
|
||
- [ ] **Stampe/report**: `@media print` resta leggibile su carta bianca
|
||
- [ ] Nessun colore V1 hardcoded residuo (`#1a73e8`, `#34a853`, `#ea4335`, `#fbbc04`, `#fff` in 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.md` e `CLAUDE.md` se cambia architettura UI.
|
||
```
|