From 43bacd2f7095a4719c0c65797434028eae53e16c Mon Sep 17 00:00:00 2001 From: Pamela Chia Date: Wed, 27 May 2026 15:36:24 +0800 Subject: [PATCH] fix(www): use service role key for LWX edge function storage uploads (#46411) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary The three LWX edge functions consume `MISC_USE_ANON_KEY` while their inline comments claim "SERVICE ROLE KEY": a copy-paste bug. This PR swaps them to `MISC_USE_SERVICE_ROLE_KEY`, matching `lw11-og` (the reference implementation that already uses the service role pattern correctly). The secret is already configured on the project. Service role bypasses RLS, so uploads succeed regardless of bucket policy and the key is never exposed (edge functions are server-side). ## Changes - `lwx-ticket/handler.tsx`: swap storage client to use `MISC_USE_SERVICE_ROLE_KEY` - `lwx-og/handler.tsx`: swap storage client to use `MISC_USE_SERVICE_ROLE_KEY` - `lwx-ticket-og/handler.tsx`: swap storage client to use `MISC_USE_SERVICE_ROLE_KEY` ## Testing (Vercel preview) 1. Hit an LWX ticket share URL with a Twitterbot UA: `curl -A 'Twitterbot/1.0' '/launch-week/x/tickets/'` — expect HTML with OG meta tags, no edge function error. 2. Confirm the storage object got upserted at `images/lwx/og//.png` on `obuldanrptloktxcffvn`. 3. Confirm `MISC_USE_SERVICE_ROLE_KEY` is set as an edge function secret on the project (it already powers `lw11-og`, so it should be). ### Follow-up (separate, manual) After merge and deploy, the storage policy on the `images` bucket needs tightening via the dashboard (no migration setup exists for this project): revoke `INSERT`/`UPDATE`/`DELETE` policies that grant `anon`, keep `SELECT` public. All legitimate writers (dashboard team uploads, LWX/LW11 edge functions) use service role and will continue to work. ## Linear - fixes GROWTH-882 ## Summary by CodeRabbit * **Chores** * Updated backend authentication configuration for image generation and ticket-related operations. [![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46411?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) --- apps/www/supabase/functions/lwx-og/handler.tsx | 4 ++-- apps/www/supabase/functions/lwx-ticket-og/handler.tsx | 4 ++-- apps/www/supabase/functions/lwx-ticket/handler.tsx | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/www/supabase/functions/lwx-og/handler.tsx b/apps/www/supabase/functions/lwx-og/handler.tsx index bd34330ff3e..381ab318d82 100644 --- a/apps/www/supabase/functions/lwx-og/handler.tsx +++ b/apps/www/supabase/functions/lwx-og/handler.tsx @@ -1,5 +1,5 @@ -import React from 'https://esm.sh/react@18.2.0?deno-std=0.140.0' import { ImageResponse } from 'https://deno.land/x/og_edge@0.0.4/mod.ts' +import React from 'https://esm.sh/react@18.2.0?deno-std=0.140.0' import { createClient } from 'jsr:@supabase/supabase-js@2' const corsHeaders = { @@ -53,7 +53,7 @@ export async function handler(req: Request) { // Supabase API URL - env var exported by default when deployed. Deno.env.get('MISC_USE_URL') ?? '', // Supabase API SERVICE ROLE KEY - env var exported by default when deployed. - Deno.env.get('MISC_USE_ANON_KEY') ?? '' + Deno.env.get('MISC_USE_SERVICE_ROLE_KEY') ?? '' ) // Track social shares diff --git a/apps/www/supabase/functions/lwx-ticket-og/handler.tsx b/apps/www/supabase/functions/lwx-ticket-og/handler.tsx index 3dbfce0e051..7681eaaf835 100644 --- a/apps/www/supabase/functions/lwx-ticket-og/handler.tsx +++ b/apps/www/supabase/functions/lwx-ticket-og/handler.tsx @@ -1,5 +1,5 @@ -import React from 'https://esm.sh/react@18.2.0?deno-std=0.140.0' import { ImageResponse } from 'https://deno.land/x/og_edge@0.0.4/mod.ts' +import React from 'https://esm.sh/react@18.2.0?deno-std=0.140.0' import { createClient } from 'jsr:@supabase/supabase-js@2' const corsHeaders = { @@ -77,7 +77,7 @@ export async function handler(req: Request) { // Supabase API URL - env var exported by default when deployed. Deno.env.get('MISC_USE_URL') ?? '', // Supabase API SERVICE ROLE KEY - env var exported by default when deployed. - Deno.env.get('MISC_USE_ANON_KEY') ?? '' + Deno.env.get('MISC_USE_SERVICE_ROLE_KEY') ?? '' ) // return geneartedOGImage diff --git a/apps/www/supabase/functions/lwx-ticket/handler.tsx b/apps/www/supabase/functions/lwx-ticket/handler.tsx index 004c4967d47..dc8ca4977f7 100644 --- a/apps/www/supabase/functions/lwx-ticket/handler.tsx +++ b/apps/www/supabase/functions/lwx-ticket/handler.tsx @@ -1,5 +1,5 @@ -import React from 'https://esm.sh/react@18.2.0?deno-std=0.140.0' import { ImageResponse } from 'https://deno.land/x/og_edge@0.0.4/mod.ts' +import React from 'https://esm.sh/react@18.2.0?deno-std=0.140.0' import { createClient } from 'jsr:@supabase/supabase-js@2' const corsHeaders = { @@ -49,7 +49,7 @@ export async function handler(req: Request) { // Supabase API URL - env var exported by default when deployed. Deno.env.get('MISC_USE_URL') ?? '', // Supabase API SERVICE ROLE KEY - env var exported by default when deployed. - Deno.env.get('MISC_USE_ANON_KEY') ?? '' + Deno.env.get('MISC_USE_SERVICE_ROLE_KEY') ?? '' ) // Track social shares