From 6e948b07d13b85e9251c3a200bf149f167649bc4 Mon Sep 17 00:00:00 2001 From: AlexRV12 <71396855+AlexRV12@users.noreply.github.com> Date: Thu, 8 Oct 2026 08:40:45 +0200 Subject: [PATCH] feat: ask before minting the frontend sdk token in the raw app editor (#11604) * feat: ask before minting the frontend sdk token in the raw app editor * fix: record editor sdk consent on continue so a late mint cannot override a decline Co-Authored-By: Claude Opus 5.5 * fix: only the newest editor sdk mint may start the preview Co-Authored-By: Claude Opus 5.5 --------- Co-authored-by: Claude Opus 5.5 --- .../apps/editor/PublicAppFrame.svelte | 8 +- .../components/raw_apps/RawAppEditor.svelte | 137 ++++++++++++++++-- .../raw_apps/RawAppSdkConsent.svelte | 19 ++- .../lib/components/raw_apps/sdkScopes.test.ts | 13 +- .../src/lib/components/raw_apps/sdkScopes.ts | 44 +++++- frontend/src/lib/components/raw_apps/utils.ts | 2 + .../sessions/sessionRuntime.svelte.ts | 8 + 7 files changed, 197 insertions(+), 34 deletions(-) diff --git a/frontend/src/lib/components/apps/editor/PublicAppFrame.svelte b/frontend/src/lib/components/apps/editor/PublicAppFrame.svelte index e994767488..a351117e5c 100644 --- a/frontend/src/lib/components/apps/editor/PublicAppFrame.svelte +++ b/frontend/src/lib/components/apps/editor/PublicAppFrame.svelte @@ -35,7 +35,11 @@ import { EMBED_NAV_CONTEXT_KEY, type EmbedNav } from '../types' import { loadAppPreview } from './loadAppPreview' import RawAppSdkConsent from '$lib/components/raw_apps/RawAppSdkConsent.svelte' - import { hasStoredSdkConsent, storeSdkConsent } from '$lib/components/raw_apps/sdkScopes' + import { + hasStoredSdkConsent, + sdkConsentCovers, + storeSdkConsent + } from '$lib/components/raw_apps/sdkScopes' type EmbedToken = { token?: string | null @@ -388,7 +392,7 @@ appPath = resp.app_path ?? appPath workspaceId = resp.workspace_id ?? workspaceId const granted = resp.sdk_scopes ?? [] - if (!granted.every((s) => approved.includes(s))) { + if (!sdkConsentCovers(approved, granted)) { // The app was redeployed with more scopes between the prompt and the // mint. Never inject a token carrying scopes the viewer wasn't shown: // drop it and ask again with the new set. diff --git a/frontend/src/lib/components/raw_apps/RawAppEditor.svelte b/frontend/src/lib/components/raw_apps/RawAppEditor.svelte index 8a0655d70e..2288403438 100644 --- a/frontend/src/lib/components/raw_apps/RawAppEditor.svelte +++ b/frontend/src/lib/components/raw_apps/RawAppEditor.svelte @@ -50,7 +50,14 @@ import { createAppSelectedContext, type AppCodeSelectionElement } from '../copilot/chat/context' import { captureScale, MAX_IMAGE_EDGE } from '../copilot/chat/imageUtils' import { rawAppLintStore } from './lintStore' - import { dbSchemas } from '$lib/stores' + import { dbSchemas, userStore } from '$lib/stores' + import RawAppSdkConsent from './RawAppSdkConsent.svelte' + import { + hasStoredSdkConsent, + movePreviewSdkConsent, + sdkConsentCovers, + storeSdkConsent + } from './sdkScopes' import { MousePointerSquareDashed, RefreshCw, @@ -414,6 +421,9 @@ // carry our origin, so they travel wrapped: listeners that trust a same-origin // message must not see the isolated app's as their own. let previewControllerUrl: string | undefined = undefined + // Editor-to-controller only, never relayed to the app: the consent prompt lives in + // the editor, so the pop-out says why it is blank. + const PREVIEW_NOTICE = 'wm:previewNotice' onDestroy(() => { if (previewControllerUrl) URL.revokeObjectURL(previewControllerUrl) }) @@ -423,14 +433,19 @@ [ `App preview - +