Background
A payment-readiness audit (2026-05-20) discovered that 8 outbound Edge Functions called by browser code do not exist in supabase/functions/. Without them, clicking "Pay" on /payment-demo fails immediately with a 404 against a nonexistent function URL. No customer can complete a payment until this is done.
Discovered via:
grep -rohE "functions/v1/[a-z-]+" src/lib/payments src/components/payment
vs.
The TODO comment in src/lib/payments/stripe.ts:48 confirms: // (Edge Function will be created in Phase 5) — Phase 5 was never completed.
What's already shipped
The webhook (inbound) side is fully built and verified:
stripe-webhook — 425 LOC, signature verification, idempotency, payment_results writes
paypal-webhook — 317 LOC, same
send-payment-email — notification skeleton
These serve as the canonical patterns for the new functions (Deno serve, Stripe SDK via esm.sh, Supabase service client). New functions should mirror their structure.
The browser-side fetch sites are also shipped (3 in src/lib/payments/stripe.ts, 3 in src/lib/payments/paypal.ts, 2 in SubscriptionManager.tsx) — they expect specific request/response shapes documented at the call sites.
The 8 missing functions
| # |
Function |
Browser caller |
Purpose |
| 1 |
create-stripe-checkout |
src/lib/payments/stripe.ts:50 |
Create a Stripe Checkout Session for one-off charge |
| 2 |
verify-stripe-session |
src/lib/payments/stripe.ts:92 |
Verify Stripe session ID post-redirect |
| 3 |
create-stripe-subscription |
src/lib/payments/stripe.ts:135 |
Create Stripe subscription checkout |
| 4 |
create-paypal-order |
src/lib/payments/paypal.ts:74 |
Create PayPal order (one-off) |
| 5 |
capture-paypal-order |
src/lib/payments/paypal.ts:101 |
Capture approved PayPal order |
| 6 |
create-paypal-subscription |
src/lib/payments/paypal.ts:145 |
Create PayPal billing subscription |
| 7 |
cancel-subscription |
src/components/payment/SubscriptionManager/SubscriptionManager.tsx:87 |
Cancel subscription (Stripe or PayPal) |
| 8 |
resume-subscription |
src/components/payment/SubscriptionManager/SubscriptionManager.tsx:126 |
Resume paused subscription |
Sub-issues
Each sub-issue is a self-contained PR-sized chunk:
Total: ~20h focused implementation. Realistic 2–3 working days with reviews.
Implementation pattern (reference)
Each function follows the structure already established in supabase/functions/stripe-webhook/index.ts:
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
import Stripe from 'https://esm.sh/stripe@14.21.0?target=deno';
const stripe = new Stripe(Deno.env.get('STRIPE_SECRET_KEY') || '', {
apiVersion: '2024-06-20',
httpClient: Stripe.createFetchHttpClient(),
});
const supabase = createClient(
Deno.env.get('NEXT_PUBLIC_SUPABASE_URL')!,
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
);
serve(async (req) => {
// 1. CORS preflight (use _shared/cors.ts from #106)
// 2. Auth: verify caller's JWT, extract user_id (use _shared/auth.ts from #106)
// 3. Parse body
// 4. Load related DB row (e.g., payment_intents) with RLS check
// 5. Call Stripe/PayPal SDK with idempotency_key (from _shared/idempotency.ts in #106)
// 6. Write provider response to DB
// 7. Return response in expected shape
});
Each PR should:
- Add the function under
supabase/functions/<name>/index.ts
- Add Deno unit tests under
supabase/functions/<name>/index.test.ts
- Un-skip the matching E2E tests in
tests/e2e/payment/ (only those that exercise the newly-shipped function)
- Update
docs/PAYMENT-DEPLOYMENT.md if the deployment story for the function differs from the pattern
Recommended order: ship #106 (shared infra) FIRST, then #101 (Stripe one-off — the MVP critical path), then the others in any order.
Acceptance
Phase 0 (this epic) is complete when:
- All 8 functions exist under
supabase/functions/<name>/index.ts
- Each has Deno unit tests + at least one E2E test un-skipped that exercises it
tests/e2e/payment/01-stripe-onetime.spec.ts:3 ('should complete one-time payment successfully') passes against Stripe sandbox
docs/PAYMENT-DEPLOYMENT.md Step 4.2 is no longer marked "NOT YET SHIPPED"
- The "Status of the integration" table at the top of that doc shows Outbound Edge Functions as ✅ shipped
Related
🤖 Created from audit on 2026-05-20
Background
A payment-readiness audit (2026-05-20) discovered that 8 outbound Edge Functions called by browser code do not exist in
supabase/functions/. Without them, clicking "Pay" on/payment-demofails immediately with a 404 against a nonexistent function URL. No customer can complete a payment until this is done.Discovered via:
grep -rohE "functions/v1/[a-z-]+" src/lib/payments src/components/paymentvs.
The TODO comment in
src/lib/payments/stripe.ts:48confirms:// (Edge Function will be created in Phase 5)— Phase 5 was never completed.What's already shipped
The webhook (inbound) side is fully built and verified:
stripe-webhook— 425 LOC, signature verification, idempotency, payment_results writespaypal-webhook— 317 LOC, samesend-payment-email— notification skeletonThese serve as the canonical patterns for the new functions (Deno serve, Stripe SDK via esm.sh, Supabase service client). New functions should mirror their structure.
The browser-side fetch sites are also shipped (3 in
src/lib/payments/stripe.ts, 3 insrc/lib/payments/paypal.ts, 2 inSubscriptionManager.tsx) — they expect specific request/response shapes documented at the call sites.The 8 missing functions
create-stripe-checkoutsrc/lib/payments/stripe.ts:50verify-stripe-sessionsrc/lib/payments/stripe.ts:92create-stripe-subscriptionsrc/lib/payments/stripe.ts:135create-paypal-ordersrc/lib/payments/paypal.ts:74capture-paypal-ordersrc/lib/payments/paypal.ts:101create-paypal-subscriptionsrc/lib/payments/paypal.ts:145cancel-subscriptionsrc/components/payment/SubscriptionManager/SubscriptionManager.tsx:87resume-subscriptionsrc/components/payment/SubscriptionManager/SubscriptionManager.tsx:126Sub-issues
Each sub-issue is a self-contained PR-sized chunk:
create-stripe-checkout+verify-stripe-session+ testscreate-stripe-subscription+ testscreate-paypal-order+capture-paypal-order+ testscreate-paypal-subscription+ testscancel-subscription+resume-subscription+ tests_shared/cors.ts,_shared/auth.ts,_shared/idempotency.ts, deploy, un-skipTotal: ~20h focused implementation. Realistic 2–3 working days with reviews.
Implementation pattern (reference)
Each function follows the structure already established in
supabase/functions/stripe-webhook/index.ts:Each PR should:
supabase/functions/<name>/index.tssupabase/functions/<name>/index.test.tstests/e2e/payment/(only those that exercise the newly-shipped function)docs/PAYMENT-DEPLOYMENT.mdif the deployment story for the function differs from the patternRecommended order: ship #106 (shared infra) FIRST, then #101 (Stripe one-off — the MVP critical path), then the others in any order.
Acceptance
Phase 0 (this epic) is complete when:
supabase/functions/<name>/index.tstests/e2e/payment/01-stripe-onetime.spec.ts:3('should complete one-time payment successfully') passes against Stripe sandboxdocs/PAYMENT-DEPLOYMENT.mdStep 4.2 is no longer marked "NOT YET SHIPPED"Related
🤖 Created from audit on 2026-05-20