From cadf88683e44b4bb9564571b66a78d8d696b1ce9 Mon Sep 17 00:00:00 2001 From: tommaso Date: Fri, 10 Jul 2026 14:41:28 +0200 Subject: [PATCH] fix(proxy): prevent caching of the withdrawal form The App Proxy HTML response carried no cache headers. Two consequences: - Browsers could serve a stale copy of /apps/recesso from cache, so theme changes made by the merchant were not reflected for the customer. - The page renders the order name, the customer email and the free-text withdrawal declaration. That content must not be stored by the browser or by any intermediate proxy. Send no-store (plus Pragma for HTTP/1.0 caches) and Referrer-Policy on every response produced by htmlResponse. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Mv83a29B4eFv5ixoj6PoE1 --- app/app/lib/recesso.server.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/app/app/lib/recesso.server.ts b/app/app/lib/recesso.server.ts index eb76673..0cebd5b 100644 --- a/app/app/lib/recesso.server.ts +++ b/app/app/lib/recesso.server.ts @@ -634,10 +634,22 @@ export async function lookupOrder( } -/** Helper: Response HTML standalone (status 200 di default per non leakare via status). */ +/** + * Response HTML standalone (status 200 di default per non leakare via status). + * + * `no-store`: la pagina contiene numero d'ordine, email e dichiarazione del + * consumatore. Non deve finire nella cache del browser (ne' in quella di un + * proxy intermedio), sia per privacy sia perche' altrimenti il cliente rivede + * una versione vecchia del form dopo un cambio di configurazione. + */ export function htmlResponse(html: string, status = 200): Response { return new Response(html, { status, - headers: { "Content-Type": "text/html; charset=utf-8" }, + headers: { + "Content-Type": "text/html; charset=utf-8", + "Cache-Control": "no-store, no-cache, must-revalidate", + Pragma: "no-cache", + "Referrer-Policy": "no-referrer", + }, }); }