/*
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin
  Permissions-Policy: geolocation=(), microphone=(self), camera=(self), payment=()
  # HSTS: mancava in produzione (verificato dal vivo su brigata.app). Senza, alla PRIMA visita un
  # attaccante di rete può tentare l'SSL-strip e servire la pagina in HTTP. 180 giorni.
  # NB volutamente SENZA includeSubDomains/preload: l'hub on-premise può servire su un sottodominio
  # (hub-*.local.brigata.app) o in HTTP sulla LAN, e un impegno esteso ai sottodomini lo romperebbe.
  # Sull'HTTP del box l'header è comunque ignorato dai browser (HSTS vale solo su HTTPS).
  Strict-Transport-Security: max-age=15552000
  # Dove il browser spedisce le violazioni della CSP. Finora la policy era severa ma CIECA: nessuno
  # sapeva se in campo veniva violata — né da un tentativo di injection, né da una nostra pagina
  # rotta sotto la policy. L'endpoint aggrega e non conserva query string (vedi /api/csp-report).
  #
  # Questo header sta SOLO qui, sulla regola generale: i blocchi più specifici staccano con `!`
  # soltanto gli header che nominano (Content-Security-Policy, X-Frame-Options), quindi
  # Reporting-Endpoints lo ereditano tutti. Le DIRETTIVE invece vanno ripetute su OGNI CSP, perché
  # una policy che sostituisce quella di /* si porta dietro solo ciò che ha scritto dentro: a una
  # CSP a cui si dimentica `report-to` il browser non segnala niente, in silenzio.
  #
  # Si dichiarano ENTRAMBE le forme e non è ridondanza: `report-to` è quella attuale, `report-uri`
  # è deprecata ma resta l'unica che Safari manda davvero. Con solo la prima si perderebbe tutto
  # il traffico iOS — cioè, per un gestionale da ristorazione, buona parte delle sale.
  #
  # 'wasm-unsafe-eval' — serve a pdf.js, che dalla versione 5 decodifica JPEG2000, JBIG2 e i
  # profili ICC in WebAssembly (lettura OCR di fatture e menu, vedi `apriPdf` in src/main.jsx).
  # Con `script-src 'self'` e basta il browser BLOCCA il wasm, e le fatture scansionate non si
  # aprirebbero piu'. Il nome spaventa ma il permesso e' stretto: consente di compilare
  # WebAssembly e NIENT'ALTRO — non `eval()`, non gli script inline, che restano vietati. E' la
  # forma granulare pensata apposta per non dover concedere 'unsafe-eval', che invece aprirebbe
  # entrambi. Lo stesso permesso e' gia' concesso alle rotte mappa piu' sotto, per MapKit.
  Reporting-Endpoints: csp="https://brigata.app/api/csp-report"
  Content-Security-Policy: default-src 'self'; script-src 'self' 'wasm-unsafe-eval' https://challenges.cloudflare.com; script-src-attr 'none'; object-src 'none'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src 'self' data: blob: https:; connect-src 'self' wss: https://challenges.cloudflare.com; frame-src https://challenges.cloudflare.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; report-to csp; report-uri /api/csp-report

# /app è l'ENTRY DEDICATA del guscio nativo Android (webview Capacitor con server.url remoto):
# il guscio inietta il bridge nativo come <script> inline nella pagina, quindi SOLO qui la CSP
# concede 'unsafe-inline' a script-src. Il resto del sito resta blindato (regola /* sopra).
# `! Content-Security-Policy` stacca l'header ereditato da /* per evitare il doppio header
# (due CSP si sommano in AND → vincerebbe la più severa e il bridge resterebbe bloccato).
#
# `unsafe-inline` qui NON si può togliere: il bridge lo inietta il guscio nativo, quindi non
# possiamo né conoscerne l'hash né aggiungergli un nonce (l'attributo lo scriverebbe Capacitor,
# non noi). Sparirà quando l'app passerà al bundle locale invece di server.url remoto.
# Nel frattempo si toglie il vettore che contava davvero: `script-src-attr 'none'` blocca gli
# HANDLER INLINE negli attributi — `<svg onload=…>`, `<img onerror=…>`, cioè la forma che prende
# quasi sempre un'iniezione HTML — continuando a permettere il <script> del bridge. I due
# permessi sembrano uno solo ma non lo sono, ed è la differenza che serve.
#
# 'wasm-unsafe-eval' anche qui, per lo stesso motivo di /*: dentro il guscio Android si aprono
# le stesse fatture PDF, e senza il permesso pdf.js non riesce a decodificarle. Sull'app sarebbe
# pure piu' difficile da diagnosticare, perche' l'errore CSP non si vede in una webview.
/app
  ! Content-Security-Policy
  Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval' https://challenges.cloudflare.com; script-src-attr 'none'; object-src 'none'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src 'self' data: blob: https:; connect-src 'self' wss: https://challenges.cloudflare.com; frame-src https://challenges.cloudflare.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; report-to csp; report-uri /api/csp-report

# /turnstile.html è il PONTE per il guscio iOS: l'unica pagina del sito che si può inquadrare.
# Il guscio bundled iOS sta su `capacitor://localhost`, un origin OPACO (window.origin === "null")
# dove Turnstile non riesce a chiudere il dialogo postMessage col proprio iframe e muore con
# l'errore 600010 → login impossibile. La pagina viene quindi caricata in un iframe dall'app, gira
# qui su `https://brigata.app` dove Turnstile funziona, e restituisce il token via postMessage.
#
# Serve staccare la CSP ereditata da /* per due motivi, entrambi obbligatori:
#  · `frame-ancestors 'none'` impedirebbe l'inquadramento e sarebbe l'unica cosa che conta qui;
#  · un origin opaco NON è esprimibile in frame-ancestors, quindi non si può nemmeno restringere
#    all'app: o si permette a tutti, o non funziona.
# Permetterlo a tutti non regala nulla: la sitekey è pubblica e chiunque può montare un widget da
# sé; il token che esce di qui è monouso, legato alla sitekey e verificato dal server con
# Cloudflare. Chi inquadrasse questa pagina otterrebbe solo un captcha da risolvere.
# `frame-ancestors` è l'UNICA invariante che questa pagina rilassa: tutto il resto resta come
# altrove, compreso NIENTE 'unsafe-inline' su script-src (la logica sta in /turnstile.js, esterno
# apposta — l'unica rotta che può avere script inline resta /app, per il bridge nativo).
#
# DUE TRAPPOLE, entrambe verificate dal vivo il 28/07/2026 su un deploy che sembrava riuscito:
#  1. La regola si scrive `/turnstile`, SENZA `.html`. Pages canonicalizza le pagine .html: una
#     richiesta a /turnstile.html risponde 308 verso /turnstile, e una regola scritta col suffisso
#     si applica soltanto a quella redirezione — la pagina vera continua a ricevere la CSP di /*.
#     Il sintomo è beffardo: l'header giusto SI VEDE, ma sulla risposta sbagliata.
#  2. Qui NON si dichiara affatto `frame-ancestors`, e non è una svista. Il primo tentativo usava
#     `frame-ancestors *`, ma `*` non è garantito che corrisponda a un origin OPACO — ed è
#     esattamente quello che ha il guscio iOS (`capacitor://localhost` → window.origin "null").
#     Omettere del tutto la direttiva è l'unica forma che non lascia dubbi.
#  3. Servono DUE blocchi, perché Pages onora un solo `!` per blocco e qui vanno staccati DUE
#     header ereditati da /*: la CSP (che vieta l'inquadramento con frame-ancestors) e
#     X-Frame-Options (che lo vieta di suo). I due blocchi devono avere pattern DIVERSI: con lo
#     stesso identico percorso il secondo sovrascrive il primo e uno dei due `!` si perde in
#     silenzio — verificato in produzione il 28/07, la CSP passava e l'XFO restava DENY.
#     Da qui `/turnstile*` per l'uno e `/turnstile` per l'altro: entrambi agganciano la pagina
#     (e lo splat prende anche /turnstile.js, che di XFO non ha bisogno).
#     La regola generale resta INTATTA — XFO e frame-ancestors 'none' su tutto il sito, come
#     prima: l'eccezione vive qui, su una pagina senza sessione, senza dati e senza azioni.
/turnstile*
  ! X-Frame-Options
/turnstile
  ! Content-Security-Policy
  Content-Security-Policy: default-src 'self'; script-src 'self' https://challenges.cloudflare.com; script-src-attr 'none'; object-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' https://challenges.cloudflare.com; frame-src https://challenges.cloudflare.com; base-uri 'self'; form-action 'self'; report-to csp; report-uri /api/csp-report

# ── Console di risposta all'incidente ────────────────────────────────────────
# Pagina di piattaforma (sessione admin + 2FA), non parte dell'app dei clienti. CSP più stretta
# della generale: niente Turnstile, niente font remoti, niente immagini esterne — non le servono, e
# ogni origine concessa a una console che congela ristoranti è una superficie in più.
#
# La regola si scrive `/admin`, SENZA `.html`: Pages canonicalizza le pagine .html e risponde 308
# da /admin.html verso /admin, quindi una regola col suffisso si applicherebbe solo al redirect e
# la pagina vera resterebbe sotto la policy generale. È lo stesso inciampo già documentato per
# /turnstile, e si sbaglia una volta sola.
#
# Un solo `!` per blocco (verificato in produzione): qui stacca la CSP. X-Robots-Tag è un header
# NUOVO, non ereditato, quindi non va staccato e può stare nello stesso blocco.
/admin
  ! Content-Security-Policy
  Content-Security-Policy: default-src 'self'; script-src 'self'; script-src-attr 'none'; object-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; report-to csp; report-uri /api/csp-report
  X-Robots-Tag: noindex, nofollow, noarchive

# ── Rotte con la MAPPA (Ondata 3) ────────────────────────────────────────────
# MapKit JS non gira sotto la policy generale: gli servono il CDN di Apple, 'wasm-unsafe-eval'
# (il rendering della mappa è WebAssembly), i worker e i blob. Invece di allentare la CSP di
# tutto il sito si apre SOLO dove la mappa serve davvero — stessa tecnica già in produzione per
# /app, con `! Content-Security-Policy` che stacca l'header ereditato da /* (due CSP si sommano
# in AND: senza staccarla vincerebbe la più severa e la mappa resterebbe nera).
#
# `Permissions-Policy: geolocation=()` sulla regola generale spegne la geolocalizzazione su
# TUTTO il sito: senza l'override qui sotto l'app del fattorino non otterrebbe mai una posizione.
# È il motivo per cui /fattorino/* ha un blocco tutto suo.
/ordine/*
  ! Content-Security-Policy
  Content-Security-Policy: default-src 'self'; script-src 'self' 'wasm-unsafe-eval' https://cdn.apple-mapkit.com https://*.apple-mapkit.com; script-src-attr 'none'; object-src 'none'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src 'self' data: blob: https:; connect-src 'self' wss: https://*.apple-mapkit.com https://*.ls.apple.com blob:; worker-src 'self' https://*.apple-mapkit.com blob:; frame-src https://*.apple-mapkit.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; report-to csp; report-uri /api/csp-report

# App del fattorino: come sopra, PIÙ la geolocalizzazione (è tutto il suo mestiere).
# Fotocamera concessa per la prova di consegna; microfono e pagamenti restano chiusi.
/fattorino/*
  ! Content-Security-Policy
  Content-Security-Policy: default-src 'self'; script-src 'self' 'wasm-unsafe-eval' https://cdn.apple-mapkit.com https://*.apple-mapkit.com; script-src-attr 'none'; object-src 'none'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src 'self' data: blob: https:; connect-src 'self' wss: https://*.apple-mapkit.com https://*.ls.apple.com blob:; worker-src 'self' https://*.apple-mapkit.com blob:; frame-src https://*.apple-mapkit.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; report-to csp; report-uri /api/csp-report

# Permissions-Policy in un BLOCCO A PARTE, e non insieme alla CSP qui sopra: verificato in
# produzione che Pages onora UN SOLO `!` per blocco di regola — con due `!` il primo (la CSP)
# passava e il secondo veniva ignorato, lasciando `geolocation=()` ereditato da /*. Risultato:
# la CSP giusta ma il GPS spento, cioè l'app del fattorino che non funziona senza dire perché.
# Una regola, un header da staccare.
/fattorino/*
  ! Permissions-Policy
  Permissions-Policy: geolocation=(self), microphone=(), camera=(self), payment=()

# Console consegne dello staff: mappa sì, geolocalizzazione no (chi smista sta al banco).
/consegne
  ! Content-Security-Policy
  Content-Security-Policy: default-src 'self'; script-src 'self' 'wasm-unsafe-eval' https://cdn.apple-mapkit.com https://*.apple-mapkit.com; script-src-attr 'none'; object-src 'none'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src 'self' data: blob: https:; connect-src 'self' wss: https://*.apple-mapkit.com https://*.ls.apple.com blob:; worker-src 'self' https://*.apple-mapkit.com blob:; frame-src https://*.apple-mapkit.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; report-to csp; report-uri /api/csp-report
