v2026.04.13.1
What's Changed
Features
Internal
- Fix Pagy::OverflowError in Products::AffiliatedController#index by @gumclaw in #4229
- Skip Sentry notification for expected TaxJar NotFound errors by @gumclaw in #4335
- Fix unhandled JSON::ParserError in DiscordController#join_server by @gumclaw in #4300
- Implement PUT /v2/products/:id update endpoint by @gianfrancopiana in #4272
- Stop reporting Taxjar::Error::BadRequest to Sentry by @gumclaw in #4239
- Allow suspended users to view most of the app by @gumclaw in #4333
- Add variant rich content support to v2 API by @gianfrancopiana in #4299
- Use cover image in the mobile app for products without a thumbnail by @binary-koan in #4324
- Add thumbnail and cover API endpoints for v2 products by @gianfrancopiana in #4311
- Fix affiliate edit page: apply_to_all_products sync and save error handling by @gumclaw in #4359
- Fix TypeError: no implicit conversion of nil into String in redirect_to_next by @gumclaw in #4240
- Remove password grant OAuth flow by @binary-koan in #4323
- Fix ArgumentError: invalid value for BigDecimal() in string_to_price_cents by @gumclaw in #4362
- Fix Rack::Timeout in AssetPreview retina variant processing by @gumclaw in #4357
- Fix unhandled Stripe::APIError in Settings::PaymentsController#update by @gumclaw in #4361
- Fix NoMethodError when default_tier is nil in API product show by @gumclaw in #4341
- Fix ProductDuplicatorService failing on effective date validation by @gumclaw in #4346
- Fix RequestTimeoutException in AnalyticsController#data_by_state by @gumclaw in #4368
- Fix Rack::Timeout in ifttt_sale_trigger by @gumclaw in #4366
- Fix Stripe Elements card input broken on Firefox + Windows by @gumclaw in #4286
- Fix Aws::S3::Errors::NoSuchKey in HLS playlist fetch by @gumclaw in #4245
- Fix false positive Sentry error when disabling membership price propagation by @gumclaw in #4277
- Fix NoMethodError on nil merchant_account in StripePayoutProcessor#prepare_payment_and_set_amount by @gumclaw in #4264
- Fix Stripe::InvalidRequestError when retrieving balance transaction in get_charge_object by @gumclaw in #4254
- Fix NoMethodError for unpaid_balance_cents_up_to_date_held_by_stripe by @gumclaw in #4231
- Fix Rack::Timeout on Discover page by adding timeout to curated products fetch by @gumclaw in #4222
- Handle stale Stripe account IDs in account session creation by @gumclaw in #4293
- Fix ArgumentError when invalid purchase_type is submitted by @gumclaw in #4360
- Fix Rack::Timeout in cart_items_count: replace full cart serialization with COUNT query by @gumclaw in #4296
- Fix Rack::Timeout on CheckoutController#show by adding timeout guard to recommendations by @gumclaw in #4221
- Add license_uses to Sales API response by @gumclaw in #4371
- Add structured comments and can_add_comment to Helper user_info API by @gianfrancopiana in #4317
- Fix Rack::Timeout in checkout upsells products endpoint by @gumclaw in #4251
- Update jobs page: email to gumclaw@gumroad.com, mark support as filled by @gumclaw in #4378
- Fix Link::LinkInvalid when deleting tiered memberships by @gumclaw in #4340
- Hide sold-out products from profile when 'Hide sold out versions' is enabled by @gumclaw in #4375
- Allow direct suspension without requiring flagging first by @gumclaw in #4364
- Fix NoMethodError on nil rich content nodes when saving product files by @gumclaw in #4379
- Fix MiniMagick::Error in Thumbnail#url crashing Discover page by @gumclaw in #4382
- Skip default offer code validation for unrelated product saves by @gumclaw in #4248
- Fix Elasticsearch BadRequest from non-Hash search param in profile pages by @gumclaw in #4334
- Update schema.rb for AddIdempotencyKeyToComments migration by @gianfrancopiana in #4390
- Update ASCII state machine diagram to reflect direct suspension transitions by @gumclaw in #4391
- Fix N+1: hoist author lookup before loop in SuspendUsersWorker by @gumclaw in #4392
- Remove feature flag requirement from CONTRIBUTING.md by @gumclaw in #4395
- Fix: Keep compiled test assets (packs-test) in Docker image by @gumclaw in #4387
- Fix NoMethodError in paypal_connect when oauth_integrations is nil by @gumclaw in #4384
- Raise unreviewed users minimum balance from $10 to $100 by @gumclaw in #4393
- Fix careers spec: update job slug to match current jobs.json by @gumclaw in #4399
- Fix purchase spec: pass author_name to suspend_for_fraud by @gumclaw in #4398
- Fix sales API spec: enable licensing on product for license_uses test by @gumclaw in #4400
- Fix profile product total count when filtering sold-out products by @gumclaw in #4401
- Fix remaining unreviewed users specs for $100 threshold by @gumclaw in #4403
- New customer detail page by @gumclaw in #4404
- Fix Resend API key restriction error for preview emails by @gumclaw in #4417
- Handle ResendApiResponseError in preview email flow by @gumclaw in #4414
- Potential fixes for 2 code quality findings by @slavingia in #4402
- Fix unreviewed users spec assertion ($50 → $150) by @gumclaw in #4421
- Fix N+1 on product options in checkout upsells endpoint by @gumclaw in #4374
- Add comment write endpoint for Helper by @gianfrancopiana in #4331
- Fix NoMethodError when address_fields is nil in InvoicesController#create by @gumclaw in #4423
- Fix NoMethodError in StripeCharge#build_flow_of_funds when destination payment balance transaction is nil by @gumclaw in #4427
- Fix Rack::Timeout in Api::V2::LinksController#index via pagination by @gumclaw in #4425
- Fix: Skip Brazilian Stripe validation when soft-deleting affiliates by @gumclaw in #4424
- Stub Stripe API calls in payments settings specs by @gumclaw in #4429
- Add PKCE support to Doorkeeper and CLI OAuth app seed by @gianfrancopiana in #4447
Full Changelog: v2026.04.06.2...v2026.04.13.1