Skip to content

Add payment-first Stripe membership and browser onboarding - #68

Merged
Maseeek merged 4 commits into
mainfrom
feat/stripe-billing-67
Oct 14, 2026
Merged

Maseeek merged 4 commits into
mainfrom
feat/stripe-billing-67

Conversation

@Maseeek

@Maseeek Maseeek commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

Issue

Refs #67. Deployment credentials and real Stripe payment testing remain activation steps.

Change

New Players now see one $15/month membership for both people and pay through Stripe before entering account or habit data. After Stripe confirms the payment, they sign up with the same verified email, create a Duel, and connect their membership. Existing Duel owners retain subscription management in Settings and /billing.

/welcome → public Stripe Checkout → paid receipt → verified account → Duel → atomic membership claim
signed Stripe webhook → canonical reconciliation → Duel subscription status

The browser membership section uses the confirmed live Do It Standard plan with a clear monthly price, one payment button, and no pre-purchase account form or trial promise. Public Checkout uses a random HttpOnly cookie (only its hash is stored), durable Stripe idempotency, canonical payment validation and fenced database leases. Claims require both the original browser token and a verified Supabase email matching Checkout. An arbitrary success URL or email cannot activate membership.

Verification

  • npm run check: typecheck/lint passed, 191 tests passed, plus Supabase database checks.
  • npm run build: production build passed, including public purchase and claim routes.
  • Nine payment-first tests cover Stripe session/subscription binding, verified email matching, retry recovery, SQL lease fencing, claim rollback, duplicate binding and denied browser privileges. Existing 18 billing tests cover owner authorization, idempotency and webhook signatures.
  • Actual /welcome HTML, styles and local fonts were rendered at 1440px and visually inspected; the payment CTA's contrast was corrected. No form precedes purchase.
  • Collaborative browser inspection hit repeated 15s automation timeouts; the alternate browser was unavailable. Visual QA used a self-contained render of the running page. Real Stripe payment/portal/webhook delivery remains untested without deployment credentials.

Risks or follow-up

Apply supabase/billing.sql, then supabase/billing-purchase.sql. Configure Stripe/Supabase server credentials, webhook signing secret, customer portal and HTTPS app origin, then run sandbox end-to-end payment tests before live activation. docs/billing/stripe-setup.md lists exact steps. No secrets are committed.

The owner confirmed price_1Sr6z31NPX0knP17OFmNZKMj on account acct_1SoBvQ1NPX0knP17: USD 15/month for both Players, no trial. The Do It product is tagged app=do-it; the account and price IDs are in .env.example. No unrelated product was used. Live Checkout requires BILLING_LIVE_ENABLED=true.

Payment-first purchase order is implemented; universal hard-paywall enforcement on existing habit/Duel APIs is not included. Existing offline access remains available. Subscription-only access needs a separate authoritative policy rollout.

A purchase must be activated in its original browser within the cookie's 30-day lifetime. Lost cookies require support recovery from the Stripe receipt. Do not tell the Player to repurchase. Financial records intentionally prevent silent Duel deletion; future deletion needs a cancellation/retention policy.

Summary

+ /welcome: payment-first membership offer for two
+ /billing: verified payment return, account setup and membership claim
+ /api/billing/purchase: public Checkout and authenticated claim
+ server-only billing tables, signed webhook reconciliation and durable leases
+ setup/recovery documentation

Evidence

  • Before: Checkout required an authenticated account and Duel before paying.
  • After: Checkout can start before signup; only a canonical paid receipt unlocks the post-payment setup screen. Checks above pass against the isolated PR checkout.

Merge Danger

Door: two-way for UI/API code; SQL migrations are additive and retain financial records.

Blast Radius: billing.

Existing habit data policies are unchanged. Current main has been merged and its dependency conflict resolved.

Connect the browser welcome page and Settings to authenticated Duel billing. Add owner-only Checkout and customer portal sessions, signed webhook reconciliation, and durable database leases to prevent duplicate purchases.

Keep existing offline access available during rollout and document Stripe, Supabase, and webhook configuration required before activation.
@vercel

vercel Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
do-it Ready Ready Preview Oct 14, 2026 9:14pm UTC

Retain the newer PGlite dependency used by the billing lease tests while including the merged Supabase egress changes and database checks.
Record the owner-selected live Stripe account and USD 15 monthly membership price for both Players. Document that the configured live product is separate from the account's basketball analytics product and requires matching deployment credentials.
Present one confirmed monthly plan and launch public Stripe Checkout before requesting account or habit data. Bind the paid receipt to a verified matching email after Duel creation using atomic fenced purchase claims.

Add durable anonymous purchase retries, canonical Stripe payment validation, signed webhook recovery, and security tests. Preserve existing data access during rollout and document activation requirements.
@Maseeek Maseeek changed the title Add Stripe subscription checkout and browser membership page Add payment-first Stripe membership and browser onboarding Oct 14, 2026
@Maseeek
Maseeek merged commit 6113a40 into main Oct 14, 2026
2 of 3 checks passed

This branch was successfully deployed

1 active deployment
Preview — 058a5f88 Deployed Oct 14, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant