feat: enforce partner-node governance across the workbench#13598
feat: enforce partner-node governance across the workbench#13598comfydesigner wants to merge 1 commit into
Conversation
Admin-disabled partner nodes (Allowlist) now enforce everywhere users meet nodes: - Discovery: a workspace.disabled-partner-nodes NodeDefFilter (the deprecated/experimental seam) hides them from node search, the category sidebar, and the node library; when a query or the Partner filter would have matched only disabled nodes, the empty state says 'This node has been disabled by your team admin.' — computed by running the same matcher over the hidden defs. The legacy right-click menu hides them via skip_list sync on registered types. - Canvas: offenders surface as a 'Disabled node(s)' group in Workflow Overview > Errors with jump-to-node rows, flag the node error highlight, gate the Run button (opens the Errors tab instead of queueing), and announce once per workflow load via a toast with a View details action. Offenders re-derive live on node add/remove and governance toggles. disabledPartnerNodesStore owns governance state: fetches the partner-nodes list, scans the graph (api_node defs matched by display name), and exposes the def predicate. TODO(endpoint): list() is the real workspace API; enforcement activates once the backend serves it.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 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:
✨ Finishing Touches🧪 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: ❌ 1679 passed, 7 failed · 2 flaky❌ Failed Tests📊 Browser Reports
📦 Bundle Size
⚡ Performance Report
Absolute values
Raw data{
"timestamp": "2026-07-11T02:38:49.890Z",
"gitSha": "a30c85c05f9b81999c2d5f3e4585ca00ccc9cfe1",
"branch": "split/node-enforcement",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2111.703000000034,
"styleRecalcs": 7,
"styleRecalcDurationMs": 8.989,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 550.297,
"heapDeltaBytes": -6620344,
"heapUsedBytes": 63664444,
"domNodes": -285,
"jsHeapTotalBytes": 20590592,
"scriptDurationMs": 28.03,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-idle",
"durationMs": 2072.5170000000617,
"styleRecalcs": 10,
"styleRecalcDurationMs": 10.705000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 427.882,
"heapDeltaBytes": -6406800,
"heapUsedBytes": 63954540,
"domNodes": -278,
"jsHeapTotalBytes": 18755584,
"scriptDurationMs": 18.581,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1842.5379999999905,
"styleRecalcs": 75,
"styleRecalcDurationMs": 37.699999999999996,
"layouts": 12,
"layoutDurationMs": 3.394,
"taskDurationMs": 785.344,
"heapDeltaBytes": -5121480,
"heapUsedBytes": 54434536,
"domNodes": 57,
"jsHeapTotalBytes": 24379392,
"scriptDurationMs": 118.693,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1823.8670000000639,
"styleRecalcs": 73,
"styleRecalcDurationMs": 37.487,
"layouts": 12,
"layoutDurationMs": 3.626,
"taskDurationMs": 781.7729999999999,
"heapDeltaBytes": -3231448,
"heapUsedBytes": 49799040,
"domNodes": -266,
"jsHeapTotalBytes": 16379904,
"scriptDurationMs": 112.66699999999999,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1732.5989999999933,
"styleRecalcs": 30,
"styleRecalcDurationMs": 15.137,
"layouts": 6,
"layoutDurationMs": 0.6430000000000001,
"taskDurationMs": 332.178,
"heapDeltaBytes": -1389260,
"heapUsedBytes": 51362656,
"domNodes": -243,
"jsHeapTotalBytes": 10874880,
"scriptDurationMs": 19.046999999999997,
"eventListeners": -186,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1756.9499999999607,
"styleRecalcs": 32,
"styleRecalcDurationMs": 25.473000000000003,
"layouts": 6,
"layoutDurationMs": 0.647,
"taskDurationMs": 319.70500000000004,
"heapDeltaBytes": 7516988,
"heapUsedBytes": 74054560,
"domNodes": 78,
"jsHeapTotalBytes": 19415040,
"scriptDurationMs": 19.771000000000004,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "dom-widget-clipping",
"durationMs": 569.5549999999798,
"styleRecalcs": 12,
"styleRecalcDurationMs": 7.687999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 330.11600000000004,
"heapDeltaBytes": 8367300,
"heapUsedBytes": 67566132,
"domNodes": 20,
"jsHeapTotalBytes": 18087936,
"scriptDurationMs": 56.723000000000006,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "dom-widget-clipping",
"durationMs": 585.0830000000542,
"styleRecalcs": 11,
"styleRecalcDurationMs": 6.796000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 374.489,
"heapDeltaBytes": 8194508,
"heapUsedBytes": 60639508,
"domNodes": -293,
"jsHeapTotalBytes": 10874880,
"scriptDurationMs": 59.09299999999999,
"eventListeners": -203,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.669999999999998,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-idle",
"durationMs": 2023.0149999999867,
"styleRecalcs": 10,
"styleRecalcDurationMs": 8.288000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 495.82099999999997,
"heapDeltaBytes": -8022108,
"heapUsedBytes": 64431120,
"domNodes": 20,
"jsHeapTotalBytes": 11153408,
"scriptDurationMs": 84.05799999999999,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "large-graph-idle",
"durationMs": 2048.8530000000083,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.310999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 551.2360000000001,
"heapDeltaBytes": -8657184,
"heapUsedBytes": 59532380,
"domNodes": -272,
"jsHeapTotalBytes": -1327104,
"scriptDurationMs": 84.257,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-pan",
"durationMs": 2123.999000000026,
"styleRecalcs": 69,
"styleRecalcDurationMs": 19.092000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1064.0559999999998,
"heapDeltaBytes": 13850672,
"heapUsedBytes": 83315760,
"domNodes": -273,
"jsHeapTotalBytes": -598016,
"scriptDurationMs": 373.201,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2107.65600000002,
"styleRecalcs": 70,
"styleRecalcDurationMs": 20.7,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1023.2339999999999,
"heapDeltaBytes": 12463396,
"heapUsedBytes": 85773452,
"domNodes": 20,
"jsHeapTotalBytes": 11591680,
"scriptDurationMs": 359.74600000000004,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-zoom",
"durationMs": 3088.2589999999936,
"styleRecalcs": 65,
"styleRecalcDurationMs": 20.159000000000002,
"layouts": 60,
"layoutDurationMs": 8.497,
"taskDurationMs": 1266.1850000000002,
"heapDeltaBytes": 16449464,
"heapUsedBytes": 71808660,
"domNodes": 14,
"jsHeapTotalBytes": 4456448,
"scriptDurationMs": 476.88399999999996,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3068.082000000004,
"styleRecalcs": 63,
"styleRecalcDurationMs": 17.514,
"layouts": 60,
"layoutDurationMs": 7.890999999999999,
"taskDurationMs": 1242.3080000000002,
"heapDeltaBytes": 13864068,
"heapUsedBytes": 68190684,
"domNodes": -283,
"jsHeapTotalBytes": 262144,
"scriptDurationMs": 463.408,
"eventListeners": -195,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2052.0460000000185,
"styleRecalcs": 7,
"styleRecalcDurationMs": 6.432,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 532.645,
"heapDeltaBytes": -1853516,
"heapUsedBytes": 61045100,
"domNodes": -278,
"jsHeapTotalBytes": 212992,
"scriptDurationMs": 86.10699999999999,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "minimap-idle",
"durationMs": 2045.2629999999772,
"styleRecalcs": 8,
"styleRecalcDurationMs": 6.623,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 524.8929999999999,
"heapDeltaBytes": -2241420,
"heapUsedBytes": 60522928,
"domNodes": -275,
"jsHeapTotalBytes": -311296,
"scriptDurationMs": 80.801,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 593.482999999992,
"styleRecalcs": 47,
"styleRecalcDurationMs": 11.837000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 411.231,
"heapDeltaBytes": -22140096,
"heapUsedBytes": 48245732,
"domNodes": -276,
"jsHeapTotalBytes": 6172672,
"scriptDurationMs": 129.469,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66666666666665,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 550.0560000000405,
"styleRecalcs": 47,
"styleRecalcDurationMs": 10.267999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 355.74500000000006,
"heapDeltaBytes": 8987644,
"heapUsedBytes": 68344252,
"domNodes": 20,
"jsHeapTotalBytes": 20709376,
"scriptDurationMs": 122.22499999999998,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-idle",
"durationMs": 2017.876000000001,
"styleRecalcs": 9,
"styleRecalcDurationMs": 7.426,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 390.551,
"heapDeltaBytes": -1793636,
"heapUsedBytes": 50436400,
"domNodes": -292,
"jsHeapTotalBytes": 17428480,
"scriptDurationMs": 14.883000000000001,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 2009.9289999999428,
"styleRecalcs": 9,
"styleRecalcDurationMs": 7.072,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 391.871,
"heapDeltaBytes": -4682128,
"heapUsedBytes": 47590932,
"domNodes": -292,
"jsHeapTotalBytes": 17428480,
"scriptDurationMs": 15.553,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1737.6910000000407,
"styleRecalcs": 75,
"styleRecalcDurationMs": 38.478,
"layouts": 16,
"layoutDurationMs": 4.197,
"taskDurationMs": 684.97,
"heapDeltaBytes": 4765472,
"heapUsedBytes": 57763336,
"domNodes": -224,
"jsHeapTotalBytes": 16642048,
"scriptDurationMs": 89.34800000000001,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1688.806999999997,
"styleRecalcs": 76,
"styleRecalcDurationMs": 35.281,
"layouts": 16,
"layoutDurationMs": 4.505,
"taskDurationMs": 649.504,
"heapDeltaBytes": -9086420,
"heapUsedBytes": 50227476,
"domNodes": 63,
"jsHeapTotalBytes": 25952256,
"scriptDurationMs": 87.67800000000001,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-transition-enter",
"durationMs": 965.9540000000106,
"styleRecalcs": 19,
"styleRecalcDurationMs": 30.81199999999999,
"layouts": 15,
"layoutDurationMs": 14.020999999999999,
"taskDurationMs": 763.4000000000001,
"heapDeltaBytes": 31367124,
"heapUsedBytes": 99922964,
"domNodes": 13673,
"jsHeapTotalBytes": 11796480,
"scriptDurationMs": 27.108000000000008,
"eventListeners": 2533,
"totalBlockingTimeMs": 132,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "viewport-pan-sweep",
"durationMs": 8136.111000000028,
"styleRecalcs": 250,
"styleRecalcDurationMs": 59.296,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3508.857,
"heapDeltaBytes": 10431852,
"heapUsedBytes": 71558796,
"domNodes": -276,
"jsHeapTotalBytes": 679936,
"scriptDurationMs": 1135.8709999999999,
"eventListeners": -183,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8173.845000000028,
"styleRecalcs": 252,
"styleRecalcDurationMs": 58.690000000000005,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3566.715,
"heapDeltaBytes": -10504380,
"heapUsedBytes": 74987476,
"domNodes": -263,
"jsHeapTotalBytes": 6565888,
"scriptDurationMs": 1168.587,
"eventListeners": -183,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-idle",
"durationMs": 12808.126000000015,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 12792.302,
"heapDeltaBytes": -29257520,
"heapUsedBytes": 166510964,
"domNodes": -3300,
"jsHeapTotalBytes": 14913536,
"scriptDurationMs": 496.203,
"eventListeners": -16062,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.223333333333358,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 13807.51799999996,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 13764.403999999999,
"heapDeltaBytes": -32516052,
"heapUsedBytes": 170009928,
"domNodes": -3302,
"jsHeapTotalBytes": 20418560,
"scriptDurationMs": 563.681,
"eventListeners": -16374,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.223333333333358,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-pan",
"durationMs": 15950.285000000007,
"styleRecalcs": 80,
"styleRecalcDurationMs": 22.639999999999993,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 15927.266999999998,
"heapDeltaBytes": -7777148,
"heapUsedBytes": 167007144,
"domNodes": -3304,
"jsHeapTotalBytes": 19107840,
"scriptDurationMs": 867.586,
"eventListeners": -16378,
"totalBlockingTimeMs": 48,
"frameDurationMs": 17.776666666666642,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 16160.911000000055,
"styleRecalcs": 82,
"styleRecalcDurationMs": 20.72400000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 16112.805000000002,
"heapDeltaBytes": -38104860,
"heapUsedBytes": 155686696,
"domNodes": -3304,
"jsHeapTotalBytes": 16224256,
"scriptDurationMs": 868.673,
"eventListeners": -16114,
"totalBlockingTimeMs": 11,
"frameDurationMs": 18.333333333333332,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 450.1870000000281,
"styleRecalcs": 14,
"styleRecalcDurationMs": 18.688,
"layouts": 2,
"layoutDurationMs": 0.4059999999999999,
"taskDurationMs": 99.24599999999998,
"heapDeltaBytes": 5014132,
"heapUsedBytes": 67631380,
"domNodes": 130,
"jsHeapTotalBytes": 4718592,
"scriptDurationMs": 10.973,
"eventListeners": 65,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "workflow-execution",
"durationMs": 463.8990000000831,
"styleRecalcs": 13,
"styleRecalcDurationMs": 18.385,
"layouts": 2,
"layoutDurationMs": 0.35899999999999993,
"taskDurationMs": 196.38400000000001,
"heapDeltaBytes": -22651112,
"heapUsedBytes": 47179916,
"domNodes": -198,
"jsHeapTotalBytes": 4861952,
"scriptDurationMs": 10.627,
"eventListeners": -132,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66999999999998,
"p95FrameDurationMs": 16.699999999999818
}
]
} |
Codecov Report❌ Patch coverage is @@ Coverage Diff @@
## split/allowlist #13598 +/- ##
===================================================
- Coverage 77.42% 77.35% -0.08%
===================================================
Files 1681 1683 +2
Lines 96321 96486 +165
Branches 34291 34333 +42
===================================================
+ Hits 74574 74633 +59
- Misses 21084 21190 +106
Partials 663 663
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 2 files with indirect coverage changes 🚀 New features to boost your workflow:
|
What
Admin-disabled partner nodes (from the Allowlist, #13594) now enforce everywhere users meet nodes:
workspace.disabled-partner-nodesNodeDefFilter(the deprecated/experimental seam) hides disabled nodes from node search, the category sidebar, and the node library. When a query — or the Partner filter — would have matched only disabled nodes, the empty state explains: "This node has been disabled by your team admin." (same matcher over the hidden defs, partitioned — no second heuristic). The legacy right-click menu hides them viaskip_listsync on registered types.Linear: DES-484. Figma: error states, search hiding.
Notes for reviewers
disabledPartnerNodesStoreowns governance state: fetches the partner-nodes list (lazy-imported; guarded on cloud + team-workspaces flag), scans the graph matchingapi_nodedefs by display name, exposes the def predicate. Enforcement activates once the backend serves the endpoint — until then the store enforces nothing.