[FEAT] Canale anonimo Vocea: pagina pubblica pre-login (scheletro) + risposta a Vocea
segnala-anonimo.html: pagina PUBBLICA (no checkAuth, no sidebar, no common.js/api.js/
pwa.js, no analytics) che ospiterà l'iframe del canale Vocea, conforme alle 6 regole
anonimato StarGateWB: Referrer-Policy no-referrer (meta + iframe), CSP frame-src
app.vocea.cloud, slug del canale da ?canale=<slug> (nessun id del segnalante nell'URL),
postMessage con check event.origin + envelope {source:'vocea'} e NESSUNA persistenza
del recovery code (solo autosize). Dormiente finché non c'è lo slug/MS live.
+ docs/OUTGOING_TO_VOCEA_...: conferma origin frame-ancestors https://nis2.agile.software.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1fe5b7ae61
commit
b787c327c1
@@ -0,0 +1,29 @@
|
||||
# OUTGOING → Vocea / StarGateWB — Anonimato embed: origin + conferma checklist
|
||||
|
||||
> **Da**: NIS2 Agile · **A**: Vocea/StarGateWB · **Data**: 2026-06-27
|
||||
> **Rif.**: vostra guida "anonimato del segnalante" del 27/6 → recepita in `docs/STARGATEWB_ANONYMITY_PLACEMENT.md`.
|
||||
|
||||
Grazie per le direttive. Confermiamo l'impostazione e vi diamo l'origin per la CSP.
|
||||
|
||||
## Origin da autorizzare in `frame-ancestors` (lato vostro, su `app.vocea.cloud`)
|
||||
- **`https://nis2.agile.software`** ← produzione, pagina pubblica del canale.
|
||||
- (eventuale, da confermare) `https://dimostrazione.agile.software` — solo se dimostreremo il canale in ambiente demo.
|
||||
|
||||
Dal nostro lato autorizziamo **`frame-src https://app.vocea.cloud`** sulla pagina che ospita il widget.
|
||||
|
||||
## Come rispettiamo le 6 regole
|
||||
1. **Pubblica, senza login**: il canale NON sta nella nostra app (post-login). Abbiamo predisposto una pagina **pubblica e pre-login** dedicata: `https://nis2.agile.software/segnala-anonimo.html?canale=<slug>` (nessun `checkAuth`, nessuna sidebar).
|
||||
2. **Nessun tracciamento dell'apertura**: la pagina è statica, senza script applicativi, senza audit/analytics; non registriamo alcun "passaggio".
|
||||
3. **Nessun identificativo nell'URL dell'iframe**: `…/it/segnala/<slug>?embed=1` (solo lo slug del canale, che NON identifica il segnalante; eventuale `&theme=dark`).
|
||||
4. **Origin + envelope verificati**: il listener `postMessage` controlla `event.origin === 'https://app.vocea.cloud'` e `data.source === 'vocea'`; gestiamo solo l'autosize, **non salviamo né inoltriamo** il codice di recupero.
|
||||
5. **Niente fughe**: `Referrer-Policy: no-referrer` (meta + `referrerpolicy` sull'iframe), zero tag analytics/telemetria di terze parti sulla pagina.
|
||||
6. **CSP allineata**: `frame-src https://app.vocea.cloud` sul nostro origin ↔ vi chiediamo di mettere `https://nis2.agile.software` in `frame-ancestors`.
|
||||
|
||||
## Stato e cosa ci serve da voi
|
||||
La pagina pubblica è **pronta (scheletro)**, in attesa di:
|
||||
- lo **slug del canale** per ciascuna organizzazione pilota (la pagina lo prende da `?canale=<slug>`);
|
||||
- il completamento del **deploy del MS** su `api.vocea.cloud` + l'**API key** del canale (per la parte server-to-server / dashboard interna).
|
||||
|
||||
Appena ci date origin-OK sulla `frame-ancestors` + uno slug di test, facciamo lo smoke end-to-end dell'embed.
|
||||
|
||||
— NIS2 Agile
|
||||
@@ -0,0 +1,80 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="it">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Segnala in anonimato</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<!-- ANONIMATO (StarGateWB/Vocea): niente referrer, niente analytics, niente login, niente tracciamento. -->
|
||||
<meta name="referrer" content="no-referrer">
|
||||
<meta http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self'; frame-src https://app.vocea.cloud; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; base-uri 'none'; form-action 'none'">
|
||||
<link rel="stylesheet" href="/vendor/bootstrap-italia/dist/css/bootstrap-italia.min.css">
|
||||
<link rel="stylesheet" href="/css/style.css?v=20260618">
|
||||
<style>
|
||||
body { background:#f5f7fa; margin:0; }
|
||||
.wb-wrap { max-width:860px; margin:0 auto; padding:28px 16px; }
|
||||
.wb-card { background:#fff; border-radius:14px; box-shadow:0 6px 24px rgba(0,0,0,.08); padding:26px; }
|
||||
.wb-frame { width:100%; height:760px; border:0; border-radius:10px; background:#fafbfc; }
|
||||
.wb-note { color:#5b6b7b; font-size:.94rem; line-height:1.55; }
|
||||
.wb-badge { display:inline-block; background:#e7f3ff; color:#0066CC; border-radius:999px; padding:3px 12px; font-size:.8rem; font-weight:600; }
|
||||
h1 { font-size:1.6rem; margin:12px 0 6px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- PAGINA PUBBLICA, PRE-LOGIN. Nessuno script di app (no common.js/api.js/pwa.js),
|
||||
nessuna sidebar, nessun checkAuth, nessuna analitica: l'accesso non è tracciato. -->
|
||||
<div class="wb-wrap">
|
||||
<div class="wb-card">
|
||||
<span class="wb-badge">Canale sicuro · cifratura zero-knowledge</span>
|
||||
<h1>Segnala in anonimato</h1>
|
||||
<p class="wb-note">
|
||||
Questo canale è cifrato end-to-end: il contenuto della segnalazione e la tua identità non sono
|
||||
visibili a nessuno, nemmeno a chi gestisce la piattaforma. <strong>Non è richiesto alcun accesso</strong>
|
||||
e il tuo passaggio non viene registrato. Al termine ti verrà mostrato un <strong>codice di recupero</strong>:
|
||||
conservalo per seguire lo stato della tua segnalazione (è l'unico modo, non è recuperabile).
|
||||
</p>
|
||||
<div id="wb-mount"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
'use strict';
|
||||
var VOCEA_ORIGIN = 'https://app.vocea.cloud';
|
||||
// Lo slug è l'ID del CANALE pubblico dell'organizzazione (NON un identificativo del segnalante),
|
||||
// passato come ?canale=<slug>. Validazione stretta.
|
||||
var qs = new URLSearchParams(location.search);
|
||||
var slug = (qs.get('canale') || '').trim().toLowerCase();
|
||||
var theme = qs.get('theme') === 'dark' ? '&theme=dark' : '';
|
||||
var mount = document.getElementById('wb-mount');
|
||||
|
||||
if (!/^[a-z0-9-]{2,64}$/.test(slug)) {
|
||||
mount.innerHTML = '<p class="wb-note">Canale non ancora configurato. Apri il link fornito dalla tua organizzazione '
|
||||
+ '(formato: <code>…/segnala-anonimo.html?canale=<nome-canale></code>).</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
var f = document.createElement('iframe');
|
||||
f.className = 'wb-frame';
|
||||
f.title = 'Canale di segnalazione anonima';
|
||||
f.setAttribute('referrerpolicy', 'no-referrer'); // nessun referrer verso Vocea
|
||||
f.setAttribute('allow', 'clipboard-write'); // per copiare il codice di recupero
|
||||
// Solo slug + embed: MAI identificativi (email/employee_id/token) nell'URL.
|
||||
f.src = VOCEA_ORIGIN + '/it/segnala/' + encodeURIComponent(slug) + '?embed=1' + theme;
|
||||
mount.appendChild(f);
|
||||
|
||||
// Messaggi dal widget: verifica ORIGIN + envelope {source:'vocea'}.
|
||||
// NON salviamo né inoltriamo nulla: il codice di recupero resta dentro l'iframe (by design).
|
||||
window.addEventListener('message', function (ev) {
|
||||
if (ev.origin !== VOCEA_ORIGIN) return; // 1) origin check
|
||||
var d = ev.data;
|
||||
if (!d || d.source !== 'vocea') return; // 2) envelope check
|
||||
// Gestiamo SOLO eventi non sensibili (autosize). Niente storage, niente analytics, niente forward.
|
||||
if (d.type === 'resize' && typeof d.height === 'number' && d.height > 200 && d.height < 4000) {
|
||||
f.style.height = d.height + 'px';
|
||||
}
|
||||
}, false);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user