PRDs · prds/06-billing-quotas-prd.md Docs Home

PRD 06: Billing, Plans, Quotas, Usage, and Wallet

Problem Statement

The legacy Zweistein platform includes Stripe subscriptions, plans, quotas, usage counters, usage records, trials, wallet/credits, token pricing, and billing UI. These are required if the preserved platform is operated as a real SaaS product. The old implementation is feature-rich but needs webhook idempotency, plan consolidation, transaction-safe quota checks, and clearer user feedback.

Solution

Build a billing and usage domain that supports:

  • Stripe checkout, upgrades, portal, and webhooks;
  • plan catalog and subscription lifecycle;
  • trial creation and expiration;
  • quota definitions and enforcement;
  • immutable usage records;
  • mutable usage counters with transaction safety;
  • wallet/credits where needed;
  • pricing and token cost tracking;
  • billing UI, upgrade prompts, and limit warnings.

Legacy Source References

  • zweistein-reference/server/src/subscriptions/
  • zweistein-reference/server/src/quotas/
  • zweistein-reference/server/src/billing/
  • zweistein-reference/server/src/wallet/
  • zweistein-reference/admin/src/subscriptions/
  • zweistein-reference/admin/src/pages/plans/

User Stories

  1. As a workspace owner, I want to choose a plan, so that I can activate the platform.
  2. As a workspace owner, I want Stripe checkout, so that payment is handled securely.
  3. As a workspace owner, I want to upgrade or downgrade, so that the plan fits usage.
  4. As a workspace owner, I want a billing portal, so that invoices and payment methods are self-service.
  5. As a trial user, I want to understand my trial status, so that I know when I need to upgrade.
  6. As a user, I want clear limit warnings, so that I can fix quota problems without confusion.
  7. As an admin, I want plan limits, so that usage can be controlled by subscription tier.
  8. As an operator, I want usage records, so that billing and audit reports are reliable.
  9. As an operator, I want quota counters to be concurrency-safe, so that users cannot exceed limits through parallel requests.
  10. As an operator, I want Stripe webhook idempotency, so that retries do not double-process billing events.
  11. As a finance owner, I want token pricing and cost tracking, so that AI spend maps to product limits.
  12. As an enterprise customer, I want no-quota or custom quota plans, so that contracted usage can be represented.

Functional Requirements

Plans

  • Single canonical plan entity.
  • Plan includes name, description, price, Stripe price ID, active flag, trial flag, trial days, priority, quota definitions, wallet grants, and enterprise/no-quota flags.
  • Admin UI to view and manage plans if required.

Subscriptions

  • Support creating checkout sessions.
  • Support upgrade checkout.
  • Support billing portal.
  • Support subscription status check.
  • Support trial creation and expiration.
  • Store active subscription per tenant, with Stripe identifiers.

Webhooks

  • Verify Stripe signature.
  • Deduplicate events by Stripe event ID.
  • Store webhook processing status.
  • Handle subscription created, updated, deleted, payment success, and payment failure events.
  • Alert or log failed webhook processing.

Quotas and Usage

  • Support resource types: tokens, messages, agents, bots, boards, companions, files, storage, research runs, tool calls, media processing, and custom resources.
  • Support daily, weekly, monthly, overall, and cumulative counters.
  • Store immutable usage records for audit.
  • Use database transactions and row locks for counter updates.
  • Support soft warnings before hard limit blocks.

Wallet and Token Pricing

  • Preserve wallet/credits if required for old plan behavior.
  • Track model token prices by provider/model.
  • Associate usage records with estimated cost.
  • Support grants on subscription start, renewal, or upgrade.

Non-Functional Requirements

  • No billing operation should depend on frontend trust.
  • No duplicate plan entities.
  • No non-idempotent webhook side effects.
  • No read-modify-write quota check without lock.
  • Billing states must be explainable in UI.

Implementation Decisions

  • Use Stripe as the first billing adapter.
  • Put Stripe behind a BillingAdapter interface.
  • Add webhook dedup table before production.
  • Merge subscription plans and quota plans into one plan model.
  • Add usage records before any expensive AI/tool execution.

Testing Decisions

  • Unit-test plan limit evaluation.
  • Unit-test quota reset logic.
  • Transaction-test concurrent quota consumption.
  • Integration-test Stripe webhook replay.
  • Browser-test checkout return, portal, upgrade, trial expired, and limit reached flows.

Out of Scope

  • Changing real Stripe production data before staging is verified.
  • Adding new payment providers before Stripe parity exists.