# Deploy — Modulo Modello Organizzativo SGSI (ISO 27001) — v1.14.0 > Implementazione completata 2026-06-11. Tutto il **codice** (backend, frontend, help, i18n, AI, KB) è scritto e committato. I passi seguenti richiedono privilegi **host** (DB + docker) e vanno eseguiti su Hetzner. ## Cosa è stato realizzato (già nel repo, files live via bind-mount) | Area | File | |---|---| | Migration schema | `docs/sql/037_isms_model.sql` (4 tabelle SGSI), `docs/sql/038_iso27001_annex_controls.sql` (dataset 111 controlli: 93 Annex A:2022 + 7 CLD/27017 + 11 PII/27018) | | Runner migrazioni | `scripts/migrate-isms.php` | | Backend | `application/controllers/IsmsModelController.php` (16 endpoint) + registrazione in `public/index.php` | | AI | `application/services/AIService.php::generateIsmsDocument()` + fonti ISO in `application/config/nis2_sources.php` | | Frontend | `public/isms.html`, `public/js/isms.js`, metodi `isms*` in `public/js/api.js`, voce sidebar in `public/js/common.js` | | Help + i18n | topic `isms` in `public/js/help.js`, stringhe `isms.*`/`nav.isms` IT/EN in `public/js/i18n.js` | | KB / RAG | `scripts/ingest-iso-sources.php` (catalogo controlli + fonti ISO, scope SYSTEM) | | Versione | `public/version.json` → 1.14.0 | ## Passi di deploy (HOST Hetzner) ### 1. Applicare le migrazioni al DB di produzione Il DB servito dall'app è il MySQL **host** (via socket), NON il container `nis2-db`. Usare il runner con la connessione dell'app: ```bash docker exec nis2-app php /var/www/nis2-agile/scripts/migrate-isms.php ``` Atteso: `iso27001_annex_controls: 111 controlli` (iso27001:93, iso27017:7, iso27018:11) + 4 tabelle SGSI create. Idempotente (CREATE TABLE IF NOT EXISTS + INSERT IGNORE). Alternativa SQL diretta: ```bash mysql -h localhost nis2_agile_db < /var/www/nis2-agile/docs/sql/037_isms_model.sql mysql -h localhost nis2_agile_db < /var/www/nis2-agile/docs/sql/038_iso27001_annex_controls.sql ``` ### 2. Hot-reload PHP-FPM (opcache) Dopo ogni edit `.php` il bytecode in cache va ricaricato: ```bash docker exec nis2-app kill -USR2 1 ``` (HTML/JS sono già live via nginx, non serve reload.) ### 3. Smoke test ```bash # con un JWT valido + X-Organization-Id: curl -s https://nis2.agile.software/api/isms/model -H "Authorization: Bearer " -H "X-Organization-Id: " curl -s https://nis2.agile.software/api/isms/annex-controls -H "Authorization: Bearer " -H "X-Organization-Id: " # UI: aprire https://nis2.agile.software/isms.html → step 1, salvare, andare al SoA (auto-derive dal NIS2) ``` Verifica chiave: con un assessment NIS2 esistente, `GET /api/isms/soa` deve restituire controlli con `derived_from_nis2=1` e uno stato pre-compilato. ### 4. (Opzionale) Ingest KB ISO per il grounding AI Richiede Qdrant + Voyage attivi e migration 038 applicata: ```bash docker exec nis2-app php /var/www/nis2-agile/scripts/ingest-iso-sources.php # anteprima senza scrivere: aggiungere --dry-run ``` ### 5. Push del codice (se non già fatto dal container) Il container NIS2 è legacy: dopo reboot la git credential-cache è vuota. Se il push da devenv non funziona, chiedere all'host (helper vault): > "NIS2 ha N commit su main da pushare, fallo tu dall'host" ## Note / vincoli rispettati - **Additivo**: nessuna tabella esistente modificata; nessun controller esistente alterato nella logica (solo registrazione del nuovo). - **Copyright ISO**: indicizzati solo titoli/sintesi proprietari + riferimenti, mai il testo letterale delle norme. - **Disclaimer**: il modulo è strumento di supporto/pre-audit, non certificazione ISO; l'UI e l'AI lo dichiarano. Gli obblighi normativi italiani restano NIS2 / D.Lgs. 138/2024 / ACN. - **27017:2015 / 27018:2019**: versioni attuali (nessuna revisione più recente). 27017 numerata su 27002:2013 → `iso27002_ref` conserva il cross-reference. ## Rollback ```sql DROP TABLE IF EXISTS isms_soa, isms_roles, isms_documents, isms_models, iso27001_annex_controls; ``` + rimuovere la riga `'isms'` da controllerMap/actionMap in `public/index.php`, USR2. Il frontend `isms.html` resta inerte senza backend.