Files
nis2-agile/public/segnala-anonimo.html
DevEnv nis2-agileandClaude Opus 4.8 a71d1a096d [FIX] V3 polish: spotlight ARIA su top-nav + CSP font segnala-anonimo
- aria-guide "Mostrami dov'è": ora aggancia le voci del menu IN ALTO V3
  (data-nav aggiunto in topnav-v3.js su voci dirette + mega-link). Se la voce è
  in un mega-menu, lo apre (.aria-guide-open) e ci punta lo spotlight; coach
  "menu in alto". Fallback navigazione invariato. (Prima cercava .sidebar-nav V2.)
- segnala-anonimo.html: CSP font-src 'self' → 'self' data: (sbloccato il font
  data: embeddato, niente più violazione CSP).
- Cache-buster: topnav-v3.js/common.js ?v=20260627t, aria-guide.js ?v=20260627t.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 17:57:21 +02:00

81 lines
4.5 KiB
HTML

<!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' data:; 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=&lt;nome-canale&gt;</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>