[DOCS] StarGateWB/Vocea: direttive anonimato segnalante per embed widget + gap NIS2

Ricevute da Vocea (27/6) le 6 regole per preservare l'anonimato del segnalante
nell'embed del widget. Gap analysis NIS2: la pagina app «Segnalazioni»
(whistleblowing.html) è dietro login → NON usabile come canale anonimo; serve una
pagina PUBBLICA pre-login. Più: no-log apertura, no id nell'URL iframe, check
event.origin, Referrer-Policy no-referrer, CSP frame-src app.vocea.cloud.
Origin da dare a Vocea per frame-ancestors: https://nis2.agile.software.
Da applicare all'attivazione Vocea (oggi scaffold dormiente).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
DevEnv nis2-agile
2026-06-27 08:22:23 +02:00
co-authored by Claude Opus 4.8
parent 01b016da50
commit 1fe5b7ae61
+39
View File
@@ -0,0 +1,39 @@
# StarGateWB / Vocea — Anonimato del segnalante nell'embed del Widget (direttive + gap NIS2)
> **Da**: Vocea/StarGateWB · **A**: NIS2 · **Ricevuto**: 2026-06-27 · Riferito all'integrazione Vocea (Modalità C).
> Stato integrazione Vocea: **scaffold dormiente** (`VoceaService`, mig 063, `VOCEA_ENABLED=off`) — vedi `OUTGOING_TO_AGILEHUB_2026_06_23_vocea_whistleblowing_integration.md`. Queste regole diventano vincolanti **quando** costruiamo la pagina di embed (all'attivazione).
## Responsabilità condivisa
- **Vocea garantisce** (non ci pensiamo noi): zero-knowledge (mai testo/identità/allegati/chiavi in chiaro); IP del segnalante mai memorizzato; codice di recupero mai fuori dall'iframe.
- **NIS2 garantisce**: che la **superficie d'accesso non sia tracciabile**.
## Le 6 regole + GAP NIS2 (stato → azione)
| # | Regola Vocea | Stato NIS2 oggi | Azione |
|---|---|---|---|
| 1 | **Accesso pubblico, senza login** (pagina pre-login "Segnala in anonimato") | ❌ `whistleblowing.html` è **dietro login** (`checkAuth()`, sidebar, app-layout) → tracciabile | **Creare una pagina pubblica NUOVA** (pre-login, no sidebar, no checkAuth) che ospita l'iframe Vocea. NON riusare la pagina app «Segnalazioni». |
| 2 | **Non registrare il "passaggio"** (apertura non in audit/web-log/analytics) | ⚠️ la pagina pubblica non deve loggare; il web-log Apache/nginx logga gli accessi | La pagina pubblica = statica, niente audit applicativo; valutare esclusione dal web-log / niente identificatori. Nessun evento "ha aperto il canale". |
| 3 | **Nessun identificativo nell'URL dell'iframe** (`…/segnala/{slug}?embed=1[&theme=dark]`) | ✅ facile (controllato in fase di build) | Iframe `src` SOLO slug+embed; mai employee_id/email/token. |
| 4 | **Verifica origin, non toccare il codice** (`event.origin==='https://app.vocea.cloud'`, envelope `{source:'vocea'}`; non salvare/inoltrare il codice di recupero) | ➖ da implementare nell'embed JS | Listener `postMessage` con check origin + envelope; **mai** persistere il recovery code. |
| 5 | **Niente fughe via referrer/analytics** (`Referrer-Policy: no-referrer`, no analytics terze) | ⚠️ globale = `strict-origin-when-cross-origin` (nginx.conf); nessuna analytics terza nota | Sulla pagina pubblica forzare **`Referrer-Policy: no-referrer`**; zero tag analytics/telemetria. |
| 6 | **CSP allineata** (noi: `frame-src https://app.vocea.cloud`; loro: il nostro origin in `frame-ancestors`) | ⚠️ oggi solo `X-Frame-Options: SAMEORIGIN`, **nessuna CSP `frame-src`** | Aggiungere CSP `frame-src https://app.vocea.cloud` sulla pagina pubblica; comunicare a Vocea il **nostro origin** (sotto). |
## Origin esatto da autorizzare in `frame-ancestors` (lato Vocea)
- **`https://nis2.agile.software`** (produzione, canale pubblico).
- Eventuale wrapper demo: `https://dimostrazione.agile.software` (se si dimostra il canale in demo — da confermare).
## Piano (all'attivazione Vocea, non ora)
1. Nuova pagina **pubblica** `public/segnala-anonimo.html` (o simile): no `checkAuth`, no sidebar, no analytics, `<meta name="referrer" content="no-referrer">` + header CSP `frame-src https://app.vocea.cloud`.
2. Iframe `https://app.vocea.cloud/it/segnala/<slug>?embed=1` (slug del canale dell'org) **oppure** widget `wb-link.js`.
3. Embed JS: check `event.origin` + envelope, nessuna persistenza del recovery code.
4. Coordinare la CSP a doppio lato (frame-src ↔ frame-ancestors) con l'origin sopra.
5. La pagina app «Segnalazioni» (post-login) resta per la **gestione interna** (Art.32 NIS2) o viene dismessa, ma **NON** è il canale anonimo Vocea.
## Checklist go-live (canale reale)
- [ ] Superficie pubblica, senza login
- [ ] "Passaggio" non in audit/web-log/analytics
- [ ] Nessun identificativo nell'URL dell'iframe
- [ ] `event.origin` verificato; recovery code non salvato/inoltrato
- [ ] `Referrer-Policy: no-referrer`, niente analytics terze sulla pagina
- [ ] CSP allineata (`frame-ancestors` ↔ `frame-src`)
Riferimenti Vocea: `app.vocea.cloud/integrazioni.html` · `app.vocea.cloud/it/canale-dedicato` · esempio `docs/api/examples/embed-test.html` (lato Vocea).