VibeRaven
How do I check the Stripe webhooks, env vars and Supabase policies in an app Claude Code wrote?
Check each one against the running system, not only the code. For Stripe, confirm the webhook handler verifies the signature over the raw request body with the endpoint's own signing secret, and that a live mode endpoint exists. For env vars, compare every variable the code reads with what each Vercel environment sets, and redeploy after changes. For Supabase, confirm RLS is on for every public table and test the policies as anon and authenticated, not with the secret key, which bypasses them.
Why this matters
An app can pass in Stripe test mode and in your own signed-in session and still fail in production: a webhook handler that parses JSON before verifying the signature, a NEXT_PUBLIC_ variable baked into the build with a preview value, or a policy that was only ever exercised with a key that skips RLS.
Check the three areas
- Stripe: the handler calls constructEvent, or your library's equivalent, with the raw request body, the Stripe-Signature header and the endpoint's whsec_ signing secret. Any change to the raw body, such as parsing it as JSON first, makes verification fail.
- Stripe: the secret matches the endpoint. The Stripe CLI and each dashboard endpoint have different secrets, so the secret printed by stripe listen does not verify events sent to a deployed endpoint.
- Stripe: the handler returns a 2xx quickly and does slow work afterwards, and it handles duplicate events and events out of order. Stripe does not guarantee order and may deliver an event more than once.
- Stripe: a live mode endpoint is registered, and the code does not depend on test mode objects, which are not usable in live mode.
- Env vars: list every variable the code reads and set each one in the Vercel environments that need it: Production, Preview and Development. Changes apply only to new deployments, so redeploy after changing one.
- Env vars: in Next.js, a variable prefixed NEXT_PUBLIC_ is inlined into the browser bundle at build time, so it is public and fixed until the next build. Never give a secret that prefix.
- Env vars: keep secret keys (the Stripe secret key, the Supabase secret or service_role key) in server code only, and out of source control.
- Supabase: every table in the public schema has RLS enabled, and the Security Advisor on the live project shows no "Table publicly accessible" errors.
- Supabase: each policy scopes rows to the user, for example using ((select auth.uid()) = user_id), and update policies check the new row too (`with check`, or `using` when there is none), so a user cannot reassign a row to someone else.
- Supabase: test as the roles your users have. Supabase's guide uses pgTAP tests that set the role to anon and authenticated and assert allow and deny for each operation, run with supabase test db. A secret key bypasses RLS when the request carries no user access token, so a query made with it proves nothing about your policies.
Optional repo check
For AI-built Vercel + Supabase apps, `npx -y viberaven@1.5.3 check` reads the code side of all three: Stripe webhook handlers with no `constructEvent` call, no `stripe-signature` header or no raw body read, env vars the code reads that `.env.example` does not list (it cannot see Vercel settings), and Supabase migrations that leave a public table without row level security or use a bare `true` policy. It is advice, not a gate, and a repository check, not a live database test: it does not call Stripe, Vercel or Supabase, so endpoint registration, signing secrets, env values and how policies behave for real users stay with the checks above. It exits with code 1 when it finds a blocker and writes a `.viberaven` folder that it does not add to `.gitignore`.
Sources
Why does Stripe signature verification pass locally and fail on Vercel?
Stripe's troubleshooting guide starts with the endpoint secret: the secret printed by stripe listen belongs to the CLI, and each dashboard endpoint has its own whsec_ secret. The other cause is the body. Any framework step that parses or changes the raw body makes verification fail.
Can I test my RLS policies with the service role key?
No. The secret key, and the legacy service_role key, bypass RLS when the request carries no user access token, so a query made with one succeeds whatever your policies say. Test with the publishable key and a signed-in user's session, or with pgTAP tests that set the role.