fix: route subscription deep links through billing facade - #14998
fix: route subscription deep links through billing facade#14998dante01yoon wants to merge 1 commit into
Conversation
Co-authored-by: Amp <amp@ampcode.com> Amp-Thread-ID: https://ampcode.com/threads/T-019fed1a-dbd9-725b-8d97-aefe395a9996
📝 WalkthroughWalkthroughChangesThe subscription redirect flow now uses pricing-table dialogs for personal and team links. Active subscriptions use billing-context management. The subscription route is standalone, and the checkout-selection helper is exported under its new name. Subscription redirect flow
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant DeepLink
participant CloudSubscriptionRedirectView
participant BillingContext
participant PricingTableDialog
DeepLink->>CloudSubscriptionRedirectView: Open subscription link
CloudSubscriptionRedirectView->>BillingContext: Read subscription state and team credit stops
CloudSubscriptionRedirectView->>BillingContext: Load plans when required
CloudSubscriptionRedirectView->>PricingTableDialog: Open pricing with checkout selection
BillingContext-->>CloudSubscriptionRedirectView: Return active subscription state
CloudSubscriptionRedirectView->>BillingContext: Manage active subscription
Possibly related PRs
Suggested labels: Suggested reviewers: Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 inconclusive)
✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🎨 Storybook: ✅ Built — View Storybook📦 Bundle: 8.69 MB gzip 🔴 +1.26 kBDetailsSummary
Category Glance App Entry Points — 3.71 kB (baseline 3.67 kB) • 🔴 +33 BMain entry bundles and manifests
Status: 1 added / 1 removed Graph Workspace — 1.36 MB (baseline 1.36 MB) • 🔴 +13 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed / 2 unchanged Views & Navigation — 123 kB (baseline 124 kB) • 🟢 -426 BTop-level views, pages, and routed surfaces
Status: 1 added / 1 removed / 16 unchanged Panels & Settings — 569 kB (baseline 569 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens Status: 26 unchanged User & Accounts — 27 kB (baseline 27 kB) • ⚪ 0 BAuthentication, profile, and account management bundles Status: 10 unchanged Editors & Dialogs — 125 kB (baseline 125 kB) • ⚪ 0 BModals, dialogs, drawers, and in-app editors Status: 8 unchanged UI Components — 67.1 kB (baseline 67.1 kB) • ⚪ 0 BReusable component library chunks Status: 14 unchanged Data & Services — 3.5 MB (baseline 3.5 MB) • ⚪ 0 BStores, services, APIs, and repositories Status: 17 unchanged Utilities & Hooks — 553 kB (baseline 549 kB) • 🔴 +3.71 kBHelpers, composables, and utility bundles
Status: 1 added / 1 removed / 37 unchanged Vendor & Third-Party — 16.3 MB (baseline 16.3 MB) • ⚪ 0 BExternal libraries and shared vendor chunks Status: 17 unchanged Other — 14 MB (baseline 14 MB) • 🔴 +861 BBundles that do not match a named category
Status: 8 added / 7 removed / 279 unchanged ⚡ Performance Report
Show regressions
All metrics
Historical variance (last 15 runs)
Trend (last 15 commits on main)
Raw data{
"timestamp": "2026-08-10T20:05:44.313Z",
"gitSha": "02692df38e86715be33618f73c9237008bb375ef",
"branch": "dante/subscription-deeplink-billing-facade",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2020.2779999999905,
"styleRecalcs": 9,
"styleRecalcDurationMs": 6.411999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 511.583,
"heapDeltaBytes": 5813988,
"heapUsedBytes": 70254964,
"domNodes": 18,
"jsHeapTotalBytes": 24903680,
"scriptDurationMs": 14.029,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-idle",
"durationMs": 2017.9840000000127,
"styleRecalcs": 9,
"styleRecalcDurationMs": 6.593,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 444.34299999999996,
"heapDeltaBytes": 5881936,
"heapUsedBytes": 70358184,
"domNodes": 18,
"jsHeapTotalBytes": 24117248,
"scriptDurationMs": 14.219,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1817.906000000022,
"styleRecalcs": 75,
"styleRecalcDurationMs": 35.039,
"layouts": 12,
"layoutDurationMs": 3.295,
"taskDurationMs": 806.677,
"heapDeltaBytes": 793348,
"heapUsedBytes": 64902432,
"domNodes": 57,
"jsHeapTotalBytes": 25165824,
"scriptDurationMs": 115.25200000000001,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1839.2690000000016,
"styleRecalcs": 74,
"styleRecalcDurationMs": 33.43899999999999,
"layouts": 12,
"layoutDurationMs": 3.5709999999999997,
"taskDurationMs": 857.2610000000001,
"heapDeltaBytes": -12010728,
"heapUsedBytes": 52332664,
"domNodes": -282,
"jsHeapTotalBytes": 23830528,
"scriptDurationMs": 121.365,
"eventListeners": -153,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1713.0200000000286,
"styleRecalcs": 32,
"styleRecalcDurationMs": 14.889000000000001,
"layouts": 6,
"layoutDurationMs": 0.611,
"taskDurationMs": 356.221,
"heapDeltaBytes": 8699920,
"heapUsedBytes": 72919764,
"domNodes": 77,
"jsHeapTotalBytes": 25165824,
"scriptDurationMs": 17.527999999999995,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1707.693000000063,
"styleRecalcs": 31,
"styleRecalcDurationMs": 14.431000000000001,
"layouts": 6,
"layoutDurationMs": 0.5609999999999998,
"taskDurationMs": 353.305,
"heapDeltaBytes": 8760344,
"heapUsedBytes": 72935296,
"domNodes": 77,
"jsHeapTotalBytes": 24641536,
"scriptDurationMs": 16.544,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "dom-widget-clipping",
"durationMs": 594.0269999999828,
"styleRecalcs": 12,
"styleRecalcDurationMs": 8.076,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 364.776,
"heapDeltaBytes": -11187836,
"heapUsedBytes": 53096868,
"domNodes": 20,
"jsHeapTotalBytes": 24903680,
"scriptDurationMs": 56.40899999999999,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "dom-widget-clipping",
"durationMs": 578.3339999999839,
"styleRecalcs": 12,
"styleRecalcDurationMs": 7.402000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 357.752,
"heapDeltaBytes": -11290220,
"heapUsedBytes": 53220848,
"domNodes": 20,
"jsHeapTotalBytes": 25427968,
"scriptDurationMs": 58.00799999999999,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-idle",
"durationMs": 2062.8279999999677,
"styleRecalcs": 9,
"styleRecalcDurationMs": 11.014,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 664.188,
"heapDeltaBytes": 7690920,
"heapUsedBytes": 67187724,
"domNodes": -282,
"jsHeapTotalBytes": 2985984,
"scriptDurationMs": 103.35399999999998,
"eventListeners": -149,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-idle",
"durationMs": 2057.8499999999167,
"styleRecalcs": 9,
"styleRecalcDurationMs": 7.225000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 666.0300000000001,
"heapDeltaBytes": 6792700,
"heapUsedBytes": 66289404,
"domNodes": -282,
"jsHeapTotalBytes": 4034560,
"scriptDurationMs": 102.835,
"eventListeners": -177,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2139.7329999999783,
"styleRecalcs": 67,
"styleRecalcDurationMs": 11.007,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1211.1509999999998,
"heapDeltaBytes": 15822104,
"heapUsedBytes": 77515184,
"domNodes": -286,
"jsHeapTotalBytes": 3702784,
"scriptDurationMs": 407.274,
"eventListeners": -177,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-pan",
"durationMs": 2162.546999999904,
"styleRecalcs": 69,
"styleRecalcDurationMs": 12.965999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1234.6920000000002,
"heapDeltaBytes": 4922304,
"heapUsedBytes": 65415080,
"domNodes": -283,
"jsHeapTotalBytes": 4227072,
"scriptDurationMs": 425.342,
"eventListeners": -149,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3213.203999999962,
"styleRecalcs": 65,
"styleRecalcDurationMs": 13.484,
"layouts": 60,
"layoutDurationMs": 6.863,
"taskDurationMs": 1449.1900000000003,
"heapDeltaBytes": -1700880,
"heapUsedBytes": 60401504,
"domNodes": -288,
"jsHeapTotalBytes": 7180288,
"scriptDurationMs": 519.4230000000001,
"eventListeners": -153,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-zoom",
"durationMs": 3196.8200000000024,
"styleRecalcs": 66,
"styleRecalcDurationMs": 14.225000000000001,
"layouts": 60,
"layoutDurationMs": 6.983000000000001,
"taskDurationMs": 1465.23,
"heapDeltaBytes": -2103032,
"heapUsedBytes": 60015100,
"domNodes": -285,
"jsHeapTotalBytes": 6656000,
"scriptDurationMs": 523.737,
"eventListeners": -153,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "minimap-idle",
"durationMs": 2054.508999999996,
"styleRecalcs": 8,
"styleRecalcDurationMs": 6.432,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 656.0970000000002,
"heapDeltaBytes": 7291016,
"heapUsedBytes": 67825704,
"domNodes": -284,
"jsHeapTotalBytes": 4034560,
"scriptDurationMs": 101.89600000000002,
"eventListeners": -181,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "minimap-idle",
"durationMs": 2034.618999999907,
"styleRecalcs": 9,
"styleRecalcDurationMs": 7.244999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 658.9639999999999,
"heapDeltaBytes": 6953692,
"heapUsedBytes": 67815020,
"domNodes": -283,
"jsHeapTotalBytes": 3248128,
"scriptDurationMs": 101.855,
"eventListeners": -149,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 586.3800000000197,
"styleRecalcs": 47,
"styleRecalcDurationMs": 9.615,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 397.684,
"heapDeltaBytes": -10587184,
"heapUsedBytes": 53820096,
"domNodes": 20,
"jsHeapTotalBytes": 26214400,
"scriptDurationMs": 119.67800000000001,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 595.6469999999854,
"styleRecalcs": 46,
"styleRecalcDurationMs": 8.922,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 399.72300000000007,
"heapDeltaBytes": -10597908,
"heapUsedBytes": 53886208,
"domNodes": 18,
"jsHeapTotalBytes": 25427968,
"scriptDurationMs": 123.149,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "subgraph-idle",
"durationMs": 1998.6210000000142,
"styleRecalcs": 9,
"styleRecalcDurationMs": 7.798999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 442.154,
"heapDeltaBytes": 5853356,
"heapUsedBytes": 70558636,
"domNodes": 18,
"jsHeapTotalBytes": 24641536,
"scriptDurationMs": 12.604,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 2003.0659999999898,
"styleRecalcs": 10,
"styleRecalcDurationMs": 7.4990000000000006,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 448.74100000000004,
"heapDeltaBytes": 5881356,
"heapUsedBytes": 70549004,
"domNodes": 20,
"jsHeapTotalBytes": 24641536,
"scriptDurationMs": 12.446,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1757.470000000012,
"styleRecalcs": 77,
"styleRecalcDurationMs": 35.638999999999996,
"layouts": 16,
"layoutDurationMs": 4.648999999999999,
"taskDurationMs": 802.165,
"heapDeltaBytes": -15567356,
"heapUsedBytes": 48815008,
"domNodes": -279,
"jsHeapTotalBytes": 22781952,
"scriptDurationMs": 86.639,
"eventListeners": -153,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1728.2340000000431,
"styleRecalcs": 76,
"styleRecalcDurationMs": 33.702000000000005,
"layouts": 16,
"layoutDurationMs": 3.5399999999999996,
"taskDurationMs": 716.4939999999999,
"heapDeltaBytes": -3440420,
"heapUsedBytes": 61129820,
"domNodes": 64,
"jsHeapTotalBytes": 25165824,
"scriptDurationMs": 83.172,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-transition-enter",
"durationMs": 1389.1050000000291,
"styleRecalcs": 18,
"styleRecalcDurationMs": 29.56099999999999,
"layouts": 14,
"layoutDurationMs": 12.482,
"taskDurationMs": 901.3749999999998,
"heapDeltaBytes": 32859432,
"heapUsedBytes": 99120016,
"domNodes": 13673,
"jsHeapTotalBytes": 12845056,
"scriptDurationMs": 31.68399999999999,
"eventListeners": 2375,
"totalBlockingTimeMs": 131,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "viewport-pan-sweep",
"durationMs": 8199.320999999998,
"styleRecalcs": 250,
"styleRecalcDurationMs": 33.153,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 4296.7339999999995,
"heapDeltaBytes": 11705552,
"heapUsedBytes": 71190076,
"domNodes": -283,
"jsHeapTotalBytes": 5275648,
"scriptDurationMs": 1349.1850000000002,
"eventListeners": -133,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.80000000000109
},
{
"name": "viewport-pan-sweep",
"durationMs": 8222.850999999991,
"styleRecalcs": 249,
"styleRecalcDurationMs": 33.340999999999994,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 4294.2970000000005,
"heapDeltaBytes": 11490232,
"heapUsedBytes": 71495320,
"domNodes": -282,
"jsHeapTotalBytes": 6324224,
"scriptDurationMs": 1337.966,
"eventListeners": -133,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-idle",
"durationMs": 15586.381999999958,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 15568.141,
"heapDeltaBytes": -36965884,
"heapUsedBytes": 167281728,
"domNodes": -8312,
"jsHeapTotalBytes": -9379840,
"scriptDurationMs": 526.91,
"eventListeners": -16385,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.780000000000047,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 15770.125000000007,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 15734.141999999998,
"heapDeltaBytes": -34680884,
"heapUsedBytes": 170717020,
"domNodes": -8312,
"jsHeapTotalBytes": -2826240,
"scriptDurationMs": 544.5649999999999,
"eventListeners": -16387,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.776666666666763,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-pan",
"durationMs": 19859.359999999982,
"styleRecalcs": 136,
"styleRecalcDurationMs": 14.604000000000006,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 19824.755000000005,
"heapDeltaBytes": -38534236,
"heapUsedBytes": 169332652,
"domNodes": -8312,
"jsHeapTotalBytes": -9379840,
"scriptDurationMs": 861.3860000000001,
"eventListeners": -16385,
"totalBlockingTimeMs": 47,
"frameDurationMs": 18.333333333333332,
"p95FrameDurationMs": 16.80000000000291
},
{
"name": "vue-large-graph-pan",
"durationMs": 19630.09999999997,
"styleRecalcs": 133,
"styleRecalcDurationMs": 13.820000000000027,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 19584.307000000004,
"heapDeltaBytes": -42139040,
"heapUsedBytes": 154517936,
"domNodes": -8312,
"jsHeapTotalBytes": -9641984,
"scriptDurationMs": 876.8480000000001,
"eventListeners": -16385,
"totalBlockingTimeMs": 68,
"frameDurationMs": 17.776666666666642,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 98.12399999998433,
"styleRecalcs": 7,
"styleRecalcDurationMs": 13.232000000000001,
"layouts": 2,
"layoutDurationMs": 0.5690000000000001,
"taskDurationMs": 75.95200000000001,
"heapDeltaBytes": 3109880,
"heapUsedBytes": 66573048,
"domNodes": 108,
"jsHeapTotalBytes": 2883584,
"scriptDurationMs": 8.553999999999998,
"eventListeners": 49,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.663333333333338,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "workflow-execution",
"durationMs": 470.32900000010613,
"styleRecalcs": 12,
"styleRecalcDurationMs": 19.701999999999998,
"layouts": 3,
"layoutDurationMs": 0.5720000000000001,
"taskDurationMs": 104.56599999999999,
"heapDeltaBytes": 5054692,
"heapUsedBytes": 68657928,
"domNodes": 121,
"jsHeapTotalBytes": 4718592,
"scriptDurationMs": 8.664000000000001,
"eventListeners": 97,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
}
]
}🎭 Playwright: ✅ 1795 passed, 0 failed · 4 flaky📊 Browser Reports
|
🎭 Playwright: ⏳ Running... |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/platform/cloud/onboarding/CloudSubscriptionRedirectView.vue`:
- Around line 143-154: Update runRedirect in CloudSubscriptionRedirectView.vue
to catch fetchPlans() failures during Team deep-link handling; when plan data
remains unavailable, call showPricingTable with the generic Team configuration
instead of allowing the rejection to abort redirect processing. Preserve the
existing initialCheckout flow when plans load successfully, and add a regression
test covering a rejected fetchPlans() call.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 8e126d8d-5c3d-4b4c-a47e-5f78fb9be186
📒 Files selected for processing (4)
src/platform/cloud/onboarding/CloudSubscriptionRedirectView.test.tssrc/platform/cloud/onboarding/CloudSubscriptionRedirectView.vuesrc/platform/cloud/onboarding/onboardingCloudRoutes.tssrc/platform/cloud/subscription/composables/usePricingTableUrlLoader.ts
| if (!teamCreditStops.value) await fetchPlans() | ||
| const initialCheckout = getPricingCheckoutSelection( | ||
| tierKeyParam, | ||
| stopId, | ||
| billingCycle, | ||
| teamCreditStops.value | ||
| ) | ||
| showPricingTable({ | ||
| reason: 'deep_link', | ||
| planMode: 'team', | ||
| initialCheckout | ||
| }) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Handle Team plan-load failures before opening checkout.
If fetchPlans() rejects, runRedirect exits before it calls
showPricingTable. The Team deep link then cannot continue to a pricing flow.
Catch this failure and open the generic Team pricing table when plan data remains
unavailable. Add a regression test where fetchPlans() rejects.
This differs from
src/platform/cloud/subscription/composables/usePricingTableUrlLoader.ts Lines
148-164, which catches this failure and opens the generic Team table.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/platform/cloud/onboarding/CloudSubscriptionRedirectView.vue` around lines
143 - 154, Update runRedirect in CloudSubscriptionRedirectView.vue to catch
fetchPlans() failures during Team deep-link handling; when plan data remains
unavailable, call showPricingTable with the generic Team configuration instead
of allowing the rejection to abort redirect processing. Preserve the existing
initialCheckout flow when plans load successfully, and add a regression test
covering a rejected fetchPlans() call.
Codecov Report❌ Patch coverage is
@@ Coverage Diff @@
## main #14998 +/- ##
========================================
Coverage 81.27% 81.28%
========================================
Files 1872 1872
Lines 106335 106353 +18
Branches 32301 32721 +420
========================================
+ Hits 86425 86449 +24
+ Misses 19564 19548 -16
- Partials 346 356 +10
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 16 files with indirect coverage changes 🚀 New features to boost your workflow:
|
Summary
Route
/cloud/subscribethrough workspace initialization and the canonical billing facade. Personal and Team selections now enter the unified pricing checkout, while active subscriptions use facade-owned subscription management.Root cause
The deep-link view directly chose backend/API families instead of using server/workspace-derived facade routing:
/customers/cloud-subscription-checkout.workspaceApi.subscribedirectly./customers/billingdirectly.This let a selected Team workspace invoke user-scoped legacy APIs from a personal-tier link and duplicated checkout ownership outside
useBillingContext/useSubscriptionCheckout.Why this change is needed
Checkout routing must be independent from legacy account-operation routing. The active workspace and billing rail are the source of truth, while
useSubscriptionCheckoutowns plan resolution, preview/reactivation confirmation, permissions, billing operation tracking, payment actions, telemetry, and terminal outcomes.AS IS / TO BE
AS IS
flowchart TD A[cloud/subscribe deep link] --> B{Tier query} B -->|Personal| C[performSubscriptionCheckout] C --> D[Legacy customers checkout API] B -->|Team| E[performTeamSubscriptionCheckout] E --> F[Workspace subscribe API] A -->|Active subscription| G[accessBillingPortal] G --> H[Legacy customers billing API]TO BE
API behavior
useSubscriptionDialog→useSubscriptionCheckout→useBillingContextcheckout context/api/billing/*)/api/billing/*)useBillingContext.manageSubscription()legacy_stripeaccount operations/customers/*APIs; checkout remains workspace-backedRegression coverage and validation
performSubscriptionCheckout.performTeamSubscriptionCheckout.manageSubscription, not directaccessBillingPortal./cloud/subscribenow mounts throughLayoutDefault/WorkspaceAuthGateso facade routing sees the restored active workspace.Validation:
pnpm test:unit src/platform/cloud/onboarding/CloudSubscriptionRedirectView.test.ts src/platform/cloud/subscription/composables/usePricingTableUrlLoader.test.ts— 49 passedpnpm typecheck— passedoxfmt, ESLint, Stylelint, Oxlint, and pre-pushknip— passedResidual intentional legacy callers remain in legacy pricing and
legacy_striperesubscribe/pending-checkout recovery. They are outside this redirect migration and are retained intentionally.Screenshots
No intentional visual change. The redirect loading surface and unified checkout UI are existing components, so screenshots are not applicable.