feat(billing): unify billing and invoice portal action - #14608
Conversation
📄 Knowledge reviewDosu skipped reviewing this PR because your organization has used its |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughCloud subscription controls now use “Billing & invoices” with permission- and distribution-aware rendering. Non-cloud deployments retain Invoice history behavior. Tests cover cloud, local, permission, and subscription-state variations. ChangesSubscription billing actions
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
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🎭 Playwright: ✅ 1787 passed, 0 failed · 2 flaky📊 Browser Reports
📦 Bundle: 8.25 MB gzip 🔴 +35 BDetailsSummary
Category Glance App Entry Points — 3.64 kB (baseline 3.64 kB) • ⚪ 0 BMain entry bundles and manifests
Status: 1 added / 1 removed Graph Workspace — 1.35 MB (baseline 1.35 MB) • ⚪ 0 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed / 1 unchanged Views & Navigation — 112 kB (baseline 112 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 13 added / 13 removed / 4 unchanged Panels & Settings — 551 kB (baseline 551 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 11 added / 11 removed / 15 unchanged User & Accounts — 27 kB (baseline 27 kB) • ⚪ 0 BAuthentication, profile, and account management bundles
Status: 6 added / 6 removed / 4 unchanged Editors & Dialogs — 124 kB (baseline 124 kB) • ⚪ 0 BModals, dialogs, drawers, and in-app editors
Status: 6 added / 6 removed / 1 unchanged UI Components — 71.1 kB (baseline 71.1 kB) • ⚪ 0 BReusable component library chunks
Status: 6 added / 6 removed / 9 unchanged Data & Services — 3.48 MB (baseline 3.48 MB) • ⚪ 0 BStores, services, APIs, and repositories
Status: 14 added / 14 removed / 3 unchanged Utilities & Hooks — 386 kB (baseline 386 kB) • ⚪ 0 BHelpers, composables, and utility bundles
Status: 16 added / 16 removed / 20 unchanged Vendor & Third-Party — 15.7 MB (baseline 15.7 MB) • ⚪ 0 BExternal libraries and shared vendor chunks Status: 16 unchanged Other — 12.8 MB (baseline 12.8 MB) • 🔴 +850 BBundles that do not match a named category
Status: 70 added / 70 removed / 211 unchanged ⚡ Performance Report
Show regressions
All metrics
Historical variance (last 15 runs)
Trend (last 15 commits on main)
Raw data{
"timestamp": "2026-08-05T00:11:06.710Z",
"gitSha": "b9c86c96060149c45e5ce22c208cf45e57b7a802",
"branch": "jaewon/fe-1452-billing-invoices",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2038.64200000001,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.076,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 570.077,
"heapDeltaBytes": 5739640,
"heapUsedBytes": 69818752,
"domNodes": 18,
"jsHeapTotalBytes": 24903680,
"scriptDurationMs": 24.365,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "canvas-idle",
"durationMs": 2015.2229999999918,
"styleRecalcs": 9,
"styleRecalcDurationMs": 7.5440000000000005,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 466.059,
"heapDeltaBytes": 5326844,
"heapUsedBytes": 69349224,
"domNodes": 18,
"jsHeapTotalBytes": 25165824,
"scriptDurationMs": 18.009,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1913.0930000000035,
"styleRecalcs": 79,
"styleRecalcDurationMs": 43.641,
"layouts": 12,
"layoutDurationMs": 4.629,
"taskDurationMs": 919.1100000000001,
"heapDeltaBytes": -215272,
"heapUsedBytes": 63788628,
"domNodes": 63,
"jsHeapTotalBytes": 26214400,
"scriptDurationMs": 132.855,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1891.379000000029,
"styleRecalcs": 76,
"styleRecalcDurationMs": 41.355999999999995,
"layouts": 12,
"layoutDurationMs": 3.913,
"taskDurationMs": 907.8,
"heapDeltaBytes": -13503408,
"heapUsedBytes": 50590224,
"domNodes": -281,
"jsHeapTotalBytes": 25145344,
"scriptDurationMs": 123.40700000000001,
"eventListeners": -153,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1739.8410000000126,
"styleRecalcs": 31,
"styleRecalcDurationMs": 17.172,
"layouts": 6,
"layoutDurationMs": 0.6330000000000001,
"taskDurationMs": 424.165,
"heapDeltaBytes": 8722060,
"heapUsedBytes": 72947288,
"domNodes": 77,
"jsHeapTotalBytes": 24117248,
"scriptDurationMs": 23.093000000000004,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1742.0769999999948,
"styleRecalcs": 30,
"styleRecalcDurationMs": 17.401,
"layouts": 6,
"layoutDurationMs": 0.697,
"taskDurationMs": 387.0330000000001,
"heapDeltaBytes": 8706844,
"heapUsedBytes": 72753852,
"domNodes": 76,
"jsHeapTotalBytes": 24641536,
"scriptDurationMs": 21.149,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "dom-widget-clipping",
"durationMs": 595.5359999999814,
"styleRecalcs": 12,
"styleRecalcDurationMs": 8.629,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 383.592,
"heapDeltaBytes": -10921964,
"heapUsedBytes": 53018696,
"domNodes": 20,
"jsHeapTotalBytes": 25690112,
"scriptDurationMs": 59.686,
"eventListeners": 2,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "dom-widget-clipping",
"durationMs": 594.7259999999233,
"styleRecalcs": 11,
"styleRecalcDurationMs": 8.354,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 391.096,
"heapDeltaBytes": -10942800,
"heapUsedBytes": 52988076,
"domNodes": 18,
"jsHeapTotalBytes": 25690112,
"scriptDurationMs": 58.753,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-idle",
"durationMs": 2027.5440000000344,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.966000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 732.5959999999999,
"heapDeltaBytes": 7179460,
"heapUsedBytes": 66625812,
"domNodes": -285,
"jsHeapTotalBytes": 3252224,
"scriptDurationMs": 119.79299999999999,
"eventListeners": -149,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-idle",
"durationMs": 2042.7809999999909,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.615,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 704.2080000000001,
"heapDeltaBytes": 6829252,
"heapUsedBytes": 66223512,
"domNodes": -283,
"jsHeapTotalBytes": 2465792,
"scriptDurationMs": 114.49600000000001,
"eventListeners": -149,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2157.348999999954,
"styleRecalcs": 68,
"styleRecalcDurationMs": 13.470999999999997,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1357.702,
"heapDeltaBytes": 19421208,
"heapUsedBytes": 79998376,
"domNodes": -285,
"jsHeapTotalBytes": 4231168,
"scriptDurationMs": 451.12,
"eventListeners": -179,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-pan",
"durationMs": 2221.0939999999937,
"styleRecalcs": 69,
"styleRecalcDurationMs": 17.562,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1325.019,
"heapDeltaBytes": 4546744,
"heapUsedBytes": 64834708,
"domNodes": -283,
"jsHeapTotalBytes": 3969024,
"scriptDurationMs": 438.817,
"eventListeners": -149,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-zoom",
"durationMs": 3295.901000000015,
"styleRecalcs": 64,
"styleRecalcDurationMs": 14.975999999999996,
"layouts": 60,
"layoutDurationMs": 7.825,
"taskDurationMs": 1610.408,
"heapDeltaBytes": 2077332,
"heapUsedBytes": 64428488,
"domNodes": -289,
"jsHeapTotalBytes": 6397952,
"scriptDurationMs": 586.9799999999999,
"eventListeners": -183,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3195.7720000000336,
"styleRecalcs": 65,
"styleRecalcDurationMs": 14.796,
"layouts": 60,
"layoutDurationMs": 7.645,
"taskDurationMs": 1507.222,
"heapDeltaBytes": 23247024,
"heapUsedBytes": 85407484,
"domNodes": 12,
"jsHeapTotalBytes": 6815744,
"scriptDurationMs": 540.4689999999999,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2074.273000000005,
"styleRecalcs": 7,
"styleRecalcDurationMs": 6.1690000000000005,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 744.1359999999999,
"heapDeltaBytes": 7210736,
"heapUsedBytes": 67810544,
"domNodes": -286,
"jsHeapTotalBytes": 2727936,
"scriptDurationMs": 125.71799999999999,
"eventListeners": -151,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "minimap-idle",
"durationMs": 2026.1079999999083,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.356000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 687.365,
"heapDeltaBytes": 7216704,
"heapUsedBytes": 68060932,
"domNodes": -285,
"jsHeapTotalBytes": 2465792,
"scriptDurationMs": 111.74399999999999,
"eventListeners": -149,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 594.9469999999906,
"styleRecalcs": 47,
"styleRecalcDurationMs": 12.042,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 403.635,
"heapDeltaBytes": -10489244,
"heapUsedBytes": 53777344,
"domNodes": 20,
"jsHeapTotalBytes": 25690112,
"scriptDurationMs": 121.53,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 605.4850000000442,
"styleRecalcs": 46,
"styleRecalcDurationMs": 10.559000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 409.151,
"heapDeltaBytes": -10472480,
"heapUsedBytes": 53671400,
"domNodes": 18,
"jsHeapTotalBytes": 26214400,
"scriptDurationMs": 122.57500000000002,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-idle",
"durationMs": 2001.5650000000278,
"styleRecalcs": 10,
"styleRecalcDurationMs": 9.194,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 499.851,
"heapDeltaBytes": 5071960,
"heapUsedBytes": 69156484,
"domNodes": 20,
"jsHeapTotalBytes": 25427968,
"scriptDurationMs": 16.723,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66999999999998,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "subgraph-idle",
"durationMs": 2012.7619999999524,
"styleRecalcs": 10,
"styleRecalcDurationMs": 9.434000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 473.522,
"heapDeltaBytes": 5406200,
"heapUsedBytes": 69589836,
"domNodes": 20,
"jsHeapTotalBytes": 24903680,
"scriptDurationMs": 15.767,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1696.6099999999642,
"styleRecalcs": 76,
"styleRecalcDurationMs": 36.587,
"layouts": 16,
"layoutDurationMs": 3.8160000000000003,
"taskDurationMs": 797.4140000000001,
"heapDeltaBytes": -4226504,
"heapUsedBytes": 59852756,
"domNodes": 64,
"jsHeapTotalBytes": 25427968,
"scriptDurationMs": 92.66099999999999,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1709.920000000011,
"styleRecalcs": 76,
"styleRecalcDurationMs": 34.596000000000004,
"layouts": 16,
"layoutDurationMs": 4.175,
"taskDurationMs": 823.67,
"heapDeltaBytes": -17289728,
"heapUsedBytes": 46822284,
"domNodes": -279,
"jsHeapTotalBytes": 23048192,
"scriptDurationMs": 94.284,
"eventListeners": -153,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-transition-enter",
"durationMs": 1435.0090000000364,
"styleRecalcs": 18,
"styleRecalcDurationMs": 31.631999999999994,
"layouts": 14,
"layoutDurationMs": 12.318,
"taskDurationMs": 980.118,
"heapDeltaBytes": 31084904,
"heapUsedBytes": 99697248,
"domNodes": 13673,
"jsHeapTotalBytes": 15466496,
"scriptDurationMs": 38.824,
"eventListeners": 2375,
"totalBlockingTimeMs": 145,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8537.214000000005,
"styleRecalcs": 250,
"styleRecalcDurationMs": 38.26599999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 4718.407999999999,
"heapDeltaBytes": 11863792,
"heapUsedBytes": 71107196,
"domNodes": -281,
"jsHeapTotalBytes": 5279744,
"scriptDurationMs": 1443.445,
"eventListeners": -131,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8353.53299999997,
"styleRecalcs": 251,
"styleRecalcDurationMs": 38.209999999999994,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 4622.603,
"heapDeltaBytes": 6417460,
"heapUsedBytes": 65143912,
"domNodes": -279,
"jsHeapTotalBytes": 6328320,
"scriptDurationMs": 1407.557,
"eventListeners": -163,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 17276.740999999958,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 17230.769000000004,
"heapDeltaBytes": -58970112,
"heapUsedBytes": 166597648,
"domNodes": -8312,
"jsHeapTotalBytes": -7282688,
"scriptDurationMs": 614.8670000000001,
"eventListeners": -16385,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.779999999999927,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-idle",
"durationMs": 16811.196999999993,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 16791.573,
"heapDeltaBytes": -50300248,
"heapUsedBytes": 175541832,
"domNodes": -8341,
"jsHeapTotalBytes": -9641984,
"scriptDurationMs": 542.778,
"eventListeners": -16385,
"totalBlockingTimeMs": 0,
"frameDurationMs": 18.330000000000048,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 21090.237,
"styleRecalcs": 144,
"styleRecalcDurationMs": 17.68900000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 21023.296000000002,
"heapDeltaBytes": -57572668,
"heapUsedBytes": 164669732,
"domNodes": -8312,
"jsHeapTotalBytes": -8855552,
"scriptDurationMs": 942.217,
"eventListeners": -16379,
"totalBlockingTimeMs": 200,
"frameDurationMs": 18.333333333333332,
"p95FrameDurationMs": 16.80000000000291
},
{
"name": "vue-large-graph-pan",
"durationMs": 20845.654000000082,
"styleRecalcs": 143,
"styleRecalcDurationMs": 17.90900000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 20818.942,
"heapDeltaBytes": -49694128,
"heapUsedBytes": 156079400,
"domNodes": -8312,
"jsHeapTotalBytes": -8065024,
"scriptDurationMs": 905.6500000000001,
"eventListeners": -16383,
"totalBlockingTimeMs": 269,
"frameDurationMs": 17.776666666666642,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 466.67200000001685,
"styleRecalcs": 18,
"styleRecalcDurationMs": 21.961000000000002,
"layouts": 3,
"layoutDurationMs": 1.365,
"taskDurationMs": 125.83,
"heapDeltaBytes": 5433056,
"heapUsedBytes": 68491332,
"domNodes": 158,
"jsHeapTotalBytes": 5242880,
"scriptDurationMs": 10.437999999999999,
"eventListeners": 99,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "workflow-execution",
"durationMs": 458.6419999999407,
"styleRecalcs": 15,
"styleRecalcDurationMs": 22.431,
"layouts": 3,
"layoutDurationMs": 1.063,
"taskDurationMs": 124.12400000000001,
"heapDeltaBytes": 5074384,
"heapUsedBytes": 68293788,
"domNodes": 123,
"jsHeapTotalBytes": 5242880,
"scriptDurationMs": 14.123999999999999,
"eventListeners": 97,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
}
]
} |
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## main #14608 +/- ##
==========================================
- Coverage 78.45% 78.34% -0.12%
==========================================
Files 1794 1793 -1
Lines 106764 109166 +2402
Branches 30634 30245 -389
==========================================
+ Hits 83765 85529 +1764
- Misses 22544 23140 +596
- Partials 455 497 +42
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 209 files with indirect coverage changes 🚀 New features to boost your workflow:
|
c6671e8 to
0f6075f
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/subscription/components/SubscriptionFooterLinks.test.ts`:
- Around line 61-75: Add user-driven interaction coverage to the test around
renderComponent, activating the “Learn more” and “Message support” buttons and
asserting the behavior produced by each action. Exercise the real component
handlers and retain the existing assertions for the rendered footer actions and
absent invoice action.
In `@src/platform/workspace/components/SubscriptionPanelContentWorkspace.vue`:
- Around line 239-245: Update the subscription-state rendering around the
isActiveSubscription branches so ended paid subscriptions remain on the
subscribed template even when is_active is false. Ensure the manager’s
manageSubscription “Billing & invoices” action and related billing/reaction
controls remain visible, while preserving the existing behavior for non-paid or
otherwise unsubscribed workspaces.
🪄 Autofix (Beta)
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: b6f696ae-c418-4ebd-a852-05601b099e6b
📒 Files selected for processing (5)
src/locales/en/main.jsonsrc/platform/cloud/subscription/components/SubscriptionFooterLinks.test.tssrc/platform/cloud/subscription/components/SubscriptionFooterLinks.vuesrc/platform/workspace/components/SubscriptionPanelContentWorkspace.test.tssrc/platform/workspace/components/SubscriptionPanelContentWorkspace.vue
💤 Files with no reviewable changes (2)
- src/locales/en/main.json
- src/platform/cloud/subscription/components/SubscriptionFooterLinks.vue
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/subscription/components/SubscriptionFooterLinks.test.ts`:
- Around line 83-87: Extend the user-event interaction test in
SubscriptionFooterLinks.test.ts to click the “Partner Nodes pricing table”
button and assert that window.open is called with the expected external
navigation target, covering the handleOpenPartnerNodesInfo behavior wired by
SubscriptionFooterLinks.vue.
🪄 Autofix (Beta)
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: aafea13f-6b1e-4642-8a9f-e3203d6398f0
📒 Files selected for processing (2)
src/platform/cloud/subscription/components/SubscriptionFooterLinks.test.tssrc/platform/workspace/components/SubscriptionPanelContentWorkspace.test.ts
|
Current-head UI evidence for a978944 (route-mocked Cloud billing state; no live backend was used). The screenshot confirms the unified Billing & invoices action renders and the legacy duplicate actions are absent. The inline review comments cover distribution/backend states that this Cloud screenshot does not prove.
|
huang47
left a comment
There was a problem hiding this comment.
I found one required distribution-state regression. The second inline comment is a backend rollout check; no code change is needed if that dependency is already confirmed.
Current-head UI evidence: #14608 (comment)
Co-authored-by: Amp <amp@ampcode.com> Amp-Thread-ID: https://ampcode.com/threads/T-019fc87c-d73e-7635-83db-1f7c0e65e42d
Amp-Thread-ID: https://ampcode.com/threads/T-019fc87c-d73e-7635-83db-1f7c0e65e42d Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019fc87c-d73e-7635-83db-1f7c0e65e42d Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019fc87c-d73e-7635-83db-1f7c0e65e42d Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019fc87c-d73e-7635-83db-1f7c0e65e42d Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019fc87c-d73e-7635-83db-1f7c0e65e42d Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019fc87c-d73e-7635-83db-1f7c0e65e42d Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019fc87c-d73e-7635-83db-1f7c0e65e42d Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019fc87c-d73e-7635-83db-1f7c0e65e42d Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019fc87c-d73e-7635-83db-1f7c0e65e42d Co-authored-by: Amp <amp@ampcode.com>
580fd10 to
fe0462e
Compare
|
Current-head UI evidence for The screenshot confirms the unified Billing & invoices action renders and the legacy duplicate actions are absent. The non-blocking review comment covers commit-stack structure, which this screenshot does not prove. |
huang47
left a comment
There was a problem hiding this comment.
LGTM.
The feature commit precedes three fixes for regressions it introduced, leaving intermediate commits broken and unreliable to bisect. Main squash-merges, so this is non-blocking; please characterize local/legacy behavior first in future stacks.
|
|


Summary
For the cloud distribution, replaces duplicate Stripe portal entry points in Plan & Credits with one role-gated Billing & invoices action, including free and never-subscribed owner states on the workspace billing rail. Local and desktop distributions retain Manage billing and footer Invoice history. Built directly from
main; the FE-1452 Figma prototype and #14450 were references only.Root cause
SubscriptionPanelContentWorkspaceexposed the samemanageSubscription()portal as Manage billing in the plan header and as Invoice history throughSubscriptionFooterLinks. The header action also excluded free plans and fresh unsubscribed workspaces, even though the workspace billing backend lazily provisions a Stripe customer when its portal is first opened. The legacy billing rail does not guarantee that contract.Changes
canManageSubscription, while preserving ended-paid legacy access and read-only member states.Review Focus
canManageSubscription; unsupported never-subscribed/FREE legacy states stay hidden, and local/desktop behavior remains unchanged.manageSubscription()error path.Linear: FE-1452
Screenshots
Real app with mocked active Pro billing state.
AS IS
TO BE
Free tier / no active subscription
Verification
pnpm test:unit src/platform/cloud/subscription/components/SubscriptionFooterLinks.test.ts src/platform/workspace/components/SubscriptionPanelContentWorkspace.test.ts(47 tests)pnpm exec playwright test --project=cloud browser_tests/tests/dialogs/creditsTile.spec.ts browser_tests/tests/dialogs/endedSubscription.spec.ts(10 tests)pnpm typecheckpnpm typecheck:browser