@trops/dash-core 0.1.508 → 0.1.509
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.
- package/dist/electron/index.js +207 -24
- package/dist/electron/index.js.map +1 -1
- package/package.json +1 -1
package/dist/electron/index.js
CHANGED
|
@@ -993,14 +993,14 @@ var events$8 = {
|
|
|
993
993
|
* Open a dialog window for choosing files
|
|
994
994
|
*/
|
|
995
995
|
|
|
996
|
-
const { dialog: dialog$
|
|
996
|
+
const { dialog: dialog$3 } = require$$0$1;
|
|
997
997
|
const events$7 = events$8;
|
|
998
998
|
|
|
999
999
|
const showDialog$1 = async (win, message, allowFile, extensions = ["*"]) => {
|
|
1000
1000
|
const properties =
|
|
1001
1001
|
allowFile === true ? ["openFile"] : ["openDirectory", "createDirectory"];
|
|
1002
1002
|
const filters = allowFile === true ? [{ name: "Data", extensions }] : [];
|
|
1003
|
-
const result = await dialog$
|
|
1003
|
+
const result = await dialog$3.showOpenDialog({ properties, filters });
|
|
1004
1004
|
if (result.canceled || !result.filePaths[0]) return null;
|
|
1005
1005
|
return result.filePaths[0];
|
|
1006
1006
|
};
|
|
@@ -2083,7 +2083,7 @@ var grantedPermissions = {
|
|
|
2083
2083
|
* _resetForTest() → void (test-only)
|
|
2084
2084
|
*/
|
|
2085
2085
|
|
|
2086
|
-
const { BrowserWindow: BrowserWindow$
|
|
2086
|
+
const { BrowserWindow: BrowserWindow$3, ipcMain: ipcMain$2 } = require$$0$1;
|
|
2087
2087
|
|
|
2088
2088
|
const REQUEST_CHANNEL = "widget:permission-required";
|
|
2089
2089
|
const RESPONSE_CHANNEL = "widget:permission-response";
|
|
@@ -2129,7 +2129,7 @@ function coalesceKeyOf(req) {
|
|
|
2129
2129
|
function emitEvent(payload) {
|
|
2130
2130
|
let wins = [];
|
|
2131
2131
|
try {
|
|
2132
|
-
wins = BrowserWindow$
|
|
2132
|
+
wins = BrowserWindow$3.getAllWindows() || [];
|
|
2133
2133
|
} catch {
|
|
2134
2134
|
wins = [];
|
|
2135
2135
|
}
|
|
@@ -34803,13 +34803,20 @@ boolean.parseBooleanDef = parseBooleanDef;
|
|
|
34803
34803
|
|
|
34804
34804
|
var branded = {};
|
|
34805
34805
|
|
|
34806
|
-
|
|
34807
|
-
|
|
34808
|
-
|
|
34809
|
-
|
|
34810
|
-
|
|
34806
|
+
var hasRequiredBranded;
|
|
34807
|
+
|
|
34808
|
+
function requireBranded () {
|
|
34809
|
+
if (hasRequiredBranded) return branded;
|
|
34810
|
+
hasRequiredBranded = 1;
|
|
34811
|
+
Object.defineProperty(branded, "__esModule", { value: true });
|
|
34812
|
+
branded.parseBrandedDef = void 0;
|
|
34813
|
+
const parseDef_js_1 = requireParseDef();
|
|
34814
|
+
function parseBrandedDef(_def, refs) {
|
|
34815
|
+
return (0, parseDef_js_1.parseDef)(_def.type._def, refs);
|
|
34816
|
+
}
|
|
34817
|
+
branded.parseBrandedDef = parseBrandedDef;
|
|
34818
|
+
return branded;
|
|
34811
34819
|
}
|
|
34812
|
-
branded.parseBrandedDef = parseBrandedDef;
|
|
34813
34820
|
|
|
34814
34821
|
var _catch = {};
|
|
34815
34822
|
|
|
@@ -35392,7 +35399,7 @@ function requireRecord () {
|
|
|
35392
35399
|
const v3_1 = v3;
|
|
35393
35400
|
const parseDef_js_1 = requireParseDef();
|
|
35394
35401
|
const string_js_1 = string;
|
|
35395
|
-
const branded_js_1 =
|
|
35402
|
+
const branded_js_1 = requireBranded();
|
|
35396
35403
|
const any_js_1 = any;
|
|
35397
35404
|
function parseRecordDef(def, refs) {
|
|
35398
35405
|
if (refs.target === "openAi") {
|
|
@@ -36043,7 +36050,7 @@ function requireSelectParser () {
|
|
|
36043
36050
|
const array_js_1 = requireArray();
|
|
36044
36051
|
const bigint_js_1 = bigint;
|
|
36045
36052
|
const boolean_js_1 = boolean;
|
|
36046
|
-
const branded_js_1 =
|
|
36053
|
+
const branded_js_1 = requireBranded();
|
|
36047
36054
|
const catch_js_1 = require_catch();
|
|
36048
36055
|
const date_js_1 = date;
|
|
36049
36056
|
const default_js_1 = require_default();
|
|
@@ -36342,7 +36349,7 @@ zodToJsonSchema$1.zodToJsonSchema = zodToJsonSchema;
|
|
|
36342
36349
|
__exportStar(requireArray(), exports);
|
|
36343
36350
|
__exportStar(bigint, exports);
|
|
36344
36351
|
__exportStar(boolean, exports);
|
|
36345
|
-
__exportStar(
|
|
36352
|
+
__exportStar(requireBranded(), exports);
|
|
36346
36353
|
__exportStar(require_catch(), exports);
|
|
36347
36354
|
__exportStar(date, exports);
|
|
36348
36355
|
__exportStar(require_default(), exports);
|
|
@@ -48733,7 +48740,7 @@ var jsonSchemaToZod_1 = { jsonSchemaToZod: jsonSchemaToZod$1, jsonSchemaProperty
|
|
|
48733
48740
|
|
|
48734
48741
|
const https$1 = require$$11;
|
|
48735
48742
|
const { randomUUID } = require$$3$4;
|
|
48736
|
-
const { BrowserWindow: BrowserWindow$
|
|
48743
|
+
const { BrowserWindow: BrowserWindow$2 } = require$$0$1;
|
|
48737
48744
|
const { McpServer } = mcp;
|
|
48738
48745
|
const {
|
|
48739
48746
|
StreamableHTTPServerTransport,
|
|
@@ -48777,7 +48784,7 @@ function broadcastStateChanged(toolName, result) {
|
|
|
48777
48784
|
/* leave null */
|
|
48778
48785
|
}
|
|
48779
48786
|
const payload = { toolName, result: parsed };
|
|
48780
|
-
for (const win of BrowserWindow$
|
|
48787
|
+
for (const win of BrowserWindow$2.getAllWindows()) {
|
|
48781
48788
|
if (!win.isDestroyed()) {
|
|
48782
48789
|
try {
|
|
48783
48790
|
win.webContents.send("dash-mcp:state-changed", payload);
|
|
@@ -57558,7 +57565,7 @@ function requireWidgetPublishManifest () {
|
|
|
57558
57565
|
* and registry interaction.
|
|
57559
57566
|
*/
|
|
57560
57567
|
const path$4 = require$$1$1;
|
|
57561
|
-
const { app: app$4, dialog: dialog$
|
|
57568
|
+
const { app: app$4, dialog: dialog$2 } = require$$0$1;
|
|
57562
57569
|
const AdmZip$2 = require$$3$2;
|
|
57563
57570
|
|
|
57564
57571
|
const themeController$3 = themeController_1;
|
|
@@ -57757,7 +57764,7 @@ async function prepareThemeForPublish$1(win, appId, themeKey, options = {}) {
|
|
|
57757
57764
|
const sanitizedName = sanitizeName(themeKey);
|
|
57758
57765
|
const defaultFilename = `theme-${sanitizedName}-v${manifest.version}.zip`;
|
|
57759
57766
|
|
|
57760
|
-
const saveResult = await dialog$
|
|
57767
|
+
const saveResult = await dialog$2.showSaveDialog(win, {
|
|
57761
57768
|
title: "Save Theme Package",
|
|
57762
57769
|
defaultPath: defaultFilename,
|
|
57763
57770
|
filters: [{ name: "ZIP Files", extensions: ["zip"] }],
|
|
@@ -58296,7 +58303,7 @@ var themeRegistryController$1 = {
|
|
|
58296
58303
|
* applies event wiring. (Import is implemented in DASH-13.)
|
|
58297
58304
|
*/
|
|
58298
58305
|
|
|
58299
|
-
const { app: app$3, dialog } = require$$0$1;
|
|
58306
|
+
const { app: app$3, dialog: dialog$1 } = require$$0$1;
|
|
58300
58307
|
const path$3 = require$$1$1;
|
|
58301
58308
|
const AdmZip$1 = require$$3$2;
|
|
58302
58309
|
const { getFileContents: getFileContents$1 } = file;
|
|
@@ -58458,7 +58465,7 @@ async function exportDashboardConfig$1(
|
|
|
58458
58465
|
.replace(/\s+/g, "-")
|
|
58459
58466
|
.toLowerCase();
|
|
58460
58467
|
|
|
58461
|
-
const { canceled, filePath } = await dialog.showSaveDialog(win, {
|
|
58468
|
+
const { canceled, filePath } = await dialog$1.showSaveDialog(win, {
|
|
58462
58469
|
title: "Export Dashboard as ZIP",
|
|
58463
58470
|
defaultPath: path$3.join(
|
|
58464
58471
|
app$3.getPath("desktop"),
|
|
@@ -58512,7 +58519,7 @@ async function exportDashboardConfig$1(
|
|
|
58512
58519
|
*/
|
|
58513
58520
|
async function selectDashboardFile$1(win) {
|
|
58514
58521
|
try {
|
|
58515
|
-
const { canceled, filePaths } = await dialog.showOpenDialog(win, {
|
|
58522
|
+
const { canceled, filePaths } = await dialog$1.showOpenDialog(win, {
|
|
58516
58523
|
title: "Import Dashboard Configuration",
|
|
58517
58524
|
filters: [{ name: "ZIP Archive", extensions: ["zip"] }],
|
|
58518
58525
|
properties: ["openFile"],
|
|
@@ -58619,7 +58626,7 @@ async function importDashboardConfig$1(
|
|
|
58619
58626
|
zipPath = options.filePath;
|
|
58620
58627
|
} else {
|
|
58621
58628
|
// Show file picker
|
|
58622
|
-
const { canceled, filePaths } = await dialog.showOpenDialog(win, {
|
|
58629
|
+
const { canceled, filePaths } = await dialog$1.showOpenDialog(win, {
|
|
58623
58630
|
title: "Import Dashboard Configuration",
|
|
58624
58631
|
filters: [{ name: "ZIP Archive", extensions: ["zip"] }],
|
|
58625
58632
|
properties: ["openFile"],
|
|
@@ -59967,7 +59974,7 @@ async function prepareDashboardForPublish$1(
|
|
|
59967
59974
|
|
|
59968
59975
|
// 9. Show save dialog for the publish package
|
|
59969
59976
|
const sanitizedName = manifest.name;
|
|
59970
|
-
const { canceled, filePath } = await dialog.showSaveDialog(win, {
|
|
59977
|
+
const { canceled, filePath } = await dialog$1.showSaveDialog(win, {
|
|
59971
59978
|
title: "Save Dashboard Package for Registry",
|
|
59972
59979
|
defaultPath: path$3.join(
|
|
59973
59980
|
app$3.getPath("desktop"),
|
|
@@ -61465,6 +61472,133 @@ function buildGrantsListing$1(
|
|
|
61465
61472
|
|
|
61466
61473
|
var widgetMcpGrantsListing = { buildGrantsListing: buildGrantsListing$1 };
|
|
61467
61474
|
|
|
61475
|
+
/**
|
|
61476
|
+
* grantDiff.js
|
|
61477
|
+
*
|
|
61478
|
+
* Pure-function diff between two grant blobs. Used by the
|
|
61479
|
+
* `widget-mcp:set-grant` IPC handler to decide whether the change
|
|
61480
|
+
* needs OS-native confirmation (broadening permissions) or can pass
|
|
61481
|
+
* through silently (revocations / equal / narrowing).
|
|
61482
|
+
*
|
|
61483
|
+
* Returns { broadening: boolean, summary: string[] }. `summary` is a
|
|
61484
|
+
* list of human-readable additions used to populate the native
|
|
61485
|
+
* confirm dialog.
|
|
61486
|
+
*
|
|
61487
|
+
* Broadening dimensions checked:
|
|
61488
|
+
* - servers: new server name present in newGrant.servers but not in
|
|
61489
|
+
* currentGrant.servers
|
|
61490
|
+
* - server tools: new tool name in an existing server's `tools[]`
|
|
61491
|
+
* - server paths: new entry in `readPaths[]` or `writePaths[]`
|
|
61492
|
+
* (including `*` wildcard added)
|
|
61493
|
+
* - domains.fs: new block, or new `readPaths[]` / `writePaths[]`
|
|
61494
|
+
* entry within an existing block (including `*`)
|
|
61495
|
+
* - domains.network: new block, or new `hosts[]` entry (including
|
|
61496
|
+
* `*` and `*.<base>` wildcards)
|
|
61497
|
+
*
|
|
61498
|
+
* Reductions, equality, and "no permission" → "no permission"
|
|
61499
|
+
* transitions are NOT broadening.
|
|
61500
|
+
*/
|
|
61501
|
+
|
|
61502
|
+
function _arr(x) {
|
|
61503
|
+
return Array.isArray(x) ? x : [];
|
|
61504
|
+
}
|
|
61505
|
+
|
|
61506
|
+
function _added(currentList, newList) {
|
|
61507
|
+
const cur = new Set(_arr(currentList));
|
|
61508
|
+
const out = [];
|
|
61509
|
+
for (const item of _arr(newList)) {
|
|
61510
|
+
if (!cur.has(item)) out.push(item);
|
|
61511
|
+
}
|
|
61512
|
+
return out;
|
|
61513
|
+
}
|
|
61514
|
+
|
|
61515
|
+
function _diffServer(serverName, currentSrv, newSrv) {
|
|
61516
|
+
const summary = [];
|
|
61517
|
+
const cur = currentSrv || {};
|
|
61518
|
+
const nxt = newSrv || {};
|
|
61519
|
+
|
|
61520
|
+
for (const tool of _added(cur.tools, nxt.tools)) {
|
|
61521
|
+
summary.push(`server "${serverName}" tool "${tool}"`);
|
|
61522
|
+
}
|
|
61523
|
+
for (const p of _added(cur.readPaths, nxt.readPaths)) {
|
|
61524
|
+
summary.push(`server "${serverName}" readPath "${p}"`);
|
|
61525
|
+
}
|
|
61526
|
+
for (const p of _added(cur.writePaths, nxt.writePaths)) {
|
|
61527
|
+
summary.push(`server "${serverName}" writePath "${p}"`);
|
|
61528
|
+
}
|
|
61529
|
+
return summary;
|
|
61530
|
+
}
|
|
61531
|
+
|
|
61532
|
+
function _diffServers(curServers, nxtServers) {
|
|
61533
|
+
const summary = [];
|
|
61534
|
+
const cur = curServers || {};
|
|
61535
|
+
const nxt = nxtServers || {};
|
|
61536
|
+
for (const name of Object.keys(nxt)) {
|
|
61537
|
+
if (!cur[name]) {
|
|
61538
|
+
// Whole new server entry → list each component as broadening.
|
|
61539
|
+
const srv = nxt[name];
|
|
61540
|
+
const tools = _arr(srv?.tools);
|
|
61541
|
+
const reads = _arr(srv?.readPaths);
|
|
61542
|
+
const writes = _arr(srv?.writePaths);
|
|
61543
|
+
if (tools.length === 0 && reads.length === 0 && writes.length === 0) {
|
|
61544
|
+
// Empty-shell server entry — no actual permissions added.
|
|
61545
|
+
// Skip; not a meaningful broadening.
|
|
61546
|
+
continue;
|
|
61547
|
+
}
|
|
61548
|
+
summary.push(`new server "${name}"`);
|
|
61549
|
+
for (const t of tools) summary.push(` tool "${t}"`);
|
|
61550
|
+
for (const p of reads) summary.push(` readPath "${p}"`);
|
|
61551
|
+
for (const p of writes) summary.push(` writePath "${p}"`);
|
|
61552
|
+
} else {
|
|
61553
|
+
summary.push(..._diffServer(name, cur[name], nxt[name]));
|
|
61554
|
+
}
|
|
61555
|
+
}
|
|
61556
|
+
return summary;
|
|
61557
|
+
}
|
|
61558
|
+
|
|
61559
|
+
function _diffDomainsFs(curFs, nxtFs) {
|
|
61560
|
+
const summary = [];
|
|
61561
|
+
const cur = curFs || {};
|
|
61562
|
+
const nxt = nxtFs || {};
|
|
61563
|
+
for (const p of _added(cur.readPaths, nxt.readPaths)) {
|
|
61564
|
+
summary.push(`fs readPath "${p}"`);
|
|
61565
|
+
}
|
|
61566
|
+
for (const p of _added(cur.writePaths, nxt.writePaths)) {
|
|
61567
|
+
summary.push(`fs writePath "${p}"`);
|
|
61568
|
+
}
|
|
61569
|
+
return summary;
|
|
61570
|
+
}
|
|
61571
|
+
|
|
61572
|
+
function _diffDomainsNetwork(curNet, nxtNet) {
|
|
61573
|
+
const summary = [];
|
|
61574
|
+
const cur = curNet || {};
|
|
61575
|
+
const nxt = nxtNet || {};
|
|
61576
|
+
for (const h of _added(cur.hosts, nxt.hosts)) {
|
|
61577
|
+
summary.push(`network host "${h}"`);
|
|
61578
|
+
}
|
|
61579
|
+
return summary;
|
|
61580
|
+
}
|
|
61581
|
+
|
|
61582
|
+
/**
|
|
61583
|
+
* @param {object|null|undefined} currentGrant
|
|
61584
|
+
* @param {object|null|undefined} newGrant
|
|
61585
|
+
* @returns {{ broadening: boolean, summary: string[] }}
|
|
61586
|
+
*/
|
|
61587
|
+
function isBroadening$1(currentGrant, newGrant) {
|
|
61588
|
+
const cur = currentGrant || {};
|
|
61589
|
+
const nxt = newGrant || {};
|
|
61590
|
+
|
|
61591
|
+
const summary = [
|
|
61592
|
+
..._diffServers(cur.servers, nxt.servers),
|
|
61593
|
+
..._diffDomainsFs(cur?.domains?.fs, nxt?.domains?.fs),
|
|
61594
|
+
..._diffDomainsNetwork(cur?.domains?.network, nxt?.domains?.network),
|
|
61595
|
+
];
|
|
61596
|
+
|
|
61597
|
+
return { broadening: summary.length > 0, summary };
|
|
61598
|
+
}
|
|
61599
|
+
|
|
61600
|
+
var grantDiff = { isBroadening: isBroadening$1 };
|
|
61601
|
+
|
|
61468
61602
|
/**
|
|
61469
61603
|
* widgetMcpGrantsController.js
|
|
61470
61604
|
*
|
|
@@ -61480,7 +61614,7 @@ var widgetMcpGrantsListing = { buildGrantsListing: buildGrantsListing$1 };
|
|
|
61480
61614
|
* grant are also surfaced — those are the install-consent retroactive prompts.
|
|
61481
61615
|
*/
|
|
61482
61616
|
|
|
61483
|
-
const { ipcMain: ipcMain$1 } = require$$0$1;
|
|
61617
|
+
const { ipcMain: ipcMain$1, dialog, BrowserWindow: BrowserWindow$1 } = require$$0$1;
|
|
61484
61618
|
const {
|
|
61485
61619
|
getGrant,
|
|
61486
61620
|
setGrant,
|
|
@@ -61491,13 +61625,62 @@ const {
|
|
|
61491
61625
|
const { getWidgetMcpPermissions } = widgetPermissions;
|
|
61492
61626
|
const { getWidgetRegistry } = widgetRegistryExports;
|
|
61493
61627
|
const { buildGrantsListing } = widgetMcpGrantsListing;
|
|
61628
|
+
const { isBroadening } = grantDiff;
|
|
61629
|
+
|
|
61630
|
+
// Native confirm dialog for any set-grant call that broadens the
|
|
61631
|
+
// widget's current permissions. The dialog runs at OS level — a
|
|
61632
|
+
// renderer (including a malicious widget) cannot dismiss it
|
|
61633
|
+
// programmatically. This is the defense-in-depth fix for the
|
|
61634
|
+
// `widget-mcp:set-grant` consent-bypass gap documented in the IPC
|
|
61635
|
+
// audit doc: a widget calling `mainApi.widgetMcp.setGrant("@self",
|
|
61636
|
+
// {wide-open perms})` now triggers a system-level prompt the user
|
|
61637
|
+
// must explicitly approve. Reductions / equality pass unprompted.
|
|
61638
|
+
async function _confirmBroadening(event, widgetId, summary) {
|
|
61639
|
+
const senderWindow =
|
|
61640
|
+
BrowserWindow$1.fromWebContents(event.sender) ||
|
|
61641
|
+
BrowserWindow$1.getFocusedWindow();
|
|
61642
|
+
// Cap the listed lines so the dialog body stays readable.
|
|
61643
|
+
const MAX_LINES = 20;
|
|
61644
|
+
const trimmed = summary.slice(0, MAX_LINES);
|
|
61645
|
+
const overflow =
|
|
61646
|
+
summary.length > MAX_LINES
|
|
61647
|
+
? `\n …and ${summary.length - MAX_LINES} more`
|
|
61648
|
+
: "";
|
|
61649
|
+
const detail =
|
|
61650
|
+
"Widget '" +
|
|
61651
|
+
widgetId +
|
|
61652
|
+
"' will be granted the following NEW permissions:\n\n " +
|
|
61653
|
+
trimmed.join("\n ") +
|
|
61654
|
+
overflow +
|
|
61655
|
+
"\n\nIf you didn't initiate this from Settings → Privacy & Security, " +
|
|
61656
|
+
"click Cancel — a malicious widget may be trying to escalate its own " +
|
|
61657
|
+
"permissions.";
|
|
61658
|
+
|
|
61659
|
+
const result = await dialog.showMessageBox(senderWindow, {
|
|
61660
|
+
type: "warning",
|
|
61661
|
+
title: "Confirm permissions change",
|
|
61662
|
+
message: "Allow new permissions for " + widgetId + "?",
|
|
61663
|
+
detail,
|
|
61664
|
+
buttons: ["Cancel", "Allow"],
|
|
61665
|
+
defaultId: 0,
|
|
61666
|
+
cancelId: 0,
|
|
61667
|
+
noLink: true,
|
|
61668
|
+
});
|
|
61669
|
+
return result.response === 1;
|
|
61670
|
+
}
|
|
61494
61671
|
|
|
61495
61672
|
function setupWidgetMcpGrantsHandlers() {
|
|
61496
61673
|
ipcMain$1.handle("widget-mcp:get-grant", (event, widgetId) => {
|
|
61497
61674
|
return getGrant(widgetId);
|
|
61498
61675
|
});
|
|
61499
61676
|
|
|
61500
|
-
ipcMain$1.handle("widget-mcp:set-grant", (event, widgetId, perms) => {
|
|
61677
|
+
ipcMain$1.handle("widget-mcp:set-grant", async (event, widgetId, perms) => {
|
|
61678
|
+
const current = getGrant(widgetId);
|
|
61679
|
+
const diff = isBroadening(current, perms);
|
|
61680
|
+
if (diff.broadening) {
|
|
61681
|
+
const approved = await _confirmBroadening(event, widgetId, diff.summary);
|
|
61682
|
+
if (!approved) return false;
|
|
61683
|
+
}
|
|
61501
61684
|
return setGrant(widgetId, perms);
|
|
61502
61685
|
});
|
|
61503
61686
|
|