[DOCS] Design modulo questionari fornitori + portale OTP + AI consulente normativo

Pacchetto di design completo (nessun codice applicato, nessuna migrazione eseguita):
- DESIGN aggiornato con 5 review agenti + 3 decisioni utente + pilastro AI consulente (sez. 12-14)
- docs/supplier-portal/template-nis2-base.questions.json: 26 domande GV.SC (Allegato 2 ACN) con nis2_ref/vuln_flag e fonti certe verbatim
- docs/supplier-portal/AI_CONSULENTE_NORMATIVO.md: corpus normativo aggiornato + persona consulente (modello TRPG)
- docs/supplier-portal/UX_MINI_SPEC.md: mini-spec portale fornitore (stati/copy/autosave/mobile/a11y/editor no-code)
- docs/sql/032-035: migrazioni idempotenti proposte (modulo, suppliers, portale auth, migrazione 027->campaigns)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
DevEnv nis2-agile
2026-05-31 09:53:07 +02:00
co-authored by Claude Opus 4.8
parent dce53a0d0c
commit aa2db4c6c2
8 changed files with 749 additions and 2 deletions
@@ -0,0 +1,91 @@
# Pilastro AI "vero consulente NIS2" — corpus normativo incluso/aggiornato + persona consulente
> Deliverable agente design 2026-05-31 (richiesta utente: "come TRPG, contesto normativo incluso e aggiornato + AI istruita, un vero consulente"). Sola analisi; nessun codice applicato.
> Riferimento incrociato: [[DESIGN_MODULO_QUESTIONARI_FORNITORI]] §13.
## 0. Stato attuale (già esistente in produzione)
La pipeline RAG c'è già e funziona — NON si riparte da zero:
- `EmbedService` (Voyage `voyage-3-lite`, 512-dim), `VectorService` (Qdrant `nis2_kb`, Cosine, filtro authz 3 livelli), `RagService` (embed→search→format).
- `AIService::askWithRag()` (top-5, minScore 0.28, fallback graceful) + `authoritativeSourcesBlock()` (anti-allucinazione).
- `AiController` → `POST /api/ai/ask` (rate-limited, audit). Persona **ARIA_SUPPORT_NIS2** (id=4, operativa).
- Registry fonti `application/config/nis2_sources.php` (7 fonti). Ingest `scripts/ingest-nis2-sources.php` — **eseguito 2026-05-29: 287 chunk** (NIS2 171 + CER 77 + Det.333017 25 + Det.164179 9 + Ambiti 5).
- Feed `normative_updates` + ACK (mig.009) — ma **scollegato dalla KB**.
- Catalogo requisiti ACN granulari: mig.031 + `docs/nis2/allegati_acn/acn_requirements.json` (87 imp + 116 ess) — in DB/JSON ma **non in KB**.
## 1. Gap del corpus (da colmare — priorità)
1. **D.Lgs. 138/2024 ASSENTE** (`file => null` nel registry) — fonte primaria obblighi italiani. **Priorità massima.**
2. **203 requisiti ACN granulari** (Allegati 1-2) non in KB → ingerire come **chunk-per-requisito** con payload ricco (`subcategory=GV.SC-04`, `function`, `entity=essenziale/importante`, `source`). È il salto da "conosce la direttiva" a "conosce i requisiti puntuali da audit".
3. Assenti dal registro/KB: **Reg. UE 2024/2690**, **ENISA Good Practices Supply Chain**, **NIST SP 800-161r1 / CSF 2.0**, **DORA (Reg. UE 2022/2554)**.
4. Fix banale: commento `EmbedService` dice "1024 dim" ma il codice forza 512 (coerente con la collection) → allineare per evitare ricreazioni errate.
> Copyright: ISO 27001 e materiali ENISA/NIST → ingerire solo sintesi/mappature proprie o testi a licenza aperta, non riproduzioni integrali protette.
## 2. Aggiornamento del corpus (chiudere il ciclo)
Oggi `normative_updates` (feed UI/ACK) e `nis2_kb` (Qdrant) sono disgiunti. Design:
- **Versioning fonte** in `nis2_sources.php`: `version`, `published_at`, `supersedes`, `status (in_force|superseded|draft)`, `content_sha`.
- **Idempotenza** ingest: `doc_uuid` deterministico per-fonte (`uuid5(ns,key)`) + `content_sha` nel payload → skip re-embed se invariato (risparmio Voyage).
- **Feed → KB**: estendere `NormativeController::create()` per ingerire opzionalmente in `nis2_kb` (scope SYSTEM) quando un super_admin pubblica un update con testo. Aggiungere `normative_updates.kb_indexed`, `kb_doc_uuid`. Così l'ACK audit e la conoscenza AI nascono dallo stesso atto.
- **Cron** settimanale `ingest-nis2-sources.php` (cron registry AgileHub, TZ Europe/Rome, log `/var/log/nis2/`), `--dry-run` confronta `content_sha`, re-ingerisce solo i delta.
- **Provenienza nei payload**: `version`, `published_at`, `url` → `formatContext()` espone la data ("secondo la Determina ACN 164179 del 14/04/2025…").
- **Cruscotto** `GET /api/knowledgebase/corpus-status` (super_admin): fonti, versione ingerita, ultimo ingest, drift vs registry.
> Caveat: `kb_uploaded_documents` (mig.013) potrebbe non essere applicata su prod → applicare migrazioni KB su Hetzner (`mysql -h localhost`) prima di basarvi il cruscotto.
## 3. Persona consulente — rafforzare i system prompt
Debolezze attuali di `askWithRag()`: prompt generico ("cita quando rilevante" → non obbligatorio), nessun tono/scope/persona, nessun comportamento esplicito quando la KB non copre, nessun disclaimer consulenza legale. Inoltre `suggestRisks`/`generatePolicy` **non** iniettano le fonti certe (incoerenza).
### Bozza system prompt (da iniettare in askWithRag, conforme a persona-conversational-rules v2.0)
```
# IDENTITÀ
Sei ARIA, consulente esperto di cybersecurity e compliance NIS2 della piattaforma
"NIS2 Agile". Operi come un consulente NIS2 reale: rigoroso, concreto, orientato
all'azione. Rispondi sempre in italiano professionale. Se ti viene chiesto
esplicitamente, dichiari di essere un assistente AI.
# AMBITO
Direttiva (UE) 2022/2555 (NIS2), (UE) 2022/2557 (CER), D.Lgs. 138/2024,
Determinazioni ACN (specifiche di base, classificazione/notifica incidenti),
Framework Nazionale (GV/ID/PR/DE/RS/RC) e l'uso operativo dei moduli della piattaforma.
# REGOLE DI CITAZIONE (vincolanti)
1. OGNI affermazione normativa DEVE citare la fonte: articolo/comma, determina+allegato,
o il riferimento [n] del contesto documentale.
2. Col contesto presente, cita i riferimenti [1],[2]… dei documenti forniti.
3. NON inventare numeri di articolo, determine, allegati, date o requisiti. Se incerto,
dichiaralo e rimanda alla fonte ufficiale.
4. Preferisci D.Lgs.138/2024 + Determine ACN per gli OBBLIGHI OPERATIVI; la Direttiva UE
per i PRINCIPI.
# QUANDO MANCA IL CONTESTO
Dichiaralo ("Non ho trovato un riscontro nelle fonti indicizzate") e rispondi con
conoscenza generale chiaramente etichettata come tale, senza citare fonti inventate.
# FUORI AMBITO (rifiuto cortese, niente eco di parole problematiche)
"Mi occupo di compliance NIS2 e cybersecurity. Per [tema] ti consiglio di rivolgerti
alla funzione competente."
# LIMITI (no deception / GDPR)
Orientamento di compliance, NON consulenza legale vincolante: per decisioni formali
rimanda a un legale o all'ACN. Non includere mai dati identificativi dell'organizzazione.
# STILE
Conciso e strutturato: (1) risposta diretta, (2) base normativa citata, (3) azione
consigliata nella piattaforma. Niente preamboli.
```
Sotto si concatenano `authoritativeSourcesBlock()` + contesto documentale numerato.
### Centralizzazione
Estrarre i blocchi prompt in `application/config/ai_persona.php` (single source of truth) e iniettarli in tutti i metodi `AIService` (oggi solo classifyIncident/askWithRag sono grounded).
## 4. Integrazione coi questionari fornitori (primo caso d'uso del consulente in-context)
- **(a) "Perché te lo chiediamo?"** (lato azienda): pulsante per domanda → `POST /api/ai/ask` precompilata "Spiega in 2 frasi il requisito {nis2_ref} e perché è rilevante per la sicurezza della catena di fornitura". Grounded sul chunk-per-requisito.
- **(b) Guida compilazione** (lato fornitore, no-auth): endpoint dedicato **read-only, rate-limited** `POST /api/supplier-portal/explain` che accetta solo il `nis2_ref` e risponde da cache pre-generata / RAG scope SYSTEM (no esposizione di askWithRag completo a non autenticati, niente PII).
- **(c) `AIService::suggestSupplierRemediation(negativeAnswers, supplierContext)`** grounded: per ogni vuln_flag/"no" propone rimedio citando GV.SC/PR + Art.21.2(d) → alimenta piano trattamento fornitore o NCR/CAPA. Anonimizzare (no nome/P.IVA nel prompt).
## 5. Piano incrementale
- **Fase 0 (igiene, ~0.5g)**: allineare commento EmbedService 512; grounding anche in `suggestRisks`/`generatePolicy`.
- **Fase 1 (corpus, alto valore)**: procurare D.Lgs.138/2024 (Gazzetta Ufficiale), promuovere Allegati 1-2 a fonti KB, ingerire i 203 requisiti chunk-per-requisito, eseguire `seed_acn_requirements.php`. Su Hetzner (Qdrant+Voyage), non in devenv.
- **Fase 2 (persona, ~basso rischio)**: `ai_persona.php` + nuovo prompt askWithRag; aggiornare help.js + KB ARIA; smoke 10-15 domande note + 3 fuori scope + 1 senza copertura.
- **Fase 3 (ciclo aggiornamento)**: versioning registry + doc_uuid/content_sha + feed→KB + cron + cruscotto corpus-status.
- **Fase 4 (AI nei questionari)**: dipende dal modulo questionari — "perché te lo chiediamo", `supplier-portal/explain`, `suggestSupplierRemediation`.
## 6. Rischi trasversali
Qdrant IP drift (assegnare ipv4 statico, conferma utente) · PHP-FPM Alpine env/DNS (mantenere multi-source lookup + IP letterale) · DB topology = host MySQL · disciplina commit (USR2→smoke→commit) · copyright ISO/ENISA/NIST.
+68
View File
@@ -0,0 +1,68 @@
# Mini-spec UX — Portale fornitore + Editor lato azienda (§6)
> Deliverable agente design 2026-05-31. Chiude i finding UX F1–F25 di [[DESIGN_MODULO_QUESTIONARI_FORNITORI]] §12. Copy + comportamento + acceptance criteria.
> Utente di riferimento del portale: referente PMI fornitrice, NON tecnico, da smartphone, 1 volta ogni 6-12 mesi, senza supporto IT. Ogni scelta privilegia chiarezza, target ≥44px, recupero da errore sempre possibile.
> Convenzioni riusate (verificate): `--primary:#06B6D4`; progress bar di `assessment.html` (`updateProgressBar`, id `progress-pct/-bar-fill/-answered/-total`, i18n `assessment.progress`); `debounce`, `showNotification`, `_loadFirmBranding()` (GET `/api/branding/current`), `initIdleTimeout()` overlay countdown — in `common.js`; badge `badge-success|warning|danger|neutral`; `sendSupplierQuestionnaire`+prompt rigenera-link in `supply-chain.html`; baseline + footer GDPR + `noindex,nofollow` in `supplier-assessment.html`.
> Endpoint (forma router §12): `POST /api/supplier-portal/request-otp`, `verify-otp`, `GET /me`, `GET /{id}`, `POST /{id}/submit`, `PATCH /{id}/answers`.
> i18n: namespace `sp.*` (+ `sp.editor.*`) in `i18n.js`; ogni stringa IT ha controparte EN.
## 1. Portale fornitore — supplier-portal.html
Principi: una colonna max 560px, branding del **committente** in header (NIS2 Agile solo footer), zero gergo ("codice"/"link"/"questionario", mai "token/OTP/JWT/campaign"), selettore lingua IT/EN in alto a destra, `noindex,nofollow`, nessun link all'app interna.
Stati:
1. **Loading**: spinner; se `GET /me`/branding >8s → stato errore rete.
2. **Richiesta accesso**: input email (`type=email inputmode=email autocomplete=email autofocus`, label visibile), CTA "Invia link di accesso", micro-copy GDPR con link informativa. **Risposta sempre opaca** (anti-enumerazione) → va sempre allo stato "email inviata".
3. **Email inviata**: "Controlla la tua email" + avviso spam + mittente; campo OTP fallback; **reinvio con countdown 60s** (raddoppia dal 3° invio); via d'uscita "Usa un'altra email".
4. **Verifica OTP — errori specifici** (F2/F3): messaggi umani con via d'uscita per: codice errato ("…hai ancora {n} tentativi", contatore reale da `supplier_otp.attempts`), scaduto ("→ Invia un nuovo codice"), lockout ("bloccato per {minuti} min", persistente lato DB), link già usato ("→ Invia un nuovo link"), errore rete ("Riprova"). Mai codici HTTP/"token".
5. **Gerarchia magic-link/OTP** (F1/F4): nel portale e nell'email il **pulsante magic-link è primario**, OTP fallback. **No doppio-consumo**: l'apertura del link (prefetch mail mobile) NON consuma il token; consumo solo al click esplicito "Entra nel portale". AC: aprire 2× e poi cliccare deve funzionare.
6. **Dashboard**: se **1 solo questionario aperto** → vai diretto alla compilazione. Se multipli → card con badge stato + scadenza in chiaro + CTA "Compila/Riprendi/Vedi ricevuta"; ordinamento da-compilare prima per scadenza.
7. **Compilazione**: header con badge scadenza sticky + progress bar + domande single-page (vedi §4).
8. **Vuoto**: "Nessun questionario in attesa" + suggerimento contattare committente.
9. **Completato/Ricevuta**: "Questionario inviato. Grazie!" + "Scarica PDF" + (Caso B) "Torna ai questionari". **Score mostrato solo se `show_score_to_supplier=true`** (default OFF, F23) → rimuovere/condizionare lo score sempre-mostrato dell'attuale supplier-assessment.html.
10. **Errore rete**: non distruttivo, risposte salvate localmente, "Riprova".
11. **Sessione in scadenza (4h)**: overlay countdown (riuso `initIdleTimeout`), "Continua" estende; alla scadenza "Le tue risposte sono salvate. Richiedi un nuovo link per riprendere". Ripresa dall'ultima domanda dopo nuovo OTP.
## 2. Autosave (F11 — priorità assoluta)
- Stato `in_progress` alla prima risposta. Salvataggio per-domanda via `PATCH /{id}/answers` con `debounce(fn,800)`.
- **Doppio livello**: localStorage immediato (resilienza offline) + PATCH server (cross-device). Server = source of truth; rinvia PATCH falliti.
- Indicatore discreto: "Salvataggio…" / "Bozza salvata {ora}" / "Salvataggio in sospeso — riproveremo".
- **Ripresa**: banner "Bentornato. Hai risposto a {x} di {y} domande" + "Riprendi" → scroll alla prima domanda senza risposta.
- **"Salva bozza"** (ghost, ridondante ma rassicurante) vs **"Invia definitivo"** (CTA primaria, conferma in modale "dopo l'invio non potrai modificare", disabilitata finché le obbligatorie non sono complete; se mancano → scroll alla prima + "{k} risposte obbligatorie mancanti").
- AC: chiudere/riaprire (anche altro device dopo nuovo OTP) → risposte presenti, cursore sull'ultima non risposta; submit blocca PATCH successivi (409 "già inviato").
## 3. Email invito/OTP (F6)
Inviata via template `/api/emails/send` (NON `send-raw` → OTP fuori da `email_log`). Branding committente, **una sola CTA**.
Contenuto minimo: (1) oggetto con nome committente; (2) motivo 1 frase ("Come fornitore di {Committente}…richiesto dalla normativa NIS2"); (3) tempo stimato (~{n} min); (4) scadenza in chiaro (solo se `due_at`); (5) CTA singola magic-link "Compila il questionario"; (6) OTP fallback "Oppure inserisci questo codice: 123 456 (15 min)"; (7) validità "15 minuti e una sola volta"; (8) footer GDPR Art.13/14 (titolare=committente, NIS2 Agile=responsabile Art.28, link informativa, "se non eri tu, ignora").
AC: OTP mai nei log; 1 sola CTA; nome committente in oggetto+corpo; scadenza solo se valorizzata.
## 4. Compilazione — ergonomia per tipo
Chrome: progress bar (riuso `updateProgressBar`) + "{answered} di {total}"; badge scadenza sticky (neutral >7gg / warning ≤7gg / danger scaduto).
Per tipo:
- `yes_no_partial`: 3 bottoni grandi (radio nativi sotto) "Sì/Parzialmente/No".
- `scale_1_5`: 5 bottoni con **etichette agli estremi sempre visibili** (da options min/max). Mai scala nuda.
- `single_choice`: radio nativi verticali. `multi_choice`: checkbox + hint "Puoi selezionare più opzioni".
- `text`: textarea + esempio placeholder. `number`: `inputmode=numeric`.
- `file`: formati/dimensioni dichiarati prima del tap; `accept` + `capture` (foto documenti); feedback upload (%/check/rimuovi); errori formato/dimensione con suggerimento; async, sopravvive ad autosave (`file_ref`).
- `help_text`: **sempre visibile** sotto la domanda (mai tooltip/hover — non funziona su touch).
- **"Non applicabile" / "Non so"** dove sensato: conta come risposta per la progress bar, distinto dal "No" nello scoring.
## 5. Ricevuta, multi-referente, score
- **Ricevuta (F22)**: email conferma al referente + **PDF risposte** scaricabile (da email e da §1.9). PDF = intestazione committente+fornitore, data, domande+risposte+allegati, riferimento normativo. Niente score se OFF. Snapshot immutabile → rigenerabile identico.
- **Multi-referente/delega (F24)**: "Inoltra a un collega" → nuovo accesso OTP per quell'email, stessa campagna/`supplier_id`, autosave condiviso, traccia `answered_by`. Delegato vede solo quella campagna (no IDOR), stessi limiti OTP.
- **Score (F23)**: `show_score_to_supplier` per template/campagna, **default false**. OFF = solo conferma invio. Toggle nell'editor "Mostra il punteggio al fornitore".
## 6. Editor lato azienda (F16) — no-code in supply-chain.html
Tab "Categorie" / "Template questionari" / "Campagne-scadenze". Mappatura tecnico→no-code:
- `slug`/`code`: auto-generati, nascosti. `order_index`: drag-and-drop (+ frecce ↑/↓ accessibili).
- `options` JSON: editor a righe ("+ Aggiungi opzione"); scale = 2 campi "Etichetta minimo/massimo".
- `reminder_offsets`: chip "14/7/1 giorni prima". `recurrence_months`: dropdown "Una tantum/Ogni 6/12/24 mesi/Personalizzato".
- `weight`: dropdown "Bassa/Media/Alta". `type`: etichette umane. `required`: toggle. `nis2_ref`: chip informativo non editabile. `show_score_to_supplier`: toggle (default OFF).
- **Anteprima "come lo vede il fornitore"**: stesso componente di rendering della compilazione (single source).
- **Versioning (F17)**: salvare un template con campagne attive → modale "crea nuova versione v{x+1}, si applica solo alle campagne future; le {n} in corso restano su v{x}". Snapshot in `questionnaire_template_versions`.
- **Cruscotto campagne**: semaforo (badge), colonne Fornitore/Questionario/Stato/Scadenza/Avanzamento/Azioni. Azioni rapide: Sollecita, Copia link (fallback manuale), Vedi risposte. **Bulk**: sollecita/avvia/esporta selezionati, con conferma e conteggio. Rispetta rate-limit reminder.
## 7. Accessibilità (F21) + mobile-first (F10)
Elementi nativi (`button`, `input radio/checkbox` con `label`); OTP `inputmode=numeric autocomplete=one-time-code pattern=[0-9]* maxlength=6`; email `inputmode=email autocomplete=email`. ARIA: `aria-live=polite` per autosave/progress, `role=alert` per errori; focus order logico, focus torna sul campo dopo errore OTP; modali con focus trap + Esc + `aria-modal`. Drag-drop con alternativa tastiera. Contrasto ≥WCAG AA, stato non solo da colore. Target ≥44×44px, single-column, no hover-only. AC: flusso completo navigabile da sola tastiera e da screen reader; OTP autofill; nessun target <44px a 360px.
## 8. i18n (F20)
Namespace `sp.*`. Lingua portale: (1) impostata dal cliente su campagna (`language it|en|auto`), (2) selezionabile dal fornitore (persistita in localStorage), (3) fallback `navigator.language` → IT. Email nella lingua della campagna. Chrome (header/footer/badge/errori/pulsanti) bilingue; i **contenuti domande** restano nella lingua in cui l'azienda li ha scritti (il selettore non auto-traduce i contenuti). AC: cambio lingua immediato senza reload; `campaign.language=en` → portale ed email in EN; nessuna stringa IT hardcoded in modalità EN.
@@ -0,0 +1,37 @@
{
"_meta": {
"template": "NIS2 base - Sicurezza catena di fornitura",
"description": "Template predefinito mappato alle misure ACN GV.SC (Allegato 2, Determina 164179/2025) e all'Art. 21.2(d)/21.3 della Direttiva (UE) 2022/2555. Tutte le help_text citano fonti CERTE presenti in application/config/nis2_sources.php (slug: acn_specifiche_base_2025, nis2_directive). Le fonti ENISA/NIST NON sono usate finche' non vengono aggiunte al registro fonti e ingerite in KB.",
"scoring": "yes=1.0 / partial=0.5 / no=0.0; scale_1_5 normalizzato (val-1)/4 (flag se <=2); number RTO flag se vuoto o oltre soglia per criticita; single/multi_choice non scorate ma generano flag se esposizione elevata. Output: score, risk_level, vulnerabilities[] (lista vuln_flag accesi) -> realizza Art. 21.3.",
"high_criticality_note": "Le domande con high_criticality_only=true si mostrano solo a suppliers.criticality in (high, critical).",
"source": "Prodotto da agente design 2026-05-31. Citazioni verbatim da docs/nis2/allegati_acn/Allegato2.txt (GV.SC, righe 111-189) e docs/nis2/Dir2022_2555_UE_NIS2_ITA.pdf.txt (Art.21)."
},
"questions": [
{ "order_index": 1, "code": "gvsc07_a_access_level", "text": "Qual e' il livello di accesso che la vostra fornitura richiede ai sistemi informativi e di rete del cliente?", "type": "single_choice", "options": ["nessun_accesso","accesso_applicativo_limitato","accesso_rete_segmentato","accesso_amministrativo_privilegiato"], "weight": 5, "required": true, "help_text": "ACN Allegato 2, GV.SC-07 §1.a: «il livello di accesso del fornitore ai sistemi informativi e di rete del soggetto NIS».", "nis2_ref": "GV.SC-07.a", "vuln_flag": "access_privileged_unmanaged", "high_criticality_only": false },
{ "order_index": 2, "code": "gvsc07_b_data_access", "text": "A quali tipologie di dati o proprieta' intellettuale del cliente avete accesso?", "type": "multi_choice", "options": ["nessun_dato","dati_aziendali_non_sensibili","dati_personali","dati_critici_o_segreti","proprieta_intellettuale"], "weight": 4, "required": true, "help_text": "ACN Allegato 2, GV.SC-07 §1.b: «l'accesso del fornitore alla proprieta' intellettuale e ai dati anche sulla base della loro criticita'».", "nis2_ref": "GV.SC-07.b", "vuln_flag": "sensitive_data_access", "high_criticality_only": false },
{ "order_index": 3, "code": "gvsc07_c_disruption_impact", "text": "Disponete di misure che limitano l'impatto sul cliente in caso di grave interruzione della vostra fornitura?", "type": "yes_no_partial", "options": null, "weight": 4, "required": true, "help_text": "ACN Allegato 2, GV.SC-07 §1.c: «l'impatto di una grave interruzione della fornitura».", "nis2_ref": "GV.SC-07.c", "vuln_flag": "no_continuity_for_client", "high_criticality_only": false },
{ "order_index": 4, "code": "gvsc07_d_rto", "text": "Qual e' il vostro RTO (Recovery Time Objective) dichiarato, in ore, per il ripristino del servizio in caso di indisponibilita'?", "type": "number", "options": null, "weight": 4, "required": true, "help_text": "ACN Allegato 2, GV.SC-07 §1.d: «i tempi e i costi di ripristino in caso di indisponibilita' dei servizi».", "nis2_ref": "GV.SC-07.d", "vuln_flag": "rto_undefined_or_high", "high_criticality_only": false },
{ "order_index": 5, "code": "gvsc07_d_recovery_cost", "text": "Avete documentato una stima dei tempi e dei costi di ripristino dei servizi forniti al cliente?", "type": "yes_no_partial", "options": null, "weight": 3, "required": true, "help_text": "ACN Allegato 2, GV.SC-07 §1.d: «i tempi e i costi di ripristino in caso di indisponibilita' dei servizi».", "nis2_ref": "GV.SC-07.d", "vuln_flag": "recovery_cost_unknown", "high_criticality_only": true },
{ "order_index": 6, "code": "gvsc07_e_roles", "text": "I ruoli e le responsabilita' del vostro personale nel governo dei sistemi informativi e di rete del cliente sono formalizzati (es. a contratto)?", "type": "yes_no_partial", "options": null, "weight": 4, "required": true, "help_text": "ACN Allegato 2, GV.SC-07 §1.e: «i ruoli e le responsabilita' del fornitore nel governo dei sistemi informativi e di rete».", "nis2_ref": "GV.SC-07.e", "vuln_flag": "no_security_roles_defined", "high_criticality_only": false },
{ "order_index": 7, "code": "iso27001", "text": "Disponete di una certificazione ISO/IEC 27001 (o equivalente) in corso di validita'?", "type": "yes_no_partial", "options": null, "weight": 4, "required": true, "help_text": "ACN Allegato 2, GV.SC-01 §2.d «conformita' e audit di sicurezza»; affidabilita' del fornitore ex GV.SC-01 §2.a.", "nis2_ref": "GV.SC-01.2.d", "vuln_flag": "no_iso27001", "high_criticality_only": false },
{ "order_index": 8, "code": "mfa", "text": "Imponete l'autenticazione a piu' fattori (MFA) per gli accessi ai sistemi che trattano dati del cliente?", "type": "yes_no_partial", "options": null, "weight": 5, "required": true, "help_text": "ACN Allegato 2, GV.SC-01 §2.g «gestione dell'autenticazione, delle identita' digitali e del controllo accessi»; cfr. Direttiva (UE) 2022/2555, Art. 21.2.j (autenticazione a piu' fattori).", "nis2_ref": "GV.SC-01.2.g", "vuln_flag": "no_mfa", "high_criticality_only": false },
{ "order_index": 9, "code": "patching", "text": "Avete un processo formale di patch management e gestione delle vulnerabilita'?", "type": "yes_no_partial", "options": null, "weight": 4, "required": true, "help_text": "ACN Allegato 2, GV.SC-01 §2.e «gestione delle vulnerabilita'»; cfr. Direttiva (UE) 2022/2555, Art. 21.2.e.", "nis2_ref": "GV.SC-01.2.e", "vuln_flag": "no_patch_mgmt", "high_criticality_only": false },
{ "order_index": 10, "code": "backup", "text": "Eseguite backup regolari con test di ripristino documentati?", "type": "yes_no_partial", "options": null, "weight": 4, "required": true, "help_text": "ACN Allegato 2, GV.SC-01 §2.f «continuita' operativa e ripristino in caso di disastro».", "nis2_ref": "GV.SC-01.2.f", "vuln_flag": "no_backup_tested", "high_criticality_only": false },
{ "order_index": 11, "code": "incident", "text": "Disponete di un piano di gestione degli incidenti che preveda la notifica al cliente?", "type": "yes_no_partial", "options": null, "weight": 5, "required": true, "help_text": "ACN Allegato 2, GV.SC-01 §2.m «gestione e segnalazione degli incidenti»; cfr. Direttiva (UE) 2022/2555, Art. 21.2.b.", "nis2_ref": "GV.SC-01.2.m", "vuln_flag": "no_incident_plan", "high_criticality_only": false },
{ "order_index": 12, "code": "access_review", "text": "Effettuate revisioni periodiche degli accessi con revoca tempestiva al cambio/cessazione di personale?", "type": "yes_no_partial", "options": null, "weight": 3, "required": true, "help_text": "ACN Allegato 2, GV.SC-01 §2.g «gestione dell'autenticazione, delle identita' digitali e del controllo accessi».", "nis2_ref": "GV.SC-01.2.g", "vuln_flag": "no_access_review", "high_criticality_only": false },
{ "order_index": 13, "code": "encryption", "text": "I dati del cliente sono cifrati a riposo e in transito con algoritmi allo stato dell'arte?", "type": "yes_no_partial", "options": null, "weight": 4, "required": true, "help_text": "ACN Allegato 2, GV.SC-01 §2.j «sicurezza dei dati»; cfr. Direttiva (UE) 2022/2555, Art. 21.2.h (crittografia).", "nis2_ref": "GV.SC-01.2.j", "vuln_flag": "no_encryption", "high_criticality_only": false },
{ "order_index": 14, "code": "subcontractor", "text": "Valutate la sicurezza dei vostri sub-fornitori (quarta parte) prima dell'affidamento?", "type": "yes_no_partial", "options": null, "weight": 3, "required": true, "help_text": "ACN Allegato 2, GV.SC-01 §2.q «subappalto, subfornitura o relativi potenziali requisiti di sicurezza lungo la catena di fornitura».", "nis2_ref": "GV.SC-01.2.q", "vuln_flag": "no_fourthparty_assessment", "high_criticality_only": false },
{ "order_index": 15, "code": "gvsc01_p_data_return", "text": "A fine fornitura garantite la restituzione e la cancellazione certificata dei dati del cliente?", "type": "yes_no_partial", "options": null, "weight": 4, "required": true, "help_text": "ACN Allegato 2, GV.SC-01 §2.p «dismissione della fornitura ivi compresa la restituzione e la cancellazione dei dati».", "nis2_ref": "GV.SC-01.2.p", "vuln_flag": "no_data_deletion_exit", "high_criticality_only": false },
{ "order_index": 16, "code": "gvsc01_q_subcontracting", "text": "In caso di subappalto/subfornitura, trasferite contrattualmente gli stessi requisiti di sicurezza lungo la catena di fornitura?", "type": "yes_no_partial", "options": null, "weight": 4, "required": true, "help_text": "ACN Allegato 2, GV.SC-01 §2.q «subappalto, subfornitura o relativi potenziali requisiti di sicurezza lungo la catena di fornitura».", "nis2_ref": "GV.SC-01.2.q", "vuln_flag": "no_security_flowdown", "high_criticality_only": false },
{ "order_index": 17, "code": "gvsc01_q_critical_subs", "text": "Elencate i sub-fornitori critici (quarta parte) coinvolti nella fornitura al cliente (ragione sociale e servizio).", "type": "text", "options": null, "weight": 3, "required": false, "help_text": "ACN Allegato 2, GV.SC-01 §2.q (catena di fornitura); cfr. Direttiva (UE) 2022/2555, Art. 21.3 (vulnerabilita' per ogni diretto fornitore e fornitore di servizi).", "nis2_ref": "GV.SC-01.2.q", "vuln_flag": "critical_subs_undisclosed", "high_criticality_only": true },
{ "order_index": 18, "code": "gvsc01_n_secure_dev", "text": "Adottate pratiche di sviluppo sicuro del codice e di sicurezza fin dalla progettazione e per impostazione predefinita?", "type": "yes_no_partial", "options": null, "weight": 4, "required": true, "help_text": "ACN Allegato 2, GV.SC-01 §2.n «sviluppo sicuro del codice e sicurezza fin dalla progettazione e per impostazione predefinita»; cfr. Direttiva (UE) 2022/2555, Art. 21.3 (procedure di sviluppo sicuro).", "nis2_ref": "GV.SC-01.2.n", "vuln_flag": "no_secure_dev", "high_criticality_only": false },
{ "order_index": 19, "code": "gvsc01_c_hr_reliability", "text": "Verificate l'affidabilita' del personale (es. background check) prima di assegnarlo ad attivita' con accesso ai dati/sistemi del cliente?", "type": "yes_no_partial", "options": null, "weight": 3, "required": true, "help_text": "ACN Allegato 2, GV.SC-01 §2.c «affidabilita' delle risorse umane».", "nis2_ref": "GV.SC-01.2.c", "vuln_flag": "no_hr_screening", "high_criticality_only": false },
{ "order_index": 20, "code": "gvsc01_f_dr_plan", "text": "Disponete di un piano di continuita' operativa e di disaster recovery documentato e testato?", "type": "yes_no_partial", "options": null, "weight": 4, "required": true, "help_text": "ACN Allegato 2, GV.SC-01 §2.f «continuita' operativa e ripristino in caso di disastro».", "nis2_ref": "GV.SC-01.2.f", "vuln_flag": "no_dr_plan", "high_criticality_only": false },
{ "order_index": 21, "code": "gvsc01_n_secdev_sdlc", "text": "In che misura il vostro ciclo di sviluppo prevede test di sicurezza pre-rilascio (SAST/DAST/code review)?", "type": "scale_1_5", "options": ["1_assenti","2_occasionali","3_su_progetti_chiave","4_sistematici","5_automatizzati_in_pipeline"], "weight": 2, "required": false, "help_text": "ACN Allegato 2, GV.SC-01 §2.n «sviluppo sicuro del codice e sicurezza fin dalla progettazione e per impostazione predefinita».", "nis2_ref": "GV.SC-01.2.n", "vuln_flag": "weak_sdlc", "high_criticality_only": true },
{ "order_index": 22, "code": "gvsc02_security_contact", "text": "Avete designato un referente/punto di contatto per la sicurezza informatica per questa fornitura?", "type": "yes_no_partial", "options": null, "weight": 3, "required": true, "help_text": "ACN Allegato 2, GV.SC-02 §1 (ruoli e responsabilita' di sicurezza per fornitori «stabiliti, comunicati e coordinati internamente ed esternamente»).", "nis2_ref": "GV.SC-02.1", "vuln_flag": "no_security_contact", "high_criticality_only": false },
{ "order_index": 23, "code": "gvsc02_staff_roles", "text": "I ruoli e le responsabilita' in materia di sicurezza del vostro personale che opera presso/per il cliente sono definiti e comunicati?", "type": "yes_no_partial", "options": null, "weight": 3, "required": true, "help_text": "ACN Allegato 2, GV.SC-02 §1: «i ruoli e responsabilita' in materia di sicurezza informatica assegnati al personale delle terze parti».", "nis2_ref": "GV.SC-02.1", "vuln_flag": "no_staff_security_roles", "high_criticality_only": false },
{ "order_index": 24, "code": "gvsc05_contract_clauses", "text": "Siete disponibili ad accettare clausole contrattuali di sicurezza informatica richieste dal cliente?", "type": "yes_no_partial", "options": null, "weight": 4, "required": true, "help_text": "ACN Allegato 2, GV.SC-05 §1 (requisiti di sicurezza «integrati nei contratti e in altri tipi di accordi con i fornitori»).", "nis2_ref": "GV.SC-05.1", "vuln_flag": "no_security_clauses", "high_criticality_only": false },
{ "order_index": 25, "code": "gvsc05_audit_right", "text": "Consentite al cliente di verificare periodicamente, anche tramite audit, la conformita' della fornitura ai requisiti di sicurezza?", "type": "yes_no_partial", "options": null, "weight": 3, "required": true, "help_text": "ACN Allegato 2, GV.SC-07 §2: «E' verificata periodicamente e documentata la conformita' delle forniture ai requisiti di cui alla misura GV.SC-05».", "nis2_ref": "GV.SC-07.2", "vuln_flag": "no_audit_right", "high_criticality_only": true },
{ "order_index": 26, "code": "gvsc05_breach_notify", "text": "Vi impegnate contrattualmente a notificare al cliente incidenti/violazioni di sicurezza entro termini definiti?", "type": "yes_no_partial", "options": null, "weight": 4, "required": true, "help_text": "ACN Allegato 2, GV.SC-05 §1 (requisiti integrati nei contratti) in combinato con GV.SC-01 §2.m «gestione e segnalazione degli incidenti».", "nis2_ref": "GV.SC-05.1", "vuln_flag": "no_contractual_breach_notify", "high_criticality_only": false }
]
}