@trops/dash-core 0.1.491 → 0.1.492

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.
@@ -17,7 +17,7 @@ var require$$0$5 = require('@modelcontextprotocol/sdk/client/index.js');
17
17
  var require$$1$4 = require('@modelcontextprotocol/sdk/client/stdio.js');
18
18
  var require$$0$4 = require('pkce-challenge');
19
19
  var require$$2$1 = require('os');
20
- var require$$10 = require('child_process');
20
+ var require$$11 = require('child_process');
21
21
  var require$$3$2 = require('adm-zip');
22
22
  var require$$4$1 = require('url');
23
23
  var require$$2$2 = require('vm');
@@ -21585,6 +21585,120 @@ var mcpServerKey = {
21585
21585
  SEP,
21586
21586
  };
21587
21587
 
21588
+ /**
21589
+ * mcpScopeResolver.js
21590
+ *
21591
+ * Slice 3b: per-workspace path scope reconfiguration.
21592
+ *
21593
+ * The Slice-3a process isolation key (`workspaceId::serverName`) is the
21594
+ * lifecycle handle. This module computes WHAT the spawned process is
21595
+ * configured to see — the union of granted paths from widgets on the
21596
+ * active workspace, applied as credential overrides at spawn time.
21597
+ *
21598
+ * Design:
21599
+ * - The renderer enumerates widgets on the active workspace, looks up
21600
+ * each widget's grant via window.mainApi.widgetMcp.getGrant, and
21601
+ * hands the array to unionPathScope() to compute the workspace
21602
+ * scope for a given server (e.g. "filesystem").
21603
+ * - The renderer passes the resulting scope as `pathScope` to
21604
+ * mcpStartServer.
21605
+ * - mcpController applies the scope to credentials (replacing
21606
+ * allowedPaths etc.) before its existing argsMapping spreads them
21607
+ * into the spawn args. Servers that don't declare argsMapping for
21608
+ * the path keys are unaffected.
21609
+ *
21610
+ * Feature flag: the controller only applies the override when
21611
+ * `security.enforceWidgetMcpPermissions` is on. When off, server starts
21612
+ * with credentials as-configured (pre-3b behavior).
21613
+ *
21614
+ * Out of scope here:
21615
+ * - Hot-respawn on widget add/remove (see Slice 3b plan, deferred).
21616
+ * - Catalog schema for new path-scoped servers (filesystem already
21617
+ * has argsMapping.allowedPaths; others added as discovered).
21618
+ */
21619
+
21620
+ /**
21621
+ * Compute the workspace-scoped path union for a given server.
21622
+ *
21623
+ * @param {Array<{widgetId, granted}>} grants - widgets-on-workspace + their grants
21624
+ * @param {string} serverName - the MCP server name (e.g. "filesystem")
21625
+ * @returns {{ readPaths: string[], writePaths: string[], allowedPaths: string[] }}
21626
+ *
21627
+ * `allowedPaths` is the dedup union of read+write — used by
21628
+ * filesystem-style servers that take a single allowed-list. Servers
21629
+ * that distinguish read-only vs read-write can use the readPaths /
21630
+ * writePaths arrays directly.
21631
+ */
21632
+ function unionPathScope(grants, serverName) {
21633
+ const reads = new Set();
21634
+ const writes = new Set();
21635
+
21636
+ if (!Array.isArray(grants)) {
21637
+ return { readPaths: [], writePaths: [], allowedPaths: [] };
21638
+ }
21639
+
21640
+ for (const entry of grants) {
21641
+ if (!entry || typeof entry !== "object") continue;
21642
+ const granted = entry.granted;
21643
+ if (!granted || typeof granted !== "object") continue;
21644
+ const servers = granted.servers;
21645
+ if (!servers || typeof servers !== "object") continue;
21646
+ const serverPerms = servers[serverName];
21647
+ if (!serverPerms || typeof serverPerms !== "object") continue;
21648
+
21649
+ if (Array.isArray(serverPerms.readPaths)) {
21650
+ for (const p of serverPerms.readPaths) {
21651
+ if (typeof p === "string" && p) reads.add(p);
21652
+ }
21653
+ }
21654
+ if (Array.isArray(serverPerms.writePaths)) {
21655
+ for (const p of serverPerms.writePaths) {
21656
+ if (typeof p === "string" && p) writes.add(p);
21657
+ }
21658
+ }
21659
+ }
21660
+
21661
+ const readPaths = [...reads];
21662
+ const writePaths = [...writes];
21663
+ const allowedPaths = [...new Set([...reads, ...writes])];
21664
+
21665
+ return { readPaths, writePaths, allowedPaths };
21666
+ }
21667
+
21668
+ /**
21669
+ * Override credential keys with values derived from a path scope.
21670
+ *
21671
+ * Filesystem-style servers expect `allowedPaths` as a comma-separated
21672
+ * string (the catalog's `argsMapping.allowedPaths.split` then expands
21673
+ * it back into positional args at spawn time). This helper joins the
21674
+ * scope's allowedPaths to match that convention.
21675
+ *
21676
+ * Returns a NEW credentials object — does not mutate the input.
21677
+ *
21678
+ * If pathScope is empty (no granted paths at all), the existing
21679
+ * credentials are returned unchanged so the user's globally-configured
21680
+ * allowedPaths still works for the LLM tool path / NO_WORKSPACE bucket.
21681
+ */
21682
+ function applyPathScopeToCredentials$1(credentials, pathScope) {
21683
+ const base =
21684
+ credentials && typeof credentials === "object" ? { ...credentials } : {};
21685
+
21686
+ if (!pathScope || typeof pathScope !== "object") return base;
21687
+
21688
+ const allowed = Array.isArray(pathScope.allowedPaths)
21689
+ ? pathScope.allowedPaths
21690
+ : [];
21691
+ if (allowed.length === 0) return base;
21692
+
21693
+ base.allowedPaths = allowed.join(",");
21694
+ return base;
21695
+ }
21696
+
21697
+ var mcpScopeResolver = {
21698
+ unionPathScope,
21699
+ applyPathScopeToCredentials: applyPathScopeToCredentials$1,
21700
+ };
21701
+
21588
21702
  /**
21589
21703
  * mcpController.js
21590
21704
  *
@@ -21611,6 +21725,7 @@ const os$2 = require$$2$1;
21611
21725
  const responseCache$2 = responseCache_1;
21612
21726
  const { gateToolCall } = permissionGate;
21613
21727
  const { serverKey, parseServerKey } = mcpServerKey;
21728
+ const { applyPathScopeToCredentials } = mcpScopeResolver;
21614
21729
  const { app: app$7 } = require$$0$1;
21615
21730
 
21616
21731
  // Read the widget-MCP-enforcement feature flag from settings.json.
@@ -21767,7 +21882,7 @@ function getShellPath$1() {
21767
21882
  return _shellPath$1;
21768
21883
  }
21769
21884
 
21770
- const { execSync } = require$$10;
21885
+ const { execSync } = require$$11;
21771
21886
  const fallbackDirs = ["/usr/local/bin", "/opt/homebrew/bin"];
21772
21887
 
21773
21888
  // Scan nvm versions, tracking both latest and best compatible version
@@ -22005,15 +22120,41 @@ const mcpController$3 = {
22005
22120
  * Pass `null`/`undefined` workspaceId to land on the legacy
22006
22121
  * NO_WORKSPACE bucket (e.g. dash MCP server tools, AI Builder previews).
22007
22122
  *
22123
+ * Slice 3b: when `security.enforceWidgetMcpPermissions` is on AND a
22124
+ * non-empty `pathScope` is supplied, the scope's allowed paths
22125
+ * override the server's existing path-style credentials before the
22126
+ * catalog's argsMapping spreads them into spawn args. This scopes
22127
+ * the server's OS-level capability to the union of widget grants on
22128
+ * the active workspace.
22129
+ *
22008
22130
  * @param {BrowserWindow} win the main window
22009
22131
  * @param {string} serverName unique name for this server instance
22010
22132
  * @param {object} mcpConfig { transport, command, args, envMapping }
22011
22133
  * @param {object} credentials decrypted credentials object
22012
22134
  * @param {string|null} workspaceId active workspace id (Slice 3a)
22135
+ * @param {object|null} pathScope { readPaths, writePaths, allowedPaths } (Slice 3b)
22013
22136
  * @returns {{ success, serverName, tools, status } | { error, message }}
22014
22137
  */
22015
- startServer: async (win, serverName, mcpConfig, credentials, workspaceId) => {
22138
+ startServer: async (
22139
+ win,
22140
+ serverName,
22141
+ mcpConfig,
22142
+ credentials,
22143
+ workspaceId,
22144
+ pathScope = null,
22145
+ ) => {
22016
22146
  const key = serverKey(workspaceId, serverName);
22147
+ // Slice 3b: when the gate is enforced, override credentials with
22148
+ // the workspace's union of granted paths so the spawned process
22149
+ // can't see anything broader than the user has consented to.
22150
+ if (
22151
+ isWidgetPermissionEnforcementEnabled() &&
22152
+ pathScope &&
22153
+ Array.isArray(pathScope.allowedPaths) &&
22154
+ pathScope.allowedPaths.length > 0
22155
+ ) {
22156
+ credentials = applyPathScopeToCredentials(credentials, pathScope);
22157
+ }
22017
22158
  // 1. Already connected? Return existing connection
22018
22159
  const existing = activeServers.get(key);
22019
22160
  if (existing && existing.status === STATUS$1.CONNECTED && existing.client) {
@@ -22695,7 +22836,7 @@ const mcpController$3 = {
22695
22836
  * @returns {{ success } | { error, message }}
22696
22837
  */
22697
22838
  runAuth: async (win, mcpConfig, credentials, authCommand) => {
22698
- const { spawn } = require$$10;
22839
+ const { spawn } = require$$11;
22699
22840
 
22700
22841
  const env = cleanEnvForChildProcess();
22701
22842
 
@@ -47862,7 +48003,7 @@ var mcpDashServerController_1 = mcpDashServerController$4;
47862
48003
  * can use the Chat widget without a separate API key.
47863
48004
  */
47864
48005
 
47865
- const { spawn, execSync } = require$$10;
48006
+ const { spawn, execSync } = require$$11;
47866
48007
  const {
47867
48008
  LLM_STREAM_DELTA: LLM_STREAM_DELTA$2,
47868
48009
  LLM_STREAM_TOOL_CALL: LLM_STREAM_TOOL_CALL$2,
@@ -62253,14 +62394,25 @@ const mcpApi$2 = {
62253
62394
  * @param {object} credentials decrypted credentials object
62254
62395
  * @param {string|null} workspaceId active workspace id (Slice 3a) —
62255
62396
  * server processes are keyed per workspace.
62397
+ * @param {object|null} pathScope (Slice 3b) — when provided, the
62398
+ * workspace's union of granted paths overrides the server's
62399
+ * path-style credentials at spawn time. Shape:
62400
+ * `{ readPaths, writePaths, allowedPaths }`.
62256
62401
  * @returns {Promise<{ success, serverName, tools, status } | { error, message }>}
62257
62402
  */
62258
- startServer: (serverName, mcpConfig, credentials, workspaceId = null) =>
62403
+ startServer: (
62404
+ serverName,
62405
+ mcpConfig,
62406
+ credentials,
62407
+ workspaceId = null,
62408
+ pathScope = null,
62409
+ ) =>
62259
62410
  ipcRenderer$i.invoke(MCP_START_SERVER, {
62260
62411
  serverName,
62261
62412
  mcpConfig,
62262
62413
  credentials,
62263
62414
  workspaceId,
62415
+ pathScope,
62264
62416
  }),
62265
62417
 
62266
62418
  /**