Skip to content

feat(billing): gate billing page behind feature flag#914

Closed
saddlepaddle wants to merge 6 commits into
mainfrom
stripe-clean
Closed

feat(billing): gate billing page behind feature flag#914
saddlepaddle wants to merge 6 commits into
mainfrom
stripe-clean

Conversation

@saddlepaddle
Copy link
Copy Markdown
Collaborator

@saddlepaddle saddlepaddle commented Jan 23, 2026

Hide billing page from users without @superset.sh email until Stripe account is fully configured.

Uses PostHog feature flag billing-enabled which is set to only allow users with @superset.sh emails.

Changes:

  • Hide billing from sidebar when flag is disabled
  • Redirect to account settings if user navigates directly to billing routes

Summary by CodeRabbit

Release Notes

  • New Features

    • Added comprehensive billing settings dashboard with real-time subscription status and plan details
    • Implemented plan upgrade, downgrade, and subscription cancellation functionality
    • Added member count-based billing with seat tracking
    • Introduced plan comparison view for easy upgrade decisions
    • Added payment success confirmation page
    • Integrated feature flag for gradual billing rollout
  • Chores

    • Updated dependencies for improved performance and security

✏️ Tip: You can customize this high-level summary in your review settings.

Implements Stripe subscription billing using Better Auth's Stripe plugin.

## Backend
- Add @better-auth/stripe and stripe packages
- Configure Stripe plugin with org-based subscriptions
- Add organization hooks: afterCreateOrganization (create Stripe customer),
  afterUpdateOrganization (sync name), beforeAddMember (seat limit check),
  afterAddMember/afterRemoveMember (update subscription quantity)
- Add plan to session via customSession plugin
- Create subscriptions table migration
- Add stripeCustomerId to organizations schema

## Frontend
- Update billing UI to use cancelAt instead of cancelAtPeriodEnd
- Show renewal date for active Pro subscriptions
- Add billing pre-warning when inviting members on Pro plan
- Add billing note to remove member confirmation on Pro plan
- Add toast notification on plan restore
- Create billing success page for web app

## Scripts
- Add backfill-stripe-customers script for existing orgs
- Add recover-stripe-customers script to link orphaned customers
- Add wipe-stripe-customers script for dev cleanup

## Environment
- Add STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET env vars
Add STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, STRIPE_PRO_MONTHLY_PRICE_ID,
and STRIPE_PRO_YEARLY_PRICE_ID to deploy-preview.yml and deploy-production.yml
for api, web, marketing, and admin jobs.
- Remove verbose/lifecycle console.logs from auth server
- Remove unused onEvent webhook handler
- Fix stale session.plan usage in MembersSettings (use subscription query)
- Remove trialing status checks (not used)
- Remove unnecessary memberCount || 1 fallback
- Remove comments from PlansComparison
- Update @sentry/nextjs to ^10.36.0 across all apps
- Align better-auth to ^1.4.17 across all packages
- Regenerate bun.lock to fix rollup version mismatch
Hide billing page from users without @superset.sh email until
Stripe account is fully configured with tax ID and payment methods.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 23, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Introduces comprehensive Stripe billing integration across the monorepo, including environment configuration, database schema for subscriptions, updated auth server plugins with organization lifecycle hooks, and refactored desktop/web billing UI components with subscription-aware features, member limits, upgrade/downgrade/cancel flows, and feature-flag gating.

Changes

Cohort / File(s) Summary
Environment Configuration
.env.example, apps/admin/src/env.ts, apps/api/src/env.ts, apps/desktop/src/renderer/auth-client.ts, apps/docs/src/env.ts, apps/marketing/src/env.ts, apps/web/src/env.ts, packages/auth/src/env.ts
Added four Stripe environment variables (STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, STRIPE_PRO_MONTHLY_PRICE_ID, STRIPE_PRO_YEARLY_PRICE_ID) to example config and server schemas across all apps; variables are required in most apps but optional in docs.
GitHub Actions Workflows
.github/workflows/deploy-preview.yml, .github/workflows/deploy-production.yml
Extended deployment workflows to pass Stripe secrets through environment variables to Vercel deployment steps across multiple deployment targets (api, web, marketing, admin, docs, electric).
Dependency Updates
apps/admin/package.json, apps/api/package.json, apps/docs/package.json, apps/marketing/package.json, apps/mobile/package.json, apps/web/package.json, packages/auth/package.json
Updated @sentry/nextjs from ^10.32.1 to ^10.36.0; updated better-auth from 1.4.16 to ^1.4.17; added @better-auth/stripe ^1.4.17 and stripe ^20.2.0 to auth package.
Database Schema & Migrations
packages/db/drizzle/0012_add_stripe_subscription_fields.sql, packages/db/drizzle/meta/0012_snapshot.json, packages/db/drizzle/meta/_journal.json, packages/db/src/schema/auth.ts, packages/db/src/schema/schema.ts, packages/db/src/schema/relations.ts
Created subscriptions table with plan, Stripe IDs, status, periods, cancellation, and seats fields; added stripe_customer_id to organizations; established foreign key and indexes; exported InsertSubscription and SelectSubscription types; added subscription relationships.
Auth Server Integration
packages/auth/src/client.ts, packages/auth/src/server.ts
Integrated Stripe plugin with stripeClient; added organization lifecycle hooks (afterCreate, beforeDelete, afterUpdate to manage Stripe customers); added member hooks (beforeAdd for limits, afterAdd/afterRemove for quantity updates); extended schema to include subscriptions; augmented session with plan data.
Desktop Billing Components
apps/desktop/src/renderer/routes/_authenticated/settings/billing/components/BillingOverview/BillingOverview.tsx, apps/desktop/src/renderer/routes/_authenticated/settings/billing/components/BillingOverview/components/CurrentPlanCard/CurrentPlanCard.tsx, apps/desktop/src/renderer/routes/_authenticated/settings/billing/components/BillingOverview/components/UpgradeCard/UpgradeCard.tsx, apps/desktop/src/renderer/routes/_authenticated/settings/billing/components/PlansComparison/PlansComparison.tsx
Replaced mock billing data with real subscription queries; added handlers for upgrade, downgrade, cancel, and restore flows; refactored UI to display plan status, cancellation dates, member counts, and loading states; extended PlanCardAction type to include downgrade and restore actions.
Desktop Billing Page & Invoices
apps/desktop/src/renderer/routes/_authenticated/settings/billing/page.tsx, apps/desktop/src/renderer/routes/_authenticated/settings/billing/plans/page.tsx, apps/desktop/src/renderer/routes/_authenticated/settings/billing/components/BillingOverview/components/InvoicesSection/InvoicesSection.tsx, apps/desktop/src/renderer/routes/_authenticated/settings/billing/components/BillingOverview/components/InvoicesSection/index.ts
Added feature-flag gating (billing-enabled) to billing pages, redirecting to settings/account when disabled; removed InvoicesSection component and its barrel export.
Desktop Members & Settings
apps/desktop/src/renderer/routes/_authenticated/settings/members/components/MembersSettings/MembersSettings.tsx, apps/desktop/src/renderer/routes/_authenticated/settings/members/components/MembersSettings/components/InviteMemberButton/InviteMemberButton.tsx, apps/desktop/src/renderer/routes/_authenticated/settings/members/components/MembersSettings/components/MemberActions/MemberActions.tsx, apps/desktop/src/renderer/routes/_authenticated/settings/members/components/PendingInvitations/PendingInvitations.tsx, apps/desktop/src/renderer/routes/_authenticated/settings/components/SettingsSidebar/GeneralSettings.tsx
Added plan-aware member management: subscription query for active plan, conditional billing alerts for pro plan invites, plan-based messages in removal confirmations; added feature-flag gating to hide billing section when disabled.
Desktop Settings Search
apps/desktop/src/renderer/routes/_authenticated/settings/utils/settings-search/settings-search.ts
Removed BILLING_INVOICES entry from settings catalog.
Web Billing Page
apps/web/src/app/(dashboard)/settings/billing/page.tsx
Added new server component BillingPage with success parameter handling; displays payment confirmation UI with icon and messaging when success=true, otherwise prompts desktop app billing management.
Utility Scripts
packages/scripts/package.json, packages/scripts/src/backfill-stripe-customers.ts, packages/scripts/src/recover-stripe-customers.ts, packages/scripts/src/wipe-stripe-customers.ts, packages/scripts/tsconfig.json
Added new scripts package with three Stripe utilities: backfill-stripe-customers (creates Stripe customers for orgs), recover-stripe-customers (re-links Stripe customers from metadata), wipe-stripe-customers (clears stripe_customer_id); includes TypeScript config and npm scripts.
Documentation
docs/tickets/desktop-invite-member.md
Comprehensive implementation documentation for invite member workflow including authorization helpers, rate limiting, email templates, and database schema; exported types include getInvitableRoles, canInvite, and email components.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Desktop as Desktop App
    participant AuthServer as Auth Server
    participant Stripe as Stripe API
    participant DB as Database

    User->>Desktop: View Billing Overview
    Desktop->>AuthServer: Get active organization & subscription
    AuthServer->>DB: Query subscription by org ID
    DB-->>AuthServer: Return subscription data (plan, status, cancelAt)
    AuthServer-->>Desktop: Return subscription with plan
    Desktop->>Desktop: Derive currentPlan from subscription

    User->>Desktop: Click Upgrade Plan
    Desktop->>AuthServer: Create checkout session
    AuthServer->>Stripe: Create checkout session (organization metadata)
    Stripe-->>AuthServer: Return checkout URL
    AuthServer-->>Desktop: Return session URL
    Desktop->>Stripe: Redirect to checkout
    
    User->>Stripe: Complete payment
    Stripe-->>AuthServer: Webhook: charge.succeeded
    AuthServer->>DB: Update subscription status (active)
    AuthServer->>Stripe: Retrieve subscription details
    Stripe-->>AuthServer: Return subscription ID & period

    User->>Desktop: View Billing (post-upgrade)
    Desktop->>AuthServer: Get updated subscription
    AuthServer->>DB: Query subscription
    DB-->>AuthServer: Return updated subscription
    AuthServer-->>Desktop: Return new plan (pro)
    Desktop->>Desktop: Render CurrentPlanCard with active plan & cancel option
Loading
sequenceDiagram
    participant Desktop as Desktop App
    participant AuthServer as Auth Server
    participant DB as Database
    participant Stripe as Stripe API

    rect rgba(200, 100, 100, 0.5)
        Note over Desktop,DB: Add Member to Pro Plan Org
        Desktop->>Desktop: Get current plan (pro)
        Desktop->>Desktop: Show InviteMemberButton with plan prop
        
        User->>Desktop: Click Invite Member
        Desktop->>Desktop: Check plan == pro
        Desktop->>Desktop: Show billing alert
        User->>Desktop: Confirm invite
    end

    Desktop->>AuthServer: Invite member (with rate limit)
    AuthServer->>AuthServer: Check inviter role permissions
    AuthServer->>AuthServer: Enforce rate limit (10 per hour)
    
    alt Rate limit OK
        AuthServer->>DB: Insert invitation record
        AuthServer->>Stripe: Update subscription quantity (members++)
        Stripe-->>AuthServer: Confirm quantity updated
        AuthServer-->>Desktop: Invitation sent
        Desktop->>Desktop: Show toast success
    else Rate limit exceeded
        AuthServer-->>Desktop: Return error
        Desktop->>Desktop: Show toast error
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Poem

🐰 A stripe across the billing sky,
With plans and subscriptions drawing nigh,
Features gated, members counted true,
Webhooks dance in Stripe's morning dew,
Subscriptions bloom where mocks once flew! 💰✨

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 23, 2026

🚀 Preview Deployment

🔗 Preview Links

Service Status Link
Neon Database (Neon) View Branch
Fly.io Electric (Fly.io) View App
Vercel API (Vercel) Open Preview
Vercel Web (Vercel) Open Preview
Vercel Marketing (Vercel) Open Preview
Vercel Admin (Vercel) Open Preview
Vercel Docs (Vercel) Open Preview

Preview updates automatically with new commits

@Kitenite Kitenite deleted the stripe-clean branch January 23, 2026 05:47
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