Make stripe_customer_id NULLABLE via migration, clean up admin_override_*
values to NULL, and update Subscription/SubscriptionResponse/UpdateSubscriptionData
types in both backend and frontend.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Remove admin_override_ placeholder from createForAdminOverride(), use NULL.
Update mapSubscriptionRow() with ?? null. Make stripeCustomerId optional
in create() method.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Delete resolveStripeCustomerId() and replace with ensureStripeCustomer()
that includes orphaned Stripe customer cleanup on DB failure. Make
syncTierToUserProfile() blocking (errors propagate). Add null guards to
cancel/reactivate for admin-set subscriptions. Fix getInvoices() null
check. Clean controller comment. Add deleteCustomer() to StripeClient.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Refactors the subscription system to cleanly separate admin-managed tier overrides from Stripe-managed billing.
stripe_customer_idNULLABLE (replacesadmin_override_*sentinel values with NULL)resolveStripeCustomerId()withensureStripeCustomer()(includes orphaned customer cleanup)syncTierToUserProfile()blocking (prevents tier drift in all code paths)getInvoices()null checkChanges
Migration
002_nullable_stripe_customer_id.sql- DROP NOT NULL, cleanup sentinel valuesBackend Types
Subscription.stripeCustomerId: string | nullSubscriptionResponse.stripeCustomerId: string | nullUpdateSubscriptionData.stripeCustomerId?: string | nullRepository
createForAdminOverride()inserts NULL instead ofadmin_override_*placeholdermapSubscriptionRow()uses?? null(nullish coalescing)create()accepts optionalstripeCustomerIdService
resolveStripeCustomerId()(30 lines removed)ensureStripeCustomer()with orphaned Stripe customer cleanup on DB failuresyncTierToUserProfile()made blocking (error swallowing removed)cancelSubscription()/reactivateSubscription()- null guard for stripeCustomerIdgetInvoices()simplified from prefix check to null checkStripe Client
deleteCustomer()for cleanup logicController
admin_override_Frontend Types
Subscription.stripeCustomerId: string | nullTest Plan
Fixes #205
Fixes #207
Fixes #208
Fixes #209
Fixes #210