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
- As a workspace owner, I want to choose a plan, so that I can activate the platform.
- As a workspace owner, I want Stripe checkout, so that payment is handled securely.
- As a workspace owner, I want to upgrade or downgrade, so that the plan fits usage.
- As a workspace owner, I want a billing portal, so that invoices and payment methods are self-service.
- As a trial user, I want to understand my trial status, so that I know when I need to upgrade.
- As a user, I want clear limit warnings, so that I can fix quota problems without confusion.
- As an admin, I want plan limits, so that usage can be controlled by subscription tier.
- As an operator, I want usage records, so that billing and audit reports are reliable.
- As an operator, I want quota counters to be concurrency-safe, so that users cannot exceed limits through parallel requests.
- As an operator, I want Stripe webhook idempotency, so that retries do not double-process billing events.
- As a finance owner, I want token pricing and cost tracking, so that AI spend maps to product limits.
- 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.