[backport core/1.47] fix(workspace): show subscribe prompt for ended subscriptions - #14509
Conversation
- Treat `subscription_status: ended` as terminal even when `is_active`
and paid-plan metadata lag behind.
- Show the subscribe prompt instead of a stale Standard plan.
- Keep cloud billing mocks internally consistent and add component and
end-to-end regression coverage.
The subscription panel required `ended` **and** `is_active=false`. When
the terminal status arrived first, stale active/plan data suppressed the
subscribe prompt.
```mermaid
flowchart LR
subgraph BEFORE[Before]
direction TB
B1[Billing state loads] --> B2{"ended AND is_active=false?"}
B2 -- Yes --> B3[Show subscribe prompt]
B2 -- "No: ended + stale active" --> B4[Show stale Standard plan]
end
subgraph AFTER[After]
direction TB
A1[Billing state loads] --> A2{"subscription_status = ended?"}
A2 -- Yes --> A3[Show subscribe prompt]
A2 -- No --> A4{"Active paid plan?"}
A4 -- Yes --> A5[Show current plan]
A4 -- No --> A3
end
```
- `SubscriptionPanelContentWorkspace.vue`: ended status now takes
precedence over stale paid-plan guards.
- `CloudWorkspaceMockHelper.ts`: `current_plan_slug` always has a
matching plan.
- Tests retain stale active/paid/team-plan state so the regression
specifically verifies ended-status precedence.
- Component tests: 42 passed
- Cloud Playwright regression: 1 passed
- App and browser typechecks
- Formatting, lint, commit hooks, and `knip`
🎨 Storybook: ✅ Built — View Storybook🎭 Playwright: ✅ 1705 passed, 0 failed · 4 flaky📊 Browser Reports
📦 Bundle Size
⚡ Performance Report
Show regressions
All metrics
Historical variance (last 15 runs)
Trend (last 15 commits on main)
Raw data{
"timestamp": "2026-07-31T22:26:44.588Z",
"gitSha": "14daf66f8ae592813869df6de7416a2fcd860091",
"branch": "backport-14504-to-core-1.47",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2022.5560000000087,
"styleRecalcs": 9,
"styleRecalcDurationMs": 7.204999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 458.12500000000006,
"heapDeltaBytes": -1251352,
"heapUsedBytes": 57937992,
"domNodes": 18,
"jsHeapTotalBytes": 24641536,
"scriptDurationMs": 17.197999999999997,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-idle",
"durationMs": 2022.689000000014,
"styleRecalcs": 10,
"styleRecalcDurationMs": 8.374999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 463.977,
"heapDeltaBytes": -1510684,
"heapUsedBytes": 57637540,
"domNodes": 20,
"jsHeapTotalBytes": 25427968,
"scriptDurationMs": 16.136,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-mouse-sweep",
"durationMs": 2033.1879999999956,
"styleRecalcs": 77,
"styleRecalcDurationMs": 42.399,
"layouts": 12,
"layoutDurationMs": 3.795,
"taskDurationMs": 972.2080000000001,
"heapDeltaBytes": -5813152,
"heapUsedBytes": 53371336,
"domNodes": 59,
"jsHeapTotalBytes": 25165824,
"scriptDurationMs": 126.51099999999998,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1824.6199999999817,
"styleRecalcs": 73,
"styleRecalcDurationMs": 33.089,
"layouts": 12,
"layoutDurationMs": 3.347,
"taskDurationMs": 801.3009999999999,
"heapDeltaBytes": -5828116,
"heapUsedBytes": 53698816,
"domNodes": 55,
"jsHeapTotalBytes": 24903680,
"scriptDurationMs": 113.44100000000002,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1729.1900000000169,
"styleRecalcs": 32,
"styleRecalcDurationMs": 15.866999999999999,
"layouts": 6,
"layoutDurationMs": 0.715,
"taskDurationMs": 374.042,
"heapDeltaBytes": 2528060,
"heapUsedBytes": 61663264,
"domNodes": 78,
"jsHeapTotalBytes": 24641536,
"scriptDurationMs": 18.772,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1725.787999999966,
"styleRecalcs": 30,
"styleRecalcDurationMs": 15.892999999999997,
"layouts": 6,
"layoutDurationMs": 0.6350000000000001,
"taskDurationMs": 364.19800000000004,
"heapDeltaBytes": 2480872,
"heapUsedBytes": 61667808,
"domNodes": 76,
"jsHeapTotalBytes": 24379392,
"scriptDurationMs": 18.156000000000006,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "dom-widget-clipping",
"durationMs": 615.3329999999642,
"styleRecalcs": 10,
"styleRecalcDurationMs": 6.771000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 373.41,
"heapDeltaBytes": 8351060,
"heapUsedBytes": 67541452,
"domNodes": 16,
"jsHeapTotalBytes": 19398656,
"scriptDurationMs": 58.186,
"eventListeners": 2,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "dom-widget-clipping",
"durationMs": 578.5129999999867,
"styleRecalcs": 11,
"styleRecalcDurationMs": 6.9769999999999985,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 361.893,
"heapDeltaBytes": 8324760,
"heapUsedBytes": 67498600,
"domNodes": 18,
"jsHeapTotalBytes": 19136512,
"scriptDurationMs": 55.55799999999999,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-idle",
"durationMs": 2025.6149999999593,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.593,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 712.3340000000001,
"heapDeltaBytes": -6728324,
"heapUsedBytes": 66470244,
"domNodes": 18,
"jsHeapTotalBytes": 8269824,
"scriptDurationMs": 122.28800000000001,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-idle",
"durationMs": 2040.4439999999795,
"styleRecalcs": 10,
"styleRecalcDurationMs": 7.910999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 641.3050000000001,
"heapDeltaBytes": -6922164,
"heapUsedBytes": 66493344,
"domNodes": 20,
"jsHeapTotalBytes": 6959104,
"scriptDurationMs": 97.626,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-pan",
"durationMs": 2143.709000000001,
"styleRecalcs": 69,
"styleRecalcDurationMs": 20.288999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1211.7169999999999,
"heapDeltaBytes": -10305660,
"heapUsedBytes": 64128192,
"domNodes": 18,
"jsHeapTotalBytes": 9756672,
"scriptDurationMs": 416.53799999999995,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-pan",
"durationMs": 2088.549999999941,
"styleRecalcs": 69,
"styleRecalcDurationMs": 19.307,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1162.569,
"heapDeltaBytes": 11657360,
"heapUsedBytes": 66858268,
"domNodes": 16,
"jsHeapTotalBytes": 5419008,
"scriptDurationMs": 408.298,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3171.401000000003,
"styleRecalcs": 65,
"styleRecalcDurationMs": 20.192999999999998,
"layouts": 60,
"layoutDurationMs": 8.427999999999999,
"taskDurationMs": 1495.5310000000002,
"heapDeltaBytes": 20151612,
"heapUsedBytes": 76743652,
"domNodes": 12,
"jsHeapTotalBytes": 6291456,
"scriptDurationMs": 534.446,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-zoom",
"durationMs": 3154.1850000000977,
"styleRecalcs": 64,
"styleRecalcDurationMs": 18.775,
"layouts": 60,
"layoutDurationMs": 8.194999999999999,
"taskDurationMs": 1480.226,
"heapDeltaBytes": 22612568,
"heapUsedBytes": 79339688,
"domNodes": 10,
"jsHeapTotalBytes": 6553600,
"scriptDurationMs": 552.1089999999999,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 1993.9149999999586,
"styleRecalcs": 7,
"styleRecalcDurationMs": 6.492000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 604.076,
"heapDeltaBytes": 12559724,
"heapUsedBytes": 68430964,
"domNodes": 14,
"jsHeapTotalBytes": 4456448,
"scriptDurationMs": 90.418,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "minimap-idle",
"durationMs": 2005.961999999954,
"styleRecalcs": 9,
"styleRecalcDurationMs": 7.509000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 610.5829999999999,
"heapDeltaBytes": 12599228,
"heapUsedBytes": 68812440,
"domNodes": 18,
"jsHeapTotalBytes": 4980736,
"scriptDurationMs": 91.203,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 592.9530000000227,
"styleRecalcs": 47,
"styleRecalcDurationMs": 11.046,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 388.974,
"heapDeltaBytes": 8985572,
"heapUsedBytes": 68253812,
"domNodes": 20,
"jsHeapTotalBytes": 20447232,
"scriptDurationMs": 122.17199999999998,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 565.4550000000427,
"styleRecalcs": 47,
"styleRecalcDurationMs": 11.076999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 389.546,
"heapDeltaBytes": 7767416,
"heapUsedBytes": 67003652,
"domNodes": 20,
"jsHeapTotalBytes": 19922944,
"scriptDurationMs": 124.454,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 1999.112000000025,
"styleRecalcs": 11,
"styleRecalcDurationMs": 8.806,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 456.507,
"heapDeltaBytes": -1398492,
"heapUsedBytes": 57829776,
"domNodes": 22,
"jsHeapTotalBytes": 25427968,
"scriptDurationMs": 13.054000000000002,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 1997.8689999999801,
"styleRecalcs": 10,
"styleRecalcDurationMs": 7.882999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 438.46500000000003,
"heapDeltaBytes": -1346944,
"heapUsedBytes": 58075076,
"domNodes": 20,
"jsHeapTotalBytes": 24379392,
"scriptDurationMs": 12.785,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1680.4329999999936,
"styleRecalcs": 76,
"styleRecalcDurationMs": 35.626,
"layouts": 16,
"layoutDurationMs": 4.001,
"taskDurationMs": 733.4920000000001,
"heapDeltaBytes": -9746900,
"heapUsedBytes": 49496320,
"domNodes": 64,
"jsHeapTotalBytes": 24641536,
"scriptDurationMs": 89.316,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1689.149000000043,
"styleRecalcs": 75,
"styleRecalcDurationMs": 34.329,
"layouts": 16,
"layoutDurationMs": 3.7950000000000004,
"taskDurationMs": 715.4430000000001,
"heapDeltaBytes": -9718144,
"heapUsedBytes": 49516248,
"domNodes": 63,
"jsHeapTotalBytes": 24379392,
"scriptDurationMs": 87.791,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "subgraph-transition-enter",
"durationMs": 1400.9560000000079,
"styleRecalcs": 18,
"styleRecalcDurationMs": 30.872999999999998,
"layouts": 14,
"layoutDurationMs": 13.860000000000001,
"taskDurationMs": 928.5150000000002,
"heapDeltaBytes": 4547716,
"heapUsedBytes": 81454904,
"domNodes": 13673,
"jsHeapTotalBytes": 16515072,
"scriptDurationMs": 32.903,
"eventListeners": 2533,
"totalBlockingTimeMs": 145,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8219.700999999986,
"styleRecalcs": 252,
"styleRecalcDurationMs": 60.932,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 4358.095,
"heapDeltaBytes": -10569468,
"heapUsedBytes": 62375508,
"domNodes": 24,
"jsHeapTotalBytes": 14299136,
"scriptDurationMs": 1385.454,
"eventListeners": 20,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "viewport-pan-sweep",
"durationMs": 8181.724999999915,
"styleRecalcs": 251,
"styleRecalcDurationMs": 64.993,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 4462.304999999999,
"heapDeltaBytes": -5692144,
"heapUsedBytes": 67583136,
"domNodes": 20,
"jsHeapTotalBytes": 19279872,
"scriptDurationMs": 1492.7489999999998,
"eventListeners": 20,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 17771.41499999999,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 17741.034,
"heapDeltaBytes": -34175876,
"heapUsedBytes": 166854372,
"domNodes": -3310,
"jsHeapTotalBytes": 16224256,
"scriptDurationMs": 527.28,
"eventListeners": -16375,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.776666666666642,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 18157.117000000086,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 18121.875,
"heapDeltaBytes": -21638056,
"heapUsedBytes": 180781272,
"domNodes": -3310,
"jsHeapTotalBytes": 15962112,
"scriptDurationMs": 548.776,
"eventListeners": -16379,
"totalBlockingTimeMs": 0,
"frameDurationMs": 18.333333333333332,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 21889.526999999987,
"styleRecalcs": 159,
"styleRecalcDurationMs": 28.816999999999982,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 21859.26,
"heapDeltaBytes": -20784644,
"heapUsedBytes": 168893388,
"domNodes": -3342,
"jsHeapTotalBytes": 16486400,
"scriptDurationMs": 829.36,
"eventListeners": -16371,
"totalBlockingTimeMs": 527,
"frameDurationMs": 18.33666666666662,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-pan",
"durationMs": 22659.441000000013,
"styleRecalcs": 176,
"styleRecalcDurationMs": 31.96399999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 22619.338,
"heapDeltaBytes": -43727016,
"heapUsedBytes": 155377740,
"domNodes": -3310,
"jsHeapTotalBytes": 16486400,
"scriptDurationMs": 858.512,
"eventListeners": -16367,
"totalBlockingTimeMs": 660,
"frameDurationMs": 17.77333333333336,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 444.95399999999563,
"styleRecalcs": 13,
"styleRecalcDurationMs": 16.119,
"layouts": 3,
"layoutDurationMs": 0.6100000000000001,
"taskDurationMs": 100.16400000000002,
"heapDeltaBytes": 5082732,
"heapUsedBytes": 63382072,
"domNodes": 130,
"jsHeapTotalBytes": 1572864,
"scriptDurationMs": 8.982999999999999,
"eventListeners": 65,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666682,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "workflow-execution",
"durationMs": 105.96399999997175,
"styleRecalcs": 8,
"styleRecalcDurationMs": 12.951999999999998,
"layouts": 1,
"layoutDurationMs": 0.662,
"taskDurationMs": 68.848,
"heapDeltaBytes": 3025856,
"heapUsedBytes": 61308960,
"domNodes": 127,
"jsHeapTotalBytes": 0,
"scriptDurationMs": 4.873999999999998,
"eventListeners": 17,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000273
}
]
} |
|
Important Review skippedIgnore keyword(s) in the title. ⛔ Ignored keywords (2)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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 |
📄 Knowledge reviewDosu skipped reviewing this PR because your organization has used its |
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## core/1.47 #14509 +/- ##
===========================================
Coverage 78.27% 78.27%
===========================================
Files 1667 1667
Lines 93136 93137 +1
Branches 32245 32918 +673
===========================================
+ Hits 72903 72904 +1
Misses 19628 19628
Partials 605 605
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Summary
Backport of #14504 to
core/1.47.subscription_status: endedas terminal even when paid-plan metadata is stale.Validation
knippush hook