[backport core/1.47] fix(dialog): keep Settings open when nested dialogs shift focus + BYOK secrets E2E#13621
Conversation
## ELI-5 The settings screen now has a "Secrets" panel where you can save API keys for model/AI providers. This adds an end-to-end test that plays out the whole story like a real user: open the panel, add a key, watch it show up in the list, then delete it. It also checks the security promise — the key you type is sent to the server but is **never** shown back to you afterward — and that an account without access to the gated providers never even sees them in the dropdown. ## What Adds `browser_tests/tests/cloudSecrets.spec.ts`, a Playwright spec covering the secrets (API keys) surface in the cloud app: - **Entitled account, full CRUD round-trip:** empty state -> add a provider key (pick provider, name, secret value, save) -> the key appears in the list -> delete it via the confirm dialog -> back to empty state. - **Secret value is write-only:** asserts the create request carried the plaintext value, but the value is never echoed back into the DOM (the list-response schema is metadata-only). - **Entitlement gate:** an account whose provider allowlist is empty never sees the gated providers anywhere in the add dialog. Follows the existing cloud E2E conventions: drives a raw `page` and reuses the `mockCloudBoot` / `bootCloud` helpers so the app boots signed-in against fully mocked endpoints. A small stateful in-memory handler backs the secrets endpoints (list / create / delete + the provider allowlist) so the flow is deterministic and never touches a real backend. ## Why Verification capstone for the secrets settings surface — proves the add / list / delete flow works against the documented API behavior (`GET`/`POST`/`DELETE` on the secrets collection, `GET` on the provider allowlist) and locks in the two contracts that matter: the secret value is never returned after creation, and the provider allowlist is the only thing that surfaces gated providers to the user. ## Tests - `browser_tests/tests/cloudSecrets.spec.ts` — new, two cases (tagged `@cloud`). - Static checks pass locally: oxlint (0 warnings/errors) and oxfmt formatting. - The browser run itself needs a served app + the E2E harness (CI), so it was not executed in this environment; the spec is self-contained and mocks all network. --------- Co-authored-by: GitHub Action <action@github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
🎨 Storybook: ✅ Built — View Storybook🎭 Playwright: ✅ 1691 passed, 0 failed · 3 flaky📊 Browser Reports
📦 Bundle Size
⚡ Performance Report
✅ No regressions detected. All metrics
Historical variance (last 15 runs)
Trend (last 15 commits on main)
Raw data{
"timestamp": "2026-07-13T17:59:05.125Z",
"gitSha": "8e4cfa759764e16067691bde7f8a42dd79962299",
"branch": "backport-13510-to-core-1.47",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2020.6530000000384,
"styleRecalcs": 10,
"styleRecalcDurationMs": 10.77,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 402.785,
"heapDeltaBytes": -5088436,
"heapUsedBytes": 49629000,
"domNodes": 20,
"jsHeapTotalBytes": 25165824,
"scriptDurationMs": 21.385999999999996,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "canvas-idle",
"durationMs": 2010.5629999999906,
"styleRecalcs": 10,
"styleRecalcDurationMs": 8.183000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 340.05999999999995,
"heapDeltaBytes": 1190920,
"heapUsedBytes": 56974648,
"domNodes": 20,
"jsHeapTotalBytes": 18874368,
"scriptDurationMs": 15.154999999999998,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 2032.083,
"styleRecalcs": 76,
"styleRecalcDurationMs": 42.97999999999999,
"layouts": 12,
"layoutDurationMs": 3.687,
"taskDurationMs": 854.715,
"heapDeltaBytes": -3855560,
"heapUsedBytes": 65513028,
"domNodes": 60,
"jsHeapTotalBytes": 18898944,
"scriptDurationMs": 128.202,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1758.8030000000003,
"styleRecalcs": 72,
"styleRecalcDurationMs": 31.93,
"layouts": 12,
"layoutDurationMs": 3.209,
"taskDurationMs": 717.2879999999999,
"heapDeltaBytes": -6445456,
"heapUsedBytes": 52428792,
"domNodes": 54,
"jsHeapTotalBytes": 25165824,
"scriptDurationMs": 117.05100000000002,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1711.1090000000218,
"styleRecalcs": 30,
"styleRecalcDurationMs": 15.117,
"layouts": 6,
"layoutDurationMs": 0.516,
"taskDurationMs": 296.66700000000003,
"heapDeltaBytes": 2364460,
"heapUsedBytes": 61258480,
"domNodes": 77,
"jsHeapTotalBytes": 25952256,
"scriptDurationMs": 17.632,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1773.054000000002,
"styleRecalcs": 32,
"styleRecalcDurationMs": 19.721999999999998,
"layouts": 6,
"layoutDurationMs": 0.5919999999999999,
"taskDurationMs": 400.533,
"heapDeltaBytes": -3465872,
"heapUsedBytes": 66302920,
"domNodes": -226,
"jsHeapTotalBytes": 12472320,
"scriptDurationMs": 25.028000000000002,
"eventListeners": -184,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "dom-widget-clipping",
"durationMs": 621.3549999999941,
"styleRecalcs": 11,
"styleRecalcDurationMs": 8.164,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 386.79400000000004,
"heapDeltaBytes": -23676088,
"heapUsedBytes": 45958256,
"domNodes": -279,
"jsHeapTotalBytes": 6705152,
"scriptDurationMs": 56.446000000000005,
"eventListeners": -201,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "dom-widget-clipping",
"durationMs": 555.8650000000398,
"styleRecalcs": 11,
"styleRecalcDurationMs": 7.6259999999999994,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 359.09499999999997,
"heapDeltaBytes": 10595124,
"heapUsedBytes": 62640072,
"domNodes": -291,
"jsHeapTotalBytes": 6156288,
"scriptDurationMs": 53.314,
"eventListeners": -203,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-idle",
"durationMs": 2041.3139999999999,
"styleRecalcs": 8,
"styleRecalcDurationMs": 7.622,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 515.245,
"heapDeltaBytes": -3114624,
"heapUsedBytes": 57903832,
"domNodes": -273,
"jsHeapTotalBytes": -1089536,
"scriptDurationMs": 85.85400000000001,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-idle",
"durationMs": 2010.0830000000087,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.888,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 478.675,
"heapDeltaBytes": 11192704,
"heapUsedBytes": 68494524,
"domNodes": 18,
"jsHeapTotalBytes": 6029312,
"scriptDurationMs": 87.15800000000002,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2156.6869999999767,
"styleRecalcs": 69,
"styleRecalcDurationMs": 17.394000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1162.7350000000001,
"heapDeltaBytes": 19674124,
"heapUsedBytes": 81549352,
"domNodes": -275,
"jsHeapTotalBytes": 163840,
"scriptDurationMs": 448.183,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2113.078000000087,
"styleRecalcs": 68,
"styleRecalcDurationMs": 17.551000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1123.4630000000002,
"heapDeltaBytes": 19041404,
"heapUsedBytes": 81347080,
"domNodes": -276,
"jsHeapTotalBytes": -622592,
"scriptDurationMs": 399.23800000000006,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3096.7259999999897,
"styleRecalcs": 62,
"styleRecalcDurationMs": 15.126000000000001,
"layouts": 60,
"layoutDurationMs": 6.994999999999999,
"taskDurationMs": 1222.02,
"heapDeltaBytes": 11758364,
"heapUsedBytes": 67760860,
"domNodes": 6,
"jsHeapTotalBytes": 1835008,
"scriptDurationMs": 466.463,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3115.0370000000294,
"styleRecalcs": 63,
"styleRecalcDurationMs": 17.799999999999997,
"layouts": 60,
"layoutDurationMs": 7.6690000000000005,
"taskDurationMs": 1357.944,
"heapDeltaBytes": 12788300,
"heapUsedBytes": 66996592,
"domNodes": -278,
"jsHeapTotalBytes": 0,
"scriptDurationMs": 511.007,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66999999999998,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "minimap-idle",
"durationMs": 2024.39099999998,
"styleRecalcs": 7,
"styleRecalcDurationMs": 5.663999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 489.51399999999995,
"heapDeltaBytes": -3287108,
"heapUsedBytes": 59693200,
"domNodes": -275,
"jsHeapTotalBytes": -303104,
"scriptDurationMs": 86.44400000000002,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2002.1370000000616,
"styleRecalcs": 9,
"styleRecalcDurationMs": 11.117999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 565.6650000000001,
"heapDeltaBytes": 10324028,
"heapUsedBytes": 65335804,
"domNodes": 18,
"jsHeapTotalBytes": 4980736,
"scriptDurationMs": 105.322,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 606.3720000000217,
"styleRecalcs": 48,
"styleRecalcDurationMs": 12.926000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 402.463,
"heapDeltaBytes": -23925484,
"heapUsedBytes": 45905672,
"domNodes": -277,
"jsHeapTotalBytes": 5394432,
"scriptDurationMs": 120.482,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666682,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 580.9400000000551,
"styleRecalcs": 47,
"styleRecalcDurationMs": 11.372,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 362.991,
"heapDeltaBytes": 8085424,
"heapUsedBytes": 67038680,
"domNodes": 20,
"jsHeapTotalBytes": 19660800,
"scriptDurationMs": 118.213,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 2052.400999999975,
"styleRecalcs": 10,
"styleRecalcDurationMs": 9.405999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 392.449,
"heapDeltaBytes": -7363680,
"heapUsedBytes": 62599744,
"domNodes": -278,
"jsHeapTotalBytes": 18239488,
"scriptDurationMs": 12.604000000000001,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-idle",
"durationMs": 1995.326000000091,
"styleRecalcs": 12,
"styleRecalcDurationMs": 10.143,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 374.90299999999996,
"heapDeltaBytes": -2382468,
"heapUsedBytes": 50135864,
"domNodes": -288,
"jsHeapTotalBytes": 17952768,
"scriptDurationMs": 13.493000000000002,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1698.6670000000004,
"styleRecalcs": 75,
"styleRecalcDurationMs": 34.31999999999999,
"layouts": 16,
"layoutDurationMs": 3.887,
"taskDurationMs": 636.5110000000001,
"heapDeltaBytes": -9940072,
"heapUsedBytes": 50641920,
"domNodes": 63,
"jsHeapTotalBytes": 26738688,
"scriptDurationMs": 89.035,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1755.4210000000694,
"styleRecalcs": 76,
"styleRecalcDurationMs": 38.785,
"layouts": 16,
"layoutDurationMs": 4.204000000000001,
"taskDurationMs": 719.215,
"heapDeltaBytes": 18042324,
"heapUsedBytes": 71099704,
"domNodes": -250,
"jsHeapTotalBytes": 15331328,
"scriptDurationMs": 92.071,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-transition-enter",
"durationMs": 965.8079999999813,
"styleRecalcs": 18,
"styleRecalcDurationMs": 32.839999999999996,
"layouts": 14,
"layoutDurationMs": 16.058000000000003,
"taskDurationMs": 758.1249999999999,
"heapDeltaBytes": 27905300,
"heapUsedBytes": 97543916,
"domNodes": 13673,
"jsHeapTotalBytes": 16515072,
"scriptDurationMs": 44.61,
"eventListeners": 2533,
"totalBlockingTimeMs": 152,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8144.496000000004,
"styleRecalcs": 251,
"styleRecalcDurationMs": 55.659,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3614.879,
"heapDeltaBytes": 8015040,
"heapUsedBytes": 68547420,
"domNodes": -272,
"jsHeapTotalBytes": 425984,
"scriptDurationMs": 1217.0210000000002,
"eventListeners": -183,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.80000000000109
},
{
"name": "viewport-pan-sweep",
"durationMs": 8180.052000000046,
"styleRecalcs": 250,
"styleRecalcDurationMs": 55.998999999999995,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3907.2919999999995,
"heapDeltaBytes": -1725924,
"heapUsedBytes": 70758888,
"domNodes": 18,
"jsHeapTotalBytes": 16834560,
"scriptDurationMs": 1276.03,
"eventListeners": 20,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-idle",
"durationMs": 12134.83500000001,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 12112.585,
"heapDeltaBytes": -29155212,
"heapUsedBytes": 170264736,
"domNodes": -3301,
"jsHeapTotalBytes": 20680704,
"scriptDurationMs": 491.444,
"eventListeners": -16374,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-idle",
"durationMs": 12915.835000000015,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 12897.927000000001,
"heapDeltaBytes": -46635068,
"heapUsedBytes": 171269044,
"domNodes": -3301,
"jsHeapTotalBytes": 16748544,
"scriptDurationMs": 579.8559999999999,
"eventListeners": -16381,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.219999999999953,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 15655.129999999986,
"styleRecalcs": 81,
"styleRecalcDurationMs": 17.404000000000032,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 15628.466,
"heapDeltaBytes": -35127668,
"heapUsedBytes": 166413760,
"domNodes": -3302,
"jsHeapTotalBytes": 16748544,
"scriptDurationMs": 764.105,
"eventListeners": -16372,
"totalBlockingTimeMs": 32,
"frameDurationMs": 17.219999999999953,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-pan",
"durationMs": 15816.456000000017,
"styleRecalcs": 81,
"styleRecalcDurationMs": 18.269999999999953,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 15790.901999999998,
"heapDeltaBytes": -9275620,
"heapUsedBytes": 180484368,
"domNodes": -3311,
"jsHeapTotalBytes": 18497536,
"scriptDurationMs": 829.1299999999999,
"eventListeners": -16371,
"totalBlockingTimeMs": 18,
"frameDurationMs": 17.776666666666642,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 447.5500000000352,
"styleRecalcs": 11,
"styleRecalcDurationMs": 16.604,
"layouts": 3,
"layoutDurationMs": 0.5940000000000001,
"taskDurationMs": 89.965,
"heapDeltaBytes": 4887108,
"heapUsedBytes": 56956004,
"domNodes": 128,
"jsHeapTotalBytes": 0,
"scriptDurationMs": 8.583,
"eventListeners": 65,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "workflow-execution",
"durationMs": 498.29699999997956,
"styleRecalcs": 10,
"styleRecalcDurationMs": 18.622,
"layouts": 3,
"layoutDurationMs": 0.673,
"taskDurationMs": 154.508,
"heapDeltaBytes": -2525884,
"heapUsedBytes": 49500464,
"domNodes": -162,
"jsHeapTotalBytes": -659456,
"scriptDurationMs": 8.872000000000002,
"eventListeners": -132,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
}
]
} |
Codecov Report❌ Patch coverage is
@@ Coverage Diff @@
## core/1.47 #13621 +/- ##
===========================================
Coverage 78.03% 78.03%
===========================================
Files 1656 1656
Lines 92592 92599 +7
Branches 32742 32082 -660
===========================================
+ Hits 72252 72259 +7
Misses 19720 19720
Partials 620 620
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 1 file with indirect coverage changes 🚀 New features to boost your workflow:
|
Backport of #13510 to
core/1.47Automatically created by backport workflow.