Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
75a228f
Initial backend impl
jahooma Jan 28, 2026
00af124
Review fixes
jahooma Jan 28, 2026
8e31469
Plans to tiered subscription. Don't store plan name/tier in db
jahooma Jan 28, 2026
66463e9
Extract getUserByStripeCustomerId helper
jahooma Jan 28, 2026
b807cfa
migrateUnusedCredits: remove filter on free/referral
jahooma Jan 28, 2026
8976298
Add .env.example for stripe price id
jahooma Jan 28, 2026
ed2a1d9
Remove subscription_count. Add more stripe status enums
jahooma Jan 28, 2026
31db66e
cleanup
jahooma Jan 28, 2026
458616a
Generate migration
jahooma Jan 28, 2026
c39155b
More reviewer improvments
jahooma Jan 28, 2026
cba210d
Update migrateUnusedCredits query
jahooma Jan 28, 2026
40a0b2e
Rename Flex to Strong
jahooma Jan 28, 2026
76f71c4
Add subscription tiers. Extract util getStripeId
jahooma Jan 28, 2026
9184aa2
Web routes to cancel, change tier, create subscription, or get subscr…
jahooma Jan 28, 2026
3f81504
Web subscription UI
jahooma Jan 28, 2026
5e9b314
Fix billing test to mock subscription endpoint
jahooma Jan 28, 2026
7f5e135
Remove subscription client UI (moved to subscription-client branch)
jahooma Jan 28, 2026
7059836
Add subscription grant type to usage-display for typecheck compatibility
jahooma Jan 28, 2026
1509a09
Update tier usage limits (1x, 3x, 8x)
jahooma Jan 29, 2026
1b1176c
Fixes from reviewer
jahooma Jan 29, 2026
f95faaa
Cleanup tier mapping code
jahooma Jan 29, 2026
f114adf
Tweaks and don't downgrade tier immediately if switch plans
jahooma Jan 29, 2026
8eafcfb
scheduled_tier used for downgrade
jahooma Jan 29, 2026
a6f9ba1
Don't default to a tier when creating a subscription
jahooma Jan 29, 2026
40921f7
Unit subscription.ts with DI patterns and unit tests
jahooma Jan 29, 2026
1fe1966
Update description of row of migrated credits
jahooma Jan 29, 2026
4a6d7c0
Simplify getStripeId. Move null checks into callers
jahooma Jan 29, 2026
f00eeb4
Split try catch in two
jahooma Jan 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ STRIPE_SECRET_KEY=sk_test_dummy_stripe_secret
STRIPE_WEBHOOK_SECRET_KEY=whsec_dummy_webhook_secret
STRIPE_USAGE_PRICE_ID=price_dummy_usage_id
STRIPE_TEAM_FEE_PRICE_ID=price_dummy_team_fee_id
STRIPE_SUBSCRIPTION_100_PRICE_ID=price_dummy_subscription_100_id
STRIPE_SUBSCRIPTION_200_PRICE_ID=price_dummy_subscription_200_id
STRIPE_SUBSCRIPTION_500_PRICE_ID=price_dummy_subscription_500_id

# External Services
LINKUP_API_KEY=dummy_linkup_key
Expand Down
10 changes: 10 additions & 0 deletions common/src/constants/analytics-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ export enum AnalyticsEvent {
ADVISORY_LOCK_CONTENTION = 'backend.advisory_lock_contention',
TRANSACTION_RETRY_THRESHOLD_EXCEEDED = 'backend.transaction_retry_threshold_exceeded',

// Backend - Subscription
SUBSCRIPTION_CREATED = 'backend.subscription_created',
SUBSCRIPTION_CANCELED = 'backend.subscription_canceled',
SUBSCRIPTION_PAYMENT_FAILED = 'backend.subscription_payment_failed',
SUBSCRIPTION_BLOCK_CREATED = 'backend.subscription_block_created',
SUBSCRIPTION_BLOCK_LIMIT_HIT = 'backend.subscription_block_limit_hit',
SUBSCRIPTION_WEEKLY_LIMIT_HIT = 'backend.subscription_weekly_limit_hit',
SUBSCRIPTION_CREDITS_MIGRATED = 'backend.subscription_credits_migrated',
SUBSCRIPTION_TIER_CHANGED = 'backend.subscription_tier_changed',

// Web
SIGNUP = 'web.signup',

Expand Down
1 change: 1 addition & 0 deletions common/src/constants/grant-priorities.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { GrantType } from '@codebuff/common/types/grant'

export const GRANT_PRIORITIES: Record<GrantType, number> = {
subscription: 10,
free: 20,
referral: 30,
ad: 40,
Expand Down
49 changes: 49 additions & 0 deletions common/src/constants/subscription-plans.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
export const SUBSCRIPTION_DISPLAY_NAME = 'Strong' as const

export interface TierConfig {
monthlyPrice: number
creditsPerBlock: number
blockDurationHours: number
weeklyCreditsLimit: number
}

export const SUBSCRIPTION_TIERS = {
100: {
monthlyPrice: 100,
creditsPerBlock: 400,
blockDurationHours: 5,
weeklyCreditsLimit: 4000,
},
200: {
monthlyPrice: 200,
creditsPerBlock: 1200,
blockDurationHours: 5,
weeklyCreditsLimit: 12000,
},
500: {
monthlyPrice: 500,
creditsPerBlock: 3200,
blockDurationHours: 5,
weeklyCreditsLimit: 32000,
},
} as const satisfies Record<number, TierConfig>

export type SubscriptionTierPrice = keyof typeof SUBSCRIPTION_TIERS

export const DEFAULT_TIER = SUBSCRIPTION_TIERS[200]

export function createSubscriptionPriceMappings(priceIds: Record<SubscriptionTierPrice, string>) {
const priceToTier = Object.fromEntries(
Object.entries(priceIds).map(([tier, priceId]) => [priceId, Number(tier) as SubscriptionTierPrice]),
) as Record<string, SubscriptionTierPrice>

function getTierFromPriceId(priceId: string): SubscriptionTierPrice | null {
return priceToTier[priceId] ?? null
}

function getPriceIdFromTier(tier: SubscriptionTierPrice): string | null {
return priceIds[tier] ?? null
}

return { getTierFromPriceId, getPriceIdFromTier }
}
2 changes: 2 additions & 0 deletions common/src/types/grant.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export type GrantType =
| 'free'
| 'referral'
| 'subscription'
| 'purchase'
| 'admin'
| 'organization'
Expand All @@ -9,6 +10,7 @@ export type GrantType =
export const GrantTypeValues = [
'free',
'referral',
'subscription',
'purchase',
'admin',
'organization',
Expand Down
Loading