Skip to content

[PM-31040] Replace ISetupIntentCache with customer-based approach#6954

Merged
amorask-bitwarden merged 40 commits intomainfrom
billing/PM-31040/replace-setup-intent-cache
Feb 18, 2026
Merged

[PM-31040] Replace ISetupIntentCache with customer-based approach#6954
amorask-bitwarden merged 40 commits intomainfrom
billing/PM-31040/replace-setup-intent-cache

Conversation

@amorask-bitwarden
Copy link
Copy Markdown
Contributor

@amorask-bitwarden amorask-bitwarden commented Feb 5, 2026

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-31040

📔 Objective

Replace the ISetupIntentCache distributed cache with a customer-based approach that directly associates Stripe SetupIntent objects with Stripe Customer objects. This eliminates infrastructure dependencies on the distributed cache and simplifies the codebase by removing dead code paths.

Problem

The SetupIntentDistributedCache maintained a bidirectional mapping between subscriber IDs and SetupIntent IDs, which was fragile and caused issues with the bank account payment method flow for organizations and providers.

Solution

Instead of caching the SetupIntent-to-subscriber relationship:

  1. Set the customer field on the SetupIntent when it's retrieved (during subscription creation or payment method update)
  2. Query subscribers by GatewayCustomerId when webhooks arrive, using new repository methods
  3. Remove all cache-related code and dead code paths

Changes

Database Infrastructure (Phase 1-3)

  • Add new stored procedures for querying Organizations, Providers, and Users by GatewayCustomerId and GatewaySubscriptionId
  • Add filtered indexes on GatewayCustomerId and GatewaySubscriptionId columns for all three entity tables
  • Add corresponding repository methods (both Dapper and Entity Framework implementations)
  • Generate EF migrations for MySQL, PostgreSQL, and SQLite

SetupIntent Handling Updates (Phase 4-5)

  • Update SetupIntentSucceededHandler to query repositories by customer ID instead of using the cache
  • Simplify StripeEventService by expanding customer data directly from SetupIntent
  • Update GetPaymentMethodQuery and HasPaymentMethodQuery to query Stripe by customer ID
  • Update OrganizationBillingService, ProviderBillingService, and UpdatePaymentMethodCommand to set the customer on SetupIntents

Dead Code Removal (Phase 6-7)

  • Remove bank account support from CreatePremiumCloudHostedSubscriptionCommand (premium users cannot use bank accounts)
  • Remove UpdatePaymentMethod from OrganizationBillingService, ProviderBillingService, and PremiumUserBillingService (replaced by UpdatePaymentMethodCommand)
  • Remove UpdatePaymentSource from SubscriberService
  • Remove SignUpPremiumAsync and ReplacePaymentMethodAsync from UserService (orphaned at API layer)
  • Remove Finalize from PremiumUserBillingService
  • Remove ISetupIntentCache and SetupIntentDistributedCache

📸 Screenshots

Screen.Recording.2026-02-05.at.1.40.26.PM.mov

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

…od and UserService.ReplacePaymentMethodAsync
…query Stripe by customer ID

Add Task 15a to plan - this was a missed requirement for updating
GetPaymentSourceAsync which still used the cache.
@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 5, 2026

Codecov Report

❌ Patch coverage is 35.16484% with 118 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.59%. Comparing base (2ce9827) to head (965c0a8).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...frastructure.Dapper/Repositories/UserRepository.cs 0.00% 20 Missing ⚠️
...dminConsole/Repositories/OrganizationRepository.cs 0.00% 18 Missing ⚠️
...er/AdminConsole/Repositories/ProviderRepository.cs 0.00% 18 Missing ⚠️
...dminConsole/Repositories/OrganizationRepository.cs 0.00% 18 Missing ⚠️
...rk/AdminConsole/Repositories/ProviderRepository.cs 0.00% 18 Missing ⚠️
...ure.EntityFramework/Repositories/UserRepository.cs 0.00% 16 Missing ⚠️
...ganizations/Services/OrganizationBillingService.cs 0.00% 7 Missing ⚠️
...vices/Implementations/PremiumUserBillingService.cs 0.00% 1 Missing ⚠️
.../Billing/Services/Implementations/StripeAdapter.cs 0.00% 1 Missing ⚠️
...ling/Services/Implementations/SubscriberService.cs 83.33% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6954      +/-   ##
==========================================
+ Coverage   56.49%   60.59%   +4.10%     
==========================================
  Files        2003     2003              
  Lines       88287    87886     -401     
  Branches     7881     7829      -52     
==========================================
+ Hits        49874    53255    +3381     
+ Misses      36581    32724    -3857     
- Partials     1832     1907      +75     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 5, 2026

Logo
Checkmarx One – Scan Summary & Detailsa565234d-2dd1-4943-b381-fb481000c27c

New Issues (3)

Checkmarx found the following issues in this Pull Request

# Severity Issue Source File / Package Checkmarx Insight
1 MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 1527
detailsMethod at line 1527 of /src/Api/Vault/Controllers/CiphersController.cs gets a parameter from a user request from id. This parameter value flows ...
Attack Vector
2 MEDIUM CSRF /src/Api/Auth/Controllers/AccountsController.cs: 291
detailsMethod at line 291 of /src/Api/Auth/Controllers/AccountsController.cs gets a parameter from a user request from model. This parameter value flow...
Attack Vector
3 MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 1403
detailsMethod at line 1403 of /src/Api/Vault/Controllers/CiphersController.cs gets a parameter from a user request from id. This parameter value flows ...
Attack Vector
Fixed Issues (1)

Great job! The following issues were fixed in this Pull Request

Severity Issue Source File / Package
MEDIUM CSRF /src/Api/Vault/Controllers/CiphersController.cs: 293

mkincaid-bw
mkincaid-bw previously approved these changes Feb 13, 2026
Copy link
Copy Markdown
Contributor

@mkincaid-bw mkincaid-bw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

BTreston
BTreston previously approved these changes Feb 17, 2026
Copy link
Copy Markdown
Contributor

@BTreston BTreston left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approved for AC owned files

mkincaid-bw
mkincaid-bw previously approved these changes Feb 18, 2026
@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@rkac-bw rkac-bw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved as per Mark's approval

@amorask-bitwarden amorask-bitwarden merged commit cfd5bed into main Feb 18, 2026
57 of 58 checks passed
@amorask-bitwarden amorask-bitwarden deleted the billing/PM-31040/replace-setup-intent-cache branch February 18, 2026 19:20
gbubemismith pushed a commit that referenced this pull request Feb 27, 2026
…6954)

* docs(billing): add design document for replacing SetupIntent cache

* docs(billing): add implementation plan for replacing SetupIntent cache

* feat(db): add gateway lookup stored procedures for Organization, Provider, and User

* feat(db): add gateway lookup indexes to Organization, Provider, and User table definitions

* chore(db): add SQL Server migration for gateway lookup indexes and stored procedures

* feat(repos): add gateway lookup methods to IOrganizationRepository and Dapper implementation

* feat(repos): add gateway lookup methods to IProviderRepository and Dapper implementation

* feat(repos): add gateway lookup methods to IUserRepository and Dapper implementation

* feat(repos): add EF OrganizationRepository gateway lookup methods and index configuration

* feat(repos): add EF ProviderRepository gateway lookup methods and index configuration

* feat(repos): add EF UserRepository gateway lookup methods and index configuration

* chore(db): add EF migrations for gateway lookup indexes

* refactor(billing): update SetupIntentSucceededHandler to use repository instead of cache

* refactor(billing): simplify StripeEventService by expanding customer on SetupIntent

* refactor(billing): query Stripe for SetupIntents by customer ID in GetPaymentMethodQuery

* refactor(billing): query Stripe for SetupIntents by customer ID in HasPaymentMethodQuery

* refactor(billing): update OrganizationBillingService to set customer on SetupIntent

* refactor(billing): update ProviderBillingService to set customer on SetupIntent and query by customer

* refactor(billing): update UpdatePaymentMethodCommand to set customer on SetupIntent

* refactor(billing): remove bank account support from CreatePremiumCloudHostedSubscriptionCommand

* refactor(billing): remove OrganizationBillingService.UpdatePaymentMethod dead code

* refactor(billing): remove ProviderBillingService.UpdatePaymentMethod

* refactor(billing): remove PremiumUserBillingService.UpdatePaymentMethod and UserService.ReplacePaymentMethodAsync

* refactor(billing): remove SubscriberService.UpdatePaymentSource and related dead code

* refactor(billing): update SubscriberService.GetPaymentSourceAsync to query Stripe by customer ID

Add Task 15a to plan - this was a missed requirement for updating
GetPaymentSourceAsync which still used the cache.

* refactor(billing): complete removal of PremiumUserBillingService.Finalize and UserService.SignUpPremiumAsync

* refactor(billing): remove ISetupIntentCache and SetupIntentDistributedCache

* chore: remove temporary planning documents

* chore: run dotnet format

* fix(billing): add MaxLength(50) to Provider gateway ID properties

* chore(db): add EF migrations for Provider gateway column lengths

* chore: run dotnet format

* chore: rename SQL migration for chronological order
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants