- simulate.html: aggiunta card BIG (10 aziende, 18 fasi) con url
simulate-nis2-big.php, label BIG in SIM_LABELS, confirm dialog dedicato
- simulate-nis2-big.php: fix training assign user_id → user_ids (array)
come richiesto da TrainingController::assignCourse()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ServicesController: nuovo endpoint GET /api/services/full-snapshot
Aggrega gap-analysis, measures, incidents, training, deadlines,
compliance-summary in una sola chiamata (reduce 6 round-trip → 1)
Parametro ?days=N per finestra deadlines (default 30, max 365)
- public/index.php: route GET:fullSnapshot aggiunta all'action map services
- public/simulate-nis2-big.php: wrapper SSE per simulate-nis2-big.php
Esegue il simulatore come sottoprocesso CLI con NIS2_SSE=1 e
streama l'output al browser tramite Server-Sent Events
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- GET /services/gap-analysis — gap per dominio NIS2 Art.21 con mapping MOG 231 pillars
- GET /services/measures — compliance_controls con mog_area e nis2_article derivati
- GET /services/incidents — incidenti con Art.23 CSIRT compliance per step (24h/72h/30d)
- GET /services/training — corsi + completamento board (Art.20 compliance flag)
- GET /services/deadlines — scadenze aggregate da 4 sorgenti con ?days= filter
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- simulate-nis2-b2b.php: 6 scenari autonomi (SIM-B1→B6):
mktg login, invito con recipient data, validazione pubblica,
registrazione ridotta, provision org, login con org, API Key M2M
- public/simulate-b2b.html: UI terminale dark con flow diagram e SSE streaming
- public/register.html:
- Registrazione ridotta: con invito che ha recipient data mostra banner
"Ciao [Nome]!" + campi pre-compilati read-only + solo password richiesta
- Post-register con inviteToken: chiama provision automaticamente,
salva nis2_org_id in localStorage, redirect a dashboard.html
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- public/simulate-nis2.php: riscritta con proc_open come lg231 test-runner.
Lancia simulate-nis2.php come subprocess CLI con NIS2_SSE=1, streama
ogni riga SSE al browser immediatamente senza buffering Apache/FPM.
Stderr del subprocess → eventi SSE 'error' visibili nel terminale.
- simulate-nis2.php: aggiunto supporto NIS2_SSE=1 (env var).
Quando NIS2_SSE=1, IS_CLI=false → output SSE anche da sottoprocesso.
API_BASE usa sempre server prod in modalità subprocess.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- autoResetDemo(): cancella tutti i file /tmp/nis2_ratelimit/*.json
all'avvio così la re-esecuzione immediata non incappa in "Troppi tentativi"
- ensureUser(): aggiunge retry login se register fallisce con "email già
registrata" (caso in cui dbSeedUser ha inserito l'utente ma il primo
login aveva avuto un errore transitorio)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- SSE heartbeat (commento ': heartbeat') ogni 25s in simLog() per mantenere
viva la connessione attraverso proxy/CDN con timeout 300s (pattern lg231)
- Apache vhost: Timeout 1800 + ProxyTimeout 1800 (su Hetzner direttamente)
per simulazioni che richiedono 8-12 minuti
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
max_execution_time=30 in Apache php.ini interrompeva la simulazione dopo 30s.
La simulazione completa richiede 8-12 minuti.
Aggiunto: set_time_limit(0), ignore_user_abort(true), memory_limit=256M.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
DocumentRoot è public/ → simulate-nis2.php (root progetto) era 404.
Aggiunto public/simulate-nis2.php: wrapper che imposta NIS2_SIM env
e include il simulatore reale tramite require __DIR__/../simulate-nis2.php.
Aggiornato URL in simulate.html: ../simulate-nis2.php → simulate-nis2.php.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- simulate-nis2.php: autoResetDemo() via PDO pulisce dati demo prima di ogni
run (SIM-01→05), skip per SIM-06 indipendente. Rimuove tutte le tabelle
org_id>4 eccetto audit_logs (trigger immutabile).
- simulate.html v2.0: rimosso pulsante "Reset Dati Demo" (chiamava endpoint
inesistente /api/admin/reset-demo). Aggiunti: confirm dialog con lista
aziende + durata, spinner sul bottone, nota auto-reset visibile, run history
localStorage (ultimi 5), card SIM-06 B2B License Provisioning, console
phase-banner stile lg231.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Il pattern */30 chiudeva prematuramente il docblock /** causando
parse error. Sostituito con spazio per chiarezza.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- help.js: nuova sezione 'feedback' con 6 sotto-sezioni (come usare FAB,
risposta AI, password gate, le mie segnalazioni, worker autonomo, consigli)
- i18n.js: 30 chiavi IT/EN per tutto il sistema feedback
- AIService::callAPI: system prompt esteso con lista completa moduli NIS2 Agile
- AIService::classifyFeedback: system prompt NIS2-aware
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
BaseController non ha costruttore — la chiamata parent::__construct()
causava Fatal Error "Cannot call constructor" su ogni richiesta.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- index.html: CTA "Registrati" → "Richiedi accesso" (anchor form)
Badge hero "Accesso su invito — Richiedi il tuo codice per iniziare"
Sezione #richiedi-accesso con form lead (nome, email, azienda, ruolo,
dimensioni, messaggio) + JS submit asincrono + stato successo/errore
CTA finale aggiornato con messaggio codice invito
- ContactController.php: POST /api/contact/request-invite
Validazione campi, rate limit 3/10min per IP, email a info@agile.software
tramite EmailService con template HTML branded
- index.php: route contact → ContactController + action requestInvite
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sostituisce il placeholder minimalista con una landing page marketing
completa dark-theme, stile AgentAI hub:
- Hero con mock dashboard interattiva e 4 statistiche chiave
- Sezione normativa: sanzioni Art.34, 18 settori, scadenze Art.23
- Sezione "Per chi è": Azienda PMI vs Consulente/MSSP con feature list
- 9 feature card moduli piattaforma con icone Font Awesome
- Banner integrazione 231 Agile (link a lg231.agile.software)
- How-it-works 4 step con CTA
- CTA finale + footer con info@agile.software
- Brand cyan #06B6D4, Inter font, Font Awesome 6.5.1
- Responsive mobile
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ServicesController::provision(): JWT usa user_id (standard requireAuth)
- simulate-nis2.php: classifyOrg null-safe per entity_type
- simulate-nis2.php: completeOnboarding usa PUT /organizations/{id}
invece di /onboarding/complete (evita 409 quando org già esiste)
- simulate-nis2.php: supplier.critical rimosso da $supDef (was extra field)
- EmailService: rimosso sent_at (non in email_log schema)
- WebhookService: status ?? 'detected' (null-safe)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Il trigger prevent_audit_log_delete blocca DELETE e interrompe lo script.
Fix: drop triggers prima di DELETE audit_logs, poi ricrea.
Richiede esecuzione con utente root MySQL.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>