Skip to content

[PM-39387] fix: Auto-sync premium status after returning from Stripe checkout#21518

Open
cyprain-okeke wants to merge 5 commits into
mainfrom
billing/pm-39387/client-does-not-auto-sync-premium-status-after-completing-stripe-checkouts
Open

[PM-39387] fix: Auto-sync premium status after returning from Stripe checkout#21518
cyprain-okeke wants to merge 5 commits into
mainfrom
billing/pm-39387/client-does-not-auto-sync-premium-status-after-completing-stripe-checkouts

Conversation

@cyprain-okeke

Copy link
Copy Markdown
Contributor

🎟️ Tracking

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

📔 Objective

Premium status was not reflected in the client after a user completed payment in an external Stripe checkout flow. The server sends a one-time PremiumStatusChanged push, but the client misses it while it is in the background during checkout — so the user's premium entitlements don't appear until a later full sync.

This PR recovers the missed push by syncing when the client returns from checkout:

  • Adds PremiumCheckoutPendingService (abstraction + DefaultPremiumCheckoutPendingService) backed by a memory-scoped, account-scoped state flag (clearOn: ["logout"]).
  • PremiumUpgradeDialogComponent marks checkout as pending when it launches the external Stripe checkout URI.
  • Desktop consumes the flag on windowIsFocused and browser popup consumes it on init, triggering fullSync(true) to pull the updated premium status.
  • Registered the service in jslib-services.module.ts (Angular clients) and service-container.ts (CLI).
  • Adds unit tests for the new service and the browser/desktop/dialog wiring.

…checkout

The one-time PremiumStatusChanged push is missed while the client is in the
background during an external Stripe checkout, so premium status does not
reflect after the user completes payment. Track a memory-scoped, account-scoped
pending flag when checkout launches and consume it to trigger a full sync when
the client regains focus (desktop windowIsFocused) or reinitializes (browser
popup), recovering the missed push.
@cyprain-okeke cyprain-okeke added the ai-review Request a Claude code review label Jun 26, 2026
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🤖 Bitwarden Claude Code Review

Overall Assessment: APPROVE

Reviewed the new PremiumCheckoutPendingService (abstraction, Default implementation, and memory-scoped state key), its DI registration in jslib-services.module.ts and the CLI service-container.ts, and the browser-popup / desktop / dialog wiring that marks and consumes the pending flag. The implementation correctly recovers the missed one-time PremiumStatusChanged push by triggering a single fullSync(true) on return from checkout.

Code Review Details

No blocking findings.

Notable strengths verified during review:

  • consumeCheckoutPending reads and clears the flag atomically inside a single update(...), so repeated windowIsFocused events sync at most once (pinned by the desktop "syncs only once across repeated window focus events" test).
  • All three consumers fail closed — errors are logged and never block ngOnInit or the dialog flow, and a failed markCheckoutLaunched still launches checkout without showing an error toast.
  • State is correctly memory-scoped (BILLING_MEMORY) and account-scoped with clearOn: ["logout"], with a unit test pinning that contract so flipping to disk storage fails loudly.
  • DI registration follows conventions: safeProvider in the Angular module and constructor injection in the non-Angular CLI container.

…remium-status-after-completing-stripe-checkouts
@cyprain-okeke cyprain-okeke added the t:feature Change Type - Feature Development label Jun 26, 2026
@codecov

codecov Bot commented Jun 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.70175% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 49.53%. Comparing base (3779492) to head (b735f1d).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...dialog/premium-upgrade-dialog.component.stories.ts 0.00% 4 Missing ⚠️
...upgrade-dialog/premium-upgrade-dialog.component.ts 80.00% 0 Missing and 2 partials ⚠️
libs/angular/src/services/jslib-services.module.ts 0.00% 2 Missing ⚠️
...ctions/account/premium-checkout-pending.service.ts 0.00% 1 Missing ⚠️
libs/common/src/billing/abstractions/index.ts 0.00% 1 Missing ⚠️
...services/account/premium-checkout-pending.state.ts 66.66% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #21518      +/-   ##
==========================================
+ Coverage   49.32%   49.53%   +0.20%     
==========================================
  Files        4096     4099       +3     
  Lines      128872   128928      +56     
  Branches    19780    19786       +6     
==========================================
+ Hits        63564    63861     +297     
+ Misses      60597    60350     -247     
- Partials     4711     4717       +6     

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

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cyprain-okeke cyprain-okeke marked this pull request as ready for review June 26, 2026 16:10
@cyprain-okeke cyprain-okeke requested a review from a team as a code owner June 26, 2026 16:10
…remium-status-after-completing-stripe-checkouts
@sonarqubecloud

Copy link
Copy Markdown

@sbrown-livefront sbrown-livefront left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

✅ Looks good. Great thorough job ✨ 🧹 . Have these been manually tested for both?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Request a Claude code review t:feature Change Type - Feature Development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants