Sample Launch Risk Receipt
A realistic example of the one-page launch risk report RepoRisk would generate for an AI-built SaaS before live payments, private data and founder reputation are on the line.
Receipt ID
RR-SAMPLE-7249
Status
Payment risk
High
Data access
High
Test coverage
Medium
High risk findings
Stripe webhook signature verification missing
app/api/webhooks/stripe/route.ts
Why it matters: Fake or replayed webhook events may update subscription status without a real Stripe event.
Fix: Use raw request body and verify the Stripe-Signature header with the endpoint secret before mutating payment state.
Supabase RLS policy not detected on customer tables
supabase/migrations/2026_create_tables.sql
Why it matters: Authenticated users may be able to read or write records that belong to another workspace.
Fix: Enable RLS on user-owned tables and add owner or organization scoped policies for select, insert and update.
Admin API route lacks server-side role check
app/api/admin/users/route.ts
Why it matters: Hiding admin controls in the UI is not authorization. Direct API calls can still reach the route.
Fix: Validate the server session and role inside the route handler before returning or mutating admin data.
Medium risk findings
Checkout success page trusted as payment confirmation
app/checkout/success/page.tsx
Fix: Treat the success page as informational and rely on verified webhooks for subscription activation.
Subscription provider ID lacks unique constraint
prisma/schema.prisma
Fix: Add unique constraints for stripeCustomerId and stripeSubscriptionId.
Broad any usage around billing payloads
lib/billing/stripe-events.ts
Fix: Use typed Stripe event narrowing before reading nested metadata.
Empty catch block hides failed writes
app/api/projects/route.ts
Fix: Log structured errors and return a safe failure response instead of silently continuing.
Missing idempotency guard for repeated provider events
lib/billing/sync-subscription.ts
Fix: Store provider event IDs or use subscription IDs to avoid duplicate billing state changes.
Account billing panel hides failed payment state
app/account/billing/page.tsx
Fix: Show failed, incomplete and past_due states instead of only active or canceled subscriptions.
Low risk findings
Recommended fix order
- 1Block unverified Stripe webhooks before any payment state writes.
- 2Enable Supabase RLS and add owner-scoped policies.
- 3Enforce server-side admin role checks on all admin API routes.
- 4Add unique billing provider constraints in the database schema.
- 5Add regression tests for checkout, webhook, auth and admin paths.
Cursor / Claude Code repair prompts
Update app/api/webhooks/stripe/route.ts so the handler reads the raw body, verifies Stripe-Signature with STRIPE_WEBHOOK_SECRET, rejects invalid signatures, and only then updates subscription state. Add a test or fixture that proves unsigned webhook payloads are rejected.
Inspect supabase/migrations/2026_create_tables.sql and add RLS for user-owned tables. Create owner-scoped select, insert and update policies using auth.uid() or organization membership. Include a short migration note explaining which tables are protected.
Review app/api/admin/users/route.ts and add server-side session validation. Require an admin role before returning data or mutating users. Do not rely on hidden UI state. Return 401 for missing sessions and 403 for non-admin users.
Launch recommendation
Do not launch paid users before fixing these 3 issues. Then add focused regression coverage for checkout, webhook, admin and database write paths and re-run the receipt after changes.