From 67f3fd311f0d545849b355304bd3028eb3aae5c8 Mon Sep 17 00:00:00 2001 From: Greg Kilmer Date: Sat, 11 Jul 2026 18:31:58 -0400 Subject: [PATCH] Turnstile and OTS update --- astro.config.mjs | 10 ++++++++++ src/components/professional/ContactForm.tsx | 12 +----------- src/middleware.ts | 14 ++++++-------- src/pages/api/contact.ts | 12 +----------- 4 files changed, 18 insertions(+), 30 deletions(-) diff --git a/astro.config.mjs b/astro.config.mjs index bcdfcce..64a54b2 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -52,6 +52,16 @@ export default defineConfig({ vite: { plugins: [tailwindcss()], + build: { + // Never inline assets as data URIs. The default (4096 bytes) causes Vite + // to inline the smallest font subsets (e.g. cyrillic-ext woff2) as + // data:font/woff2 base64, which (a) requires data: in font-src and (b) + // triggers Chromium "OTS parsing error: Size of decompressed WOFF 2.0 is + // less than compressed size" warnings on those inlined subsets. Forcing + // every asset to a real file keeps font-src tight at 'self' and avoids + // the OTS parse errors. + assetsInlineLimit: 0, + }, }, server: { diff --git a/src/components/professional/ContactForm.tsx b/src/components/professional/ContactForm.tsx index c4bb5f2..edf3cbc 100644 --- a/src/components/professional/ContactForm.tsx +++ b/src/components/professional/ContactForm.tsx @@ -131,18 +131,8 @@ export default function ContactForm({ turnstileSiteKey }: Props) { // widget rapidly flashing. Instead we leave the widget in its errored // state; the next form submission will reset it for a fresh attempt. // The error surfaces as the token being empty, which onSubmit reports. - 'error-callback': (error: unknown) => { + 'error-callback': () => { turnstileTokenRef.current = ''; - // TEMPORARY DIAGNOSTIC: Turnstile passes an error code/string when the - // widget fails its challenge (e.g. "110200-domain-not-authorized", - // "300030-..."). The 400 on challenges.cloudflare.com/cdn-cgi/ - // challenge-platform/... originates here. Log it so the browser - // console shows the exact reason. Remove once resolved. - console.warn('[contact] turnstile widget error:', error, { - sitekey: turnstileSiteKey, - origin: location.origin, - hostname: location.hostname, - }); }, theme: 'dark', }, diff --git a/src/middleware.ts b/src/middleware.ts index 8cdbd46..4774c13 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -31,10 +31,9 @@ * need the origin. (SRI is intentionally NOT applied to the Turnstile * loader — see ContactForm.tsx for why.) * - * Fonts: Fontsource variable fonts (woff2) are self-hosted, but Vite inlines - * font subsets below build.assetsInlineLimit (default 4096 bytes) as - * data:font/woff2 base64 URIs. At least two small cyrillic-ext subsets fall - * under that threshold, so font-src MUST include data: or they are blocked. + * Fonts: Fontsource variable fonts (woff2) are self-hosted and emitted as + * real files (Vite's assetsInlineLimit is set to 0 in astro.config.mjs so no + * subset is inlined as a data URI), so font-src can stay 'self'. * * Images: board-game covers are self-hosted (fetched at build time by * scripts/fetch-bgg-covers.mjs) and the hero portrait is local, but TCG deck @@ -67,10 +66,9 @@ const CONTENT_SECURITY_POLICY = [ // storage.googleapis.com origin serves TCG deck featured-card art hotlinked // from Archidekt's card-image bucket (see src/lib/archidekt.ts). "img-src 'self' data: https://storage.googleapis.com", - // Self-hosted variable fonts (woff2) via @fontsource-variable. data: is - // required because Vite inlines font subsets under assetsInlineLimit as - // data:font/woff2 base64 URIs. - "font-src 'self' data:", + // Self-hosted variable fonts (woff2) via @fontsource-variable, emitted as + // real files (assetsInlineLimit: 0 — see astro.config.mjs). + "font-src 'self'", // Same-origin fetch/XHR (the contact form POSTs to /api/contact) plus the // Turnstile siteverify calls the widget makes from the browser. "connect-src 'self' https://challenges.cloudflare.com", diff --git a/src/pages/api/contact.ts b/src/pages/api/contact.ts index 283c792..5251c6b 100644 --- a/src/pages/api/contact.ts +++ b/src/pages/api/contact.ts @@ -94,17 +94,7 @@ async function verifyTurnstile(token: string | undefined, ip: string): Promise