create-interview-cockpit 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1143,6 +1143,414 @@ export const DEFAULT_MODULE_FEDERATION_LAB: FrontendLabWorkspace = {
1143
1143
  files: MODULE_FEDERATION_DEFAULT_FILES,
1144
1144
  };
1145
1145
 
1146
+ // ─── Isolated Mount/Unmount MFE workspace ───────────────────────────────────
1147
+ // Each remote manages its own React root — no shared React tree with the host.
1148
+ // The remote exposes mount(el, props) / unmount(el) instead of a React component.
1149
+ const MODULE_FEDERATION_ISOLATED_FILES: Record<string, string> = {
1150
+ "README.md": `# Isolated Mount/Unmount Module Federation Lab
1151
+
1152
+ ## Pattern overview
1153
+
1154
+ In the classic "shared React tree" pattern the host imports a remote React component
1155
+ and renders it inside its own tree - both share one React runtime.
1156
+
1157
+ In this **isolated** pattern:
1158
+ - The remote exposes \`mount(el, props)\` and \`unmount(el)\` functions
1159
+ - The host calls those functions with a DOM element
1160
+ - Each remote creates its own \`ReactDOM.createRoot\` — it is NOT in the host's tree
1161
+ - The remote can use a different React major version from the host
1162
+
1163
+ ## Structure
1164
+
1165
+ - \`apps/host\` — the shell app (React 18)
1166
+ - \`apps/mfe-auth\` — the micro-frontend (could be React 18 or 19)
1167
+
1168
+ ## Key files
1169
+
1170
+ - \`apps/mfe-auth/src/mount.jsx\` — exposes \`mount\` / \`unmount\`
1171
+ - \`apps/mfe-auth/webpack.config.js\` — exposes \`./mount\` (not a React component)
1172
+ - \`apps/host/src/MfeContainer.jsx\` — host side: DOM ref + useEffect calling mount/unmount
1173
+ - \`apps/host/src/App.jsx\` — renders \`<MfeContainer />\` like any normal component
1174
+
1175
+ ## What to experiment with
1176
+
1177
+ 1. Try passing different versions of React to host vs mfe-auth and see they don't conflict
1178
+ 2. Add a second MFE (\`apps/mfe-dashboard\`) following the same mount/unmount contract
1179
+ 3. Pass props through \`mount(el, { user, theme })\` and handle updates in the remote
1180
+ 4. Observe that React context from the host does NOT flow into the remote
1181
+ `,
1182
+ "package.json": `{
1183
+ "name": "mf-isolated-lab",
1184
+ "private": true,
1185
+ "workspaces": [
1186
+ "apps/host",
1187
+ "apps/mfe-auth"
1188
+ ],
1189
+ "scripts": {
1190
+ "dev": "concurrently -k -n host,mfe-auth -c cyan,magenta 'npm run dev --workspace=@mf-isolated/host' 'npm run dev --workspace=@mf-isolated/mfe-auth'",
1191
+ "build": "npm run build --workspace=@mf-isolated/host && npm run build --workspace=@mf-isolated/mfe-auth"
1192
+ },
1193
+ "devDependencies": {
1194
+ "concurrently": "^9.2.1"
1195
+ }
1196
+ }
1197
+ `,
1198
+ "apps/host/package.json": `{
1199
+ "name": "@mf-isolated/host",
1200
+ "version": "1.0.0",
1201
+ "private": true,
1202
+ "scripts": {
1203
+ "dev": "webpack serve --config webpack.config.js",
1204
+ "build": "webpack --config webpack.config.js"
1205
+ },
1206
+ "dependencies": {
1207
+ "react": "^19.0.0",
1208
+ "react-dom": "^19.0.0"
1209
+ },
1210
+ "devDependencies": {
1211
+ "esbuild": "^0.28.0",
1212
+ "esbuild-loader": "^4.4.3",
1213
+ "html-webpack-plugin": "^5.6.7",
1214
+ "webpack": "^5.106.2",
1215
+ "webpack-cli": "^7.0.2",
1216
+ "webpack-dev-server": "^5.2.3"
1217
+ }
1218
+ }
1219
+ `,
1220
+ "apps/host/webpack.config.js": `const HtmlWebpackPlugin = require("html-webpack-plugin");
1221
+ const { ModuleFederationPlugin } = require("webpack").container;
1222
+ const deps = require("./package.json").dependencies;
1223
+
1224
+ const HOST_PORT = parseInt(process.env.HOST_PORT || "3001");
1225
+ const MFE_AUTH_PORT = parseInt(process.env.MFE_AUTH_PORT || "3002");
1226
+
1227
+ module.exports = {
1228
+ mode: "development",
1229
+ entry: "./src/index.js",
1230
+ output: {
1231
+ publicPath: "auto",
1232
+ },
1233
+ resolve: { extensions: [".js", ".jsx"] },
1234
+ module: {
1235
+ rules: [
1236
+ {
1237
+ test: /\\.(js|jsx)$/,
1238
+ exclude: /node_modules/,
1239
+ use: {
1240
+ loader: "esbuild-loader",
1241
+ options: { loader: "jsx", jsx: "automatic", target: "es2020" },
1242
+ },
1243
+ },
1244
+ ],
1245
+ },
1246
+ plugins: [
1247
+ new ModuleFederationPlugin({
1248
+ name: "host",
1249
+ remotes: {
1250
+ // The remote exposes mount/unmount — NOT a React component
1251
+ mfeAuth: \`mfeAuth@http://localhost:\${MFE_AUTH_PORT}/remoteEntry.js\`,
1252
+ },
1253
+ // Host does NOT share React with the remote.
1254
+ // Each app brings its own copy.
1255
+ shared: {
1256
+ react: { requiredVersion: deps.react },
1257
+ "react-dom": { requiredVersion: deps["react-dom"] },
1258
+ },
1259
+ }),
1260
+ new HtmlWebpackPlugin({ template: "./public/index.html" }),
1261
+ ],
1262
+ devServer: {
1263
+ port: HOST_PORT,
1264
+ headers: { "Access-Control-Allow-Origin": "*" },
1265
+ },
1266
+ };
1267
+ `,
1268
+ "apps/host/public/index.html": `<!doctype html>
1269
+ <html lang="en">
1270
+ <head>
1271
+ <meta charset="UTF-8" />
1272
+ <title>Host (Isolated MFE)</title>
1273
+ <style>
1274
+ body { font-family: system-ui, sans-serif; background: #0f172a; color: #e2e8f0; margin: 0; }
1275
+ h1 { padding: 1rem 1.5rem 0; font-size: 1.1rem; color: #94a3b8; }
1276
+ .mfe-slot {
1277
+ margin: 1rem 1.5rem;
1278
+ border: 1px solid #334155;
1279
+ border-radius: 8px;
1280
+ padding: 1rem;
1281
+ min-height: 80px;
1282
+ background: #1e293b;
1283
+ }
1284
+ </style>
1285
+ </head>
1286
+ <body>
1287
+ <div id="root"></div>
1288
+ </body>
1289
+ </html>
1290
+ `,
1291
+ "apps/host/src/index.js": `// Async boundary: required for Module Federation dynamic imports
1292
+ import("./bootstrap");
1293
+ `,
1294
+ "apps/host/src/bootstrap.jsx": `import React from "react";
1295
+ import { createRoot } from "react-dom/client";
1296
+ import App from "./App";
1297
+
1298
+ createRoot(document.getElementById("root")).render(<App />);
1299
+ `,
1300
+ "apps/host/src/App.jsx": `import React from "react";
1301
+ import MfeContainer from "./MfeContainer";
1302
+
1303
+ export default function App() {
1304
+ return (
1305
+ <div>
1306
+ <h1>Host App — Isolated MFE demo</h1>
1307
+ <p style={{ padding: "0 1.5rem", color: "#64748b", fontSize: "0.8rem" }}>
1308
+ The auth widget below is rendered by mfe-auth into its own React root.
1309
+ The host and the remote do NOT share a React tree.
1310
+ </p>
1311
+
1312
+ {/* Host renders a plain DOM container.
1313
+ MfeContainer calls mount/unmount on that element. */}
1314
+ <MfeContainer user={{ name: "Alice", role: "admin" }} />
1315
+ </div>
1316
+ );
1317
+ }
1318
+ `,
1319
+ "apps/host/src/MfeContainer.jsx": `import React, { useRef, useEffect } from "react";
1320
+
1321
+ // Lazy-load the remote's mount/unmount contract — not a React component.
1322
+ const mfeAuthMountPromise = import("mfeAuth/mount");
1323
+
1324
+ export default function MfeContainer({ user }) {
1325
+ const elRef = useRef(null);
1326
+ const mountedRef = useRef(null); // holds { unmount } returned by remote
1327
+
1328
+ useEffect(() => {
1329
+ let cancelled = false;
1330
+ let cleanup = null;
1331
+
1332
+ mfeAuthMountPromise.then(({ mount }) => {
1333
+ if (cancelled || !elRef.current) return;
1334
+ // mount() creates a new ReactDOM.createRoot inside mfe-auth.
1335
+ // It returns an object with an unmount() method.
1336
+ cleanup = mount(elRef.current, { user });
1337
+ mountedRef.current = cleanup;
1338
+ });
1339
+
1340
+ return () => {
1341
+ cancelled = true;
1342
+ // On cleanup, call the remote's own unmount so it can tear down its root.
1343
+ cleanup?.unmount();
1344
+ };
1345
+ }, []); // mount once — treat like a portal
1346
+
1347
+ // If props change, tell the remote to update.
1348
+ // The remote decides how to handle prop updates.
1349
+ useEffect(() => {
1350
+ mountedRef.current?.update?.({ user });
1351
+ }, [user]);
1352
+
1353
+ return (
1354
+ <div
1355
+ ref={elRef}
1356
+ className="mfe-slot"
1357
+ style={{
1358
+ margin: "1rem 1.5rem",
1359
+ border: "1px solid #334155",
1360
+ borderRadius: "8px",
1361
+ padding: "1rem",
1362
+ minHeight: "80px",
1363
+ background: "#1e293b",
1364
+ }}
1365
+ />
1366
+ );
1367
+ }
1368
+ `,
1369
+ "apps/mfe-auth/package.json": `{
1370
+ "name": "@mf-isolated/mfe-auth",
1371
+ "version": "1.0.0",
1372
+ "private": true,
1373
+ "scripts": {
1374
+ "dev": "webpack serve --config webpack.config.js",
1375
+ "build": "webpack --config webpack.config.js"
1376
+ },
1377
+ "dependencies": {
1378
+ "react": "^19.0.0",
1379
+ "react-dom": "^19.0.0"
1380
+ },
1381
+ "devDependencies": {
1382
+ "esbuild": "^0.28.0",
1383
+ "esbuild-loader": "^4.4.3",
1384
+ "html-webpack-plugin": "^5.6.7",
1385
+ "webpack": "^5.106.2",
1386
+ "webpack-cli": "^7.0.2",
1387
+ "webpack-dev-server": "^5.2.3"
1388
+ }
1389
+ }
1390
+ `,
1391
+ "apps/mfe-auth/webpack.config.js": `const HtmlWebpackPlugin = require("html-webpack-plugin");
1392
+ const { ModuleFederationPlugin } = require("webpack").container;
1393
+ const deps = require("./package.json").dependencies;
1394
+
1395
+ const MFE_AUTH_PORT = parseInt(process.env.MFE_AUTH_PORT || "3002");
1396
+
1397
+ module.exports = {
1398
+ mode: "development",
1399
+ entry: "./src/index.js",
1400
+ output: {
1401
+ publicPath: "auto",
1402
+ },
1403
+ resolve: { extensions: [".js", ".jsx"] },
1404
+ module: {
1405
+ rules: [
1406
+ {
1407
+ test: /\\.(js|jsx)$/,
1408
+ exclude: /node_modules/,
1409
+ use: {
1410
+ loader: "esbuild-loader",
1411
+ options: { loader: "jsx", jsx: "automatic", target: "es2020" },
1412
+ },
1413
+ },
1414
+ ],
1415
+ },
1416
+ plugins: [
1417
+ new ModuleFederationPlugin({
1418
+ name: "mfeAuth",
1419
+ filename: "remoteEntry.js",
1420
+ exposes: {
1421
+ // Key difference: we expose the MOUNT MODULE, not a React component.
1422
+ // The host never imports a JSX element from us directly.
1423
+ "./mount": "./src/mount.jsx",
1424
+ },
1425
+ // This remote brings its OWN React copy.
1426
+ // No singleton sharing with the host here.
1427
+ shared: {
1428
+ react: { requiredVersion: deps.react },
1429
+ "react-dom": { requiredVersion: deps["react-dom"] },
1430
+ },
1431
+ }),
1432
+ new HtmlWebpackPlugin({ template: "./public/index.html" }),
1433
+ ],
1434
+ devServer: {
1435
+ port: MFE_AUTH_PORT,
1436
+ headers: { "Access-Control-Allow-Origin": "*" },
1437
+ },
1438
+ };
1439
+ `,
1440
+ "apps/mfe-auth/public/index.html": `<!doctype html>
1441
+ <html lang="en">
1442
+ <head><meta charset="UTF-8" /><title>MFE Auth (standalone)</title></head>
1443
+ <body><div id="root"></div></body>
1444
+ </html>
1445
+ `,
1446
+ "apps/mfe-auth/src/index.js": `import("./bootstrap");
1447
+ `,
1448
+ "apps/mfe-auth/src/bootstrap.jsx": `// Standalone entry — only used when running mfe-auth on its own for development.
1449
+ import React from "react";
1450
+ import { createRoot } from "react-dom/client";
1451
+ import App from "./App";
1452
+
1453
+ createRoot(document.getElementById("root")).render(
1454
+ <App user={{ name: "Dev User", role: "developer" }} />
1455
+ );
1456
+ `,
1457
+ "apps/mfe-auth/src/App.jsx": `import React from "react";
1458
+
1459
+ // Standalone view — used for local development of the MFE in isolation.
1460
+ export default function App({ user = {} }) {
1461
+ return (
1462
+ <div style={{ padding: "1rem", fontFamily: "system-ui, sans-serif", background: "#0f172a", color: "#e2e8f0", minHeight: "100vh" }}>
1463
+ <h2 style={{ color: "#a78bfa", fontSize: "0.9rem", margin: "0 0 0.5rem" }}>
1464
+ mfe-auth — standalone dev view
1465
+ </h2>
1466
+ <AuthWidget user={user} />
1467
+ </div>
1468
+ );
1469
+ }
1470
+
1471
+ // The actual React component that this MFE renders.
1472
+ export function AuthWidget({ user = {} }) {
1473
+ return (
1474
+ <div style={{ padding: "0.75rem 1rem", background: "#1e293b", borderRadius: "6px", border: "1px solid #334155" }}>
1475
+ <p style={{ margin: 0, fontSize: "0.8rem", color: "#94a3b8" }}>Auth MFE — isolated React root</p>
1476
+ <p style={{ margin: "0.5rem 0 0", fontSize: "0.75rem", color: "#64748b" }}>
1477
+ Logged in as: <strong style={{ color: "#e2e8f0" }}>{user.name ?? "Guest"}</strong>
1478
+ {user.role && <span style={{ marginLeft: "0.5rem", color: "#6366f1" }}>({user.role})</span>}
1479
+ </p>
1480
+ <p style={{ margin: "0.5rem 0 0", fontSize: "0.7rem", color: "#334155", fontStyle: "italic" }}>
1481
+ This component lives in its own React root — not in the host tree.
1482
+ React context from the host does not reach here.
1483
+ </p>
1484
+ </div>
1485
+ );
1486
+ }
1487
+ `,
1488
+ "apps/mfe-auth/src/mount.jsx": `// ─────────────────────────────────────────────────────────────
1489
+ // mount.jsx — the public contract exposed via Module Federation
1490
+ //
1491
+ // The host imports THIS file, not a React component.
1492
+ // It calls mount(domElement, props) to render, unmount(domElement) to tear down.
1493
+ //
1494
+ // This is the core of the isolated MFE pattern:
1495
+ // 1. We create our OWN React root (not the host's)
1496
+ // 2. We own our own lifecycle
1497
+ // 3. The host never sees our React instance
1498
+ // ─────────────────────────────────────────────────────────────
1499
+ import React from "react";
1500
+ import { createRoot } from "react-dom/client";
1501
+ import { AuthWidget } from "./App";
1502
+
1503
+ // Keep track of roots by element so we can update or unmount them.
1504
+ const roots = new WeakMap();
1505
+
1506
+ /**
1507
+ * Mount the MFE into the given DOM element.
1508
+ *
1509
+ * @param {HTMLElement} el - the host-provided DOM node
1510
+ * @param {object} props - initial props from the host
1511
+ * @returns {{ unmount: () => void, update: (props: object) => void }}
1512
+ */
1513
+ export function mount(el, props = {}) {
1514
+ const root = createRoot(el);
1515
+ roots.set(el, root);
1516
+
1517
+ root.render(<AuthWidget {...props} />);
1518
+
1519
+ return {
1520
+ /** Call this to pass updated props from the host without remounting. */
1521
+ update(newProps) {
1522
+ root.render(<AuthWidget {...newProps} />);
1523
+ },
1524
+ /** Tear down the React root when the host removes this MFE. */
1525
+ unmount() {
1526
+ root.unmount();
1527
+ roots.delete(el);
1528
+ },
1529
+ };
1530
+ }
1531
+
1532
+ /**
1533
+ * Convenience function: unmount using only the element reference.
1534
+ * Useful if the host didn't store the return value of mount().
1535
+ */
1536
+ export function unmount(el) {
1537
+ const root = roots.get(el);
1538
+ if (root) {
1539
+ root.unmount();
1540
+ roots.delete(el);
1541
+ }
1542
+ }
1543
+ `,
1544
+ };
1545
+
1546
+ export const ISOLATED_MODULE_FEDERATION_LAB: FrontendLabWorkspace = {
1547
+ version: 1,
1548
+ label: "Webpack MF — Isolated Mount/Unmount",
1549
+ type: "module-federation",
1550
+ activeFile: "apps/mfe-auth/src/mount.jsx",
1551
+ files: MODULE_FEDERATION_ISOLATED_FILES,
1552
+ };
1553
+
1146
1554
  export function defaultForType(type: FrontendLabType): FrontendLabWorkspace {
1147
1555
  if (type === "nextjs") return DEFAULT_NEXTJS_LAB;
1148
1556
  if (type === "module-federation") return DEFAULT_MODULE_FEDERATION_LAB;
@@ -220,6 +220,7 @@ interface Store {
220
220
  | "user"
221
221
  | "ai"
222
222
  | "sandbox"
223
+ | "browser-security"
223
224
  | "infra"
224
225
  | "react"
225
226
  | "nextjs"
@@ -283,6 +284,8 @@ interface Store {
283
284
  clientCode: string;
284
285
  clientLang: string;
285
286
  fileId?: string;
287
+ label?: string;
288
+ origin?: "sandbox" | "browser-security";
286
289
  /** If set, the client panel opens in React or Next.js preview mode instead of script mode */
287
290
  clientType?: "script" | "react" | "nextjs" | "module-federation";
288
291
  reactFiles?: Record<string, string> | null;
@@ -298,6 +301,8 @@ interface Store {
298
301
  clientLang: string,
299
302
  fileId?: string,
300
303
  opts?: {
304
+ label?: string;
305
+ origin?: "sandbox" | "browser-security";
301
306
  clientType?: "script" | "react" | "nextjs" | "module-federation";
302
307
  reactFiles?: Record<string, string>;
303
308
  reactActiveFile?: string;
@@ -320,6 +325,11 @@ interface Store {
320
325
  openDeploymentLab: () => void;
321
326
  closeDeploymentLab: () => void;
322
327
 
328
+ // ── Browser Security Lab ─────────────────────────────────────
329
+ showBrowserSecurityLab: boolean;
330
+ openBrowserSecurityLab: () => void;
331
+ closeBrowserSecurityLab: () => void;
332
+
323
333
  // ── Infra Lab ────────────────────────────────────────────────
324
334
  showInfraLab: boolean;
325
335
  runnerInitialInfra: InfraLabWorkspace | null;
@@ -373,6 +383,7 @@ export const useStore = create<Store>((set, get) => ({
373
383
  runnerInitialSandbox: null,
374
384
  runnerInitialFileId: null,
375
385
  showDeploymentLab: false,
386
+ showBrowserSecurityLab: false,
376
387
  showInfraLab: false,
377
388
  runnerInitialInfra: null,
378
389
  runnerInitialInfraFileId: null,
@@ -971,6 +982,8 @@ export const useStore = create<Store>((set, get) => ({
971
982
  clientCode,
972
983
  clientLang,
973
984
  fileId,
985
+ label: opts?.label,
986
+ origin: opts?.origin,
974
987
  clientType: opts?.clientType,
975
988
  reactFiles: opts?.reactFiles,
976
989
  reactActiveFile: opts?.reactActiveFile,
@@ -1058,9 +1071,10 @@ export const useStore = create<Store>((set, get) => ({
1058
1071
  }));
1059
1072
  },
1060
1073
  closeCodeRunner: () => set({ showCodeRunner: false }),
1061
- showDeploymentLab: false,
1062
1074
  openDeploymentLab: () => set({ showDeploymentLab: true }),
1063
1075
  closeDeploymentLab: () => set({ showDeploymentLab: false }),
1076
+ openBrowserSecurityLab: () => set({ showBrowserSecurityLab: true }),
1077
+ closeBrowserSecurityLab: () => set({ showBrowserSecurityLab: false }),
1064
1078
  closeInfraLab: () => set({ showInfraLab: false }),
1065
1079
 
1066
1080
  fetchAiSettings: async () => {
@@ -3,6 +3,7 @@ export type ContextFileOrigin =
3
3
  | "ai"
4
4
  | "upload"
5
5
  | "sandbox"
6
+ | "browser-security"
6
7
  | "infra"
7
8
  | "react"
8
9
  | "nextjs"
@@ -17,6 +18,7 @@ export interface ContextFile {
17
18
  /** Distinguishes how this file was added. 'upload' = user-uploaded doc,
18
19
  * 'user' = code saved from Code Runner, 'ai' = AI-generated code block,
19
20
  * 'sandbox' = paired server+client sandbox saved as JSON,
21
+ * 'browser-security' = paired server+client security lab saved as JSON,
20
22
  * 'infra' = Terraform-style infra lab workspace saved as JSON. */
21
23
  origin?: ContextFileOrigin;
22
24
  /** Language hint for code snippets (e.g. 'typescript', 'javascript'). */
@@ -1 +1 @@
1
- {"root":["./src/app.tsx","./src/api.ts","./src/infralab.ts","./src/main.tsx","./src/reactlab.ts","./src/store.ts","./src/types.ts","./src/vite-env.d.ts","./src/components/aisettingsmodal.tsx","./src/components/annotationdialog.tsx","./src/components/chatmessage.tsx","./src/components/chatview.tsx","./src/components/codecontextpanel.tsx","./src/components/codelineannotationpopup.tsx","./src/components/coderunnermodal.tsx","./src/components/docrefmodal.tsx","./src/components/fileattachments.tsx","./src/components/filepickermodal.tsx","./src/components/fileviewermodal.tsx","./src/components/infralabmodal.tsx","./src/components/linkedconvospicker.tsx","./src/components/markdownrenderer.tsx","./src/components/mermaiddiagram.tsx","./src/components/notesmodal.tsx","./src/components/plotembed.tsx","./src/components/sidebar.tsx","./src/components/textannotator.tsx","./src/components/vizcraftembed.tsx","./src/components/workspaceswitcher.tsx"],"errors":true,"version":"5.9.3"}
1
+ {"root":["./src/app.tsx","./src/api.ts","./src/browsersecuritytemplates.ts","./src/infralab.ts","./src/main.tsx","./src/reactlab.ts","./src/store.ts","./src/types.ts","./src/vite-env.d.ts","./src/components/aisettingsmodal.tsx","./src/components/annotationdialog.tsx","./src/components/browsersecuritylabmodal.tsx","./src/components/chatmessage.tsx","./src/components/chatview.tsx","./src/components/codecontextpanel.tsx","./src/components/codelineannotationpopup.tsx","./src/components/coderunnermodal.tsx","./src/components/deploymentlabmodal.tsx","./src/components/docrefmodal.tsx","./src/components/fileattachments.tsx","./src/components/filepickermodal.tsx","./src/components/fileviewermodal.tsx","./src/components/infralabmodal.tsx","./src/components/labspanel.tsx","./src/components/linkedconvospicker.tsx","./src/components/markdownrenderer.tsx","./src/components/mermaiddiagram.tsx","./src/components/notesmodal.tsx","./src/components/plotembed.tsx","./src/components/sidebar.tsx","./src/components/textannotator.tsx","./src/components/vizcraftembed.tsx","./src/components/workspaceswitcher.tsx"],"errors":true,"version":"5.9.3"}
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "0.12.0"
2
+ "version": "0.13.0"
3
3
  }
@@ -358,6 +358,7 @@ export async function syncWorkspace(
358
358
  (cs.origin === "user" ||
359
359
  cs.origin === "ai" ||
360
360
  cs.origin === "sandbox" ||
361
+ cs.origin === "browser-security" ||
361
362
  cs.origin === "react" ||
362
363
  cs.origin === "nextjs" ||
363
364
  cs.origin === "module-federation" ||
@@ -769,6 +770,7 @@ export async function exportWorkspace(
769
770
  cf.origin === "user" ||
770
771
  cf.origin === "ai" ||
771
772
  cf.origin === "sandbox" ||
773
+ cf.origin === "browser-security" ||
772
774
  cf.origin === "react" ||
773
775
  cf.origin === "nextjs" ||
774
776
  cf.origin === "module-federation" ||