@objectstack/core 2.0.1 → 2.0.3
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +15 -0
- package/dist/index.cjs +121 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -11
- package/dist/index.d.ts +10 -11
- package/dist/index.js +121 -42
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/hot-reload.ts +4 -12
- package/src/qa/runner.ts +12 -4
- package/src/security/plugin-permission-enforcer.ts +29 -9
- package/src/security/plugin-signature-verifier.ts +48 -7
- package/src/security/sandbox-runtime.ts +61 -34
package/dist/index.d.cts
CHANGED
|
@@ -1236,6 +1236,7 @@ declare class PluginPermissionEnforcer {
|
|
|
1236
1236
|
private checkPermission;
|
|
1237
1237
|
private checkServiceAccess;
|
|
1238
1238
|
private checkHookAccess;
|
|
1239
|
+
private matchGlob;
|
|
1239
1240
|
private checkFileRead;
|
|
1240
1241
|
private checkFileWrite;
|
|
1241
1242
|
private checkNetworkAccess;
|
|
@@ -1395,9 +1396,12 @@ interface SandboxContext {
|
|
|
1395
1396
|
* and access controls
|
|
1396
1397
|
*/
|
|
1397
1398
|
declare class PluginSandboxRuntime {
|
|
1399
|
+
private static readonly MONITORING_INTERVAL_MS;
|
|
1398
1400
|
private logger;
|
|
1399
1401
|
private sandboxes;
|
|
1400
1402
|
private monitoringIntervals;
|
|
1403
|
+
private memoryBaselines;
|
|
1404
|
+
private cpuBaselines;
|
|
1401
1405
|
constructor(logger: ObjectLogger);
|
|
1402
1406
|
/**
|
|
1403
1407
|
* Create a sandbox for a plugin
|
|
@@ -1416,14 +1420,12 @@ declare class PluginSandboxRuntime {
|
|
|
1416
1420
|
};
|
|
1417
1421
|
/**
|
|
1418
1422
|
* Check file system access
|
|
1419
|
-
*
|
|
1420
|
-
* resolution with path.resolve() and path.normalize() to prevent traversal.
|
|
1423
|
+
* Uses path.resolve() and path.normalize() to prevent directory traversal.
|
|
1421
1424
|
*/
|
|
1422
1425
|
private checkFileAccess;
|
|
1423
1426
|
/**
|
|
1424
1427
|
* Check network access
|
|
1425
|
-
*
|
|
1426
|
-
* parsing with new URL() and check hostname property.
|
|
1428
|
+
* Uses URL parsing to properly validate hostnames.
|
|
1427
1429
|
*/
|
|
1428
1430
|
private checkNetworkAccess;
|
|
1429
1431
|
/**
|
|
@@ -1456,10 +1458,9 @@ declare class PluginSandboxRuntime {
|
|
|
1456
1458
|
/**
|
|
1457
1459
|
* Update resource usage statistics
|
|
1458
1460
|
*
|
|
1459
|
-
*
|
|
1460
|
-
*
|
|
1461
|
-
* per-plugin
|
|
1462
|
-
* plugin boundaries.
|
|
1461
|
+
* Tracks per-plugin memory and CPU usage using delta from baseline
|
|
1462
|
+
* captured at sandbox creation time. This is an approximation since
|
|
1463
|
+
* true per-plugin isolation isn't possible in a single Node.js process.
|
|
1463
1464
|
*/
|
|
1464
1465
|
private updateResourceUsage;
|
|
1465
1466
|
/**
|
|
@@ -1667,9 +1668,7 @@ declare class PluginStateManager {
|
|
|
1667
1668
|
*/
|
|
1668
1669
|
clearState(pluginId: string): void;
|
|
1669
1670
|
/**
|
|
1670
|
-
* Calculate
|
|
1671
|
-
* WARNING: This is a simple hash for demo purposes.
|
|
1672
|
-
* In production, use a cryptographic hash like SHA-256.
|
|
1671
|
+
* Calculate checksum for state verification using SHA-256.
|
|
1673
1672
|
*/
|
|
1674
1673
|
private calculateChecksum;
|
|
1675
1674
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1236,6 +1236,7 @@ declare class PluginPermissionEnforcer {
|
|
|
1236
1236
|
private checkPermission;
|
|
1237
1237
|
private checkServiceAccess;
|
|
1238
1238
|
private checkHookAccess;
|
|
1239
|
+
private matchGlob;
|
|
1239
1240
|
private checkFileRead;
|
|
1240
1241
|
private checkFileWrite;
|
|
1241
1242
|
private checkNetworkAccess;
|
|
@@ -1395,9 +1396,12 @@ interface SandboxContext {
|
|
|
1395
1396
|
* and access controls
|
|
1396
1397
|
*/
|
|
1397
1398
|
declare class PluginSandboxRuntime {
|
|
1399
|
+
private static readonly MONITORING_INTERVAL_MS;
|
|
1398
1400
|
private logger;
|
|
1399
1401
|
private sandboxes;
|
|
1400
1402
|
private monitoringIntervals;
|
|
1403
|
+
private memoryBaselines;
|
|
1404
|
+
private cpuBaselines;
|
|
1401
1405
|
constructor(logger: ObjectLogger);
|
|
1402
1406
|
/**
|
|
1403
1407
|
* Create a sandbox for a plugin
|
|
@@ -1416,14 +1420,12 @@ declare class PluginSandboxRuntime {
|
|
|
1416
1420
|
};
|
|
1417
1421
|
/**
|
|
1418
1422
|
* Check file system access
|
|
1419
|
-
*
|
|
1420
|
-
* resolution with path.resolve() and path.normalize() to prevent traversal.
|
|
1423
|
+
* Uses path.resolve() and path.normalize() to prevent directory traversal.
|
|
1421
1424
|
*/
|
|
1422
1425
|
private checkFileAccess;
|
|
1423
1426
|
/**
|
|
1424
1427
|
* Check network access
|
|
1425
|
-
*
|
|
1426
|
-
* parsing with new URL() and check hostname property.
|
|
1428
|
+
* Uses URL parsing to properly validate hostnames.
|
|
1427
1429
|
*/
|
|
1428
1430
|
private checkNetworkAccess;
|
|
1429
1431
|
/**
|
|
@@ -1456,10 +1458,9 @@ declare class PluginSandboxRuntime {
|
|
|
1456
1458
|
/**
|
|
1457
1459
|
* Update resource usage statistics
|
|
1458
1460
|
*
|
|
1459
|
-
*
|
|
1460
|
-
*
|
|
1461
|
-
* per-plugin
|
|
1462
|
-
* plugin boundaries.
|
|
1461
|
+
* Tracks per-plugin memory and CPU usage using delta from baseline
|
|
1462
|
+
* captured at sandbox creation time. This is an approximation since
|
|
1463
|
+
* true per-plugin isolation isn't possible in a single Node.js process.
|
|
1463
1464
|
*/
|
|
1464
1465
|
private updateResourceUsage;
|
|
1465
1466
|
/**
|
|
@@ -1667,9 +1668,7 @@ declare class PluginStateManager {
|
|
|
1667
1668
|
*/
|
|
1668
1669
|
clearState(pluginId: string): void;
|
|
1669
1670
|
/**
|
|
1670
|
-
* Calculate
|
|
1671
|
-
* WARNING: This is a simple hash for demo purposes.
|
|
1672
|
-
* In production, use a cryptographic hash like SHA-256.
|
|
1671
|
+
* Calculate checksum for state verification using SHA-256.
|
|
1673
1672
|
*/
|
|
1674
1673
|
private calculateChecksum;
|
|
1675
1674
|
/**
|
package/dist/index.js
CHANGED
|
@@ -2081,8 +2081,18 @@ var TestRunner = class {
|
|
|
2081
2081
|
}
|
|
2082
2082
|
return result;
|
|
2083
2083
|
}
|
|
2084
|
-
resolveVariables(action,
|
|
2085
|
-
|
|
2084
|
+
resolveVariables(action, context) {
|
|
2085
|
+
const actionStr = JSON.stringify(action);
|
|
2086
|
+
const resolved = actionStr.replace(/\{\{([^}]+)\}\}/g, (_match, varPath) => {
|
|
2087
|
+
const value = this.getValueByPath(context, varPath.trim());
|
|
2088
|
+
if (value === void 0) return _match;
|
|
2089
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
2090
|
+
});
|
|
2091
|
+
try {
|
|
2092
|
+
return JSON.parse(resolved);
|
|
2093
|
+
} catch {
|
|
2094
|
+
return action;
|
|
2095
|
+
}
|
|
2086
2096
|
}
|
|
2087
2097
|
getValueByPath(obj, path) {
|
|
2088
2098
|
if (!path) return obj;
|
|
@@ -2419,9 +2429,38 @@ var PluginSignatureVerifier = class {
|
|
|
2419
2429
|
return false;
|
|
2420
2430
|
}
|
|
2421
2431
|
}
|
|
2422
|
-
async verifyCryptoSignatureBrowser(
|
|
2423
|
-
|
|
2424
|
-
|
|
2432
|
+
async verifyCryptoSignatureBrowser(data, signature, publicKey) {
|
|
2433
|
+
try {
|
|
2434
|
+
const subtle = globalThis.crypto?.subtle;
|
|
2435
|
+
if (!subtle) {
|
|
2436
|
+
this.logger.error("SubtleCrypto not available in this environment");
|
|
2437
|
+
return false;
|
|
2438
|
+
}
|
|
2439
|
+
const pemBody = publicKey.replace(/-----BEGIN PUBLIC KEY-----/, "").replace(/-----END PUBLIC KEY-----/, "").replace(/\s/g, "");
|
|
2440
|
+
const keyBytes = Uint8Array.from(atob(pemBody), (c) => c.charCodeAt(0));
|
|
2441
|
+
let importAlgorithm;
|
|
2442
|
+
let verifyAlgorithm;
|
|
2443
|
+
if (this.config.algorithm === "ES256") {
|
|
2444
|
+
importAlgorithm = { name: "ECDSA", namedCurve: "P-256" };
|
|
2445
|
+
verifyAlgorithm = { name: "ECDSA", hash: "SHA-256" };
|
|
2446
|
+
} else {
|
|
2447
|
+
importAlgorithm = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" };
|
|
2448
|
+
verifyAlgorithm = { name: "RSASSA-PKCS1-v1_5" };
|
|
2449
|
+
}
|
|
2450
|
+
const cryptoKey = await subtle.importKey(
|
|
2451
|
+
"spki",
|
|
2452
|
+
keyBytes,
|
|
2453
|
+
importAlgorithm,
|
|
2454
|
+
false,
|
|
2455
|
+
["verify"]
|
|
2456
|
+
);
|
|
2457
|
+
const signatureBytes = Uint8Array.from(atob(signature), (c) => c.charCodeAt(0));
|
|
2458
|
+
const dataBytes = new TextEncoder().encode(data);
|
|
2459
|
+
return await subtle.verify(verifyAlgorithm, cryptoKey, signatureBytes, dataBytes);
|
|
2460
|
+
} catch (error) {
|
|
2461
|
+
this.logger.error("Browser signature verification failed", error);
|
|
2462
|
+
return false;
|
|
2463
|
+
}
|
|
2425
2464
|
}
|
|
2426
2465
|
validateConfig() {
|
|
2427
2466
|
if (!this.config.trustedPublicKeys || this.config.trustedPublicKeys.size === 0) {
|
|
@@ -2639,29 +2678,48 @@ var PluginPermissionEnforcer = class {
|
|
|
2639
2678
|
return false;
|
|
2640
2679
|
});
|
|
2641
2680
|
}
|
|
2642
|
-
|
|
2681
|
+
matchGlob(pattern, str) {
|
|
2682
|
+
const regexStr = pattern.split("**").map((segment) => {
|
|
2683
|
+
const escaped = segment.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
|
|
2684
|
+
return escaped.replace(/\*/g, "[^/]*");
|
|
2685
|
+
}).join(".*");
|
|
2686
|
+
return new RegExp(`^${regexStr}$`).test(str);
|
|
2687
|
+
}
|
|
2688
|
+
checkFileRead(capabilities, path) {
|
|
2643
2689
|
return capabilities.some((cap) => {
|
|
2644
2690
|
const protocolId = cap.protocol.id;
|
|
2645
2691
|
if (protocolId.includes("protocol.filesystem.read")) {
|
|
2646
|
-
|
|
2692
|
+
const paths = cap.metadata?.paths;
|
|
2693
|
+
if (!Array.isArray(paths) || paths.length === 0) {
|
|
2694
|
+
return true;
|
|
2695
|
+
}
|
|
2696
|
+
return paths.some((p) => typeof p === "string" && this.matchGlob(p, path));
|
|
2647
2697
|
}
|
|
2648
2698
|
return false;
|
|
2649
2699
|
});
|
|
2650
2700
|
}
|
|
2651
|
-
checkFileWrite(capabilities,
|
|
2701
|
+
checkFileWrite(capabilities, path) {
|
|
2652
2702
|
return capabilities.some((cap) => {
|
|
2653
2703
|
const protocolId = cap.protocol.id;
|
|
2654
2704
|
if (protocolId.includes("protocol.filesystem.write")) {
|
|
2655
|
-
|
|
2705
|
+
const paths = cap.metadata?.paths;
|
|
2706
|
+
if (!Array.isArray(paths) || paths.length === 0) {
|
|
2707
|
+
return true;
|
|
2708
|
+
}
|
|
2709
|
+
return paths.some((p) => typeof p === "string" && this.matchGlob(p, path));
|
|
2656
2710
|
}
|
|
2657
2711
|
return false;
|
|
2658
2712
|
});
|
|
2659
2713
|
}
|
|
2660
|
-
checkNetworkAccess(capabilities,
|
|
2714
|
+
checkNetworkAccess(capabilities, url) {
|
|
2661
2715
|
return capabilities.some((cap) => {
|
|
2662
2716
|
const protocolId = cap.protocol.id;
|
|
2663
2717
|
if (protocolId.includes("protocol.network")) {
|
|
2664
|
-
|
|
2718
|
+
const hosts = cap.metadata?.hosts;
|
|
2719
|
+
if (!Array.isArray(hosts) || hosts.length === 0) {
|
|
2720
|
+
return true;
|
|
2721
|
+
}
|
|
2722
|
+
return hosts.some((h) => typeof h === "string" && this.matchGlob(h, url));
|
|
2665
2723
|
}
|
|
2666
2724
|
return false;
|
|
2667
2725
|
});
|
|
@@ -2928,12 +2986,16 @@ var PluginPermissionManager = class {
|
|
|
2928
2986
|
};
|
|
2929
2987
|
|
|
2930
2988
|
// src/security/sandbox-runtime.ts
|
|
2931
|
-
|
|
2989
|
+
import nodePath from "path";
|
|
2990
|
+
var _PluginSandboxRuntime = class _PluginSandboxRuntime {
|
|
2932
2991
|
constructor(logger) {
|
|
2933
2992
|
// Active sandboxes (pluginId -> context)
|
|
2934
2993
|
this.sandboxes = /* @__PURE__ */ new Map();
|
|
2935
2994
|
// Resource monitoring intervals
|
|
2936
2995
|
this.monitoringIntervals = /* @__PURE__ */ new Map();
|
|
2996
|
+
// Per-plugin resource baselines for delta tracking
|
|
2997
|
+
this.memoryBaselines = /* @__PURE__ */ new Map();
|
|
2998
|
+
this.cpuBaselines = /* @__PURE__ */ new Map();
|
|
2937
2999
|
this.logger = logger.child({ component: "SandboxRuntime" });
|
|
2938
3000
|
}
|
|
2939
3001
|
/**
|
|
@@ -2954,6 +3016,9 @@ var PluginSandboxRuntime = class {
|
|
|
2954
3016
|
}
|
|
2955
3017
|
};
|
|
2956
3018
|
this.sandboxes.set(pluginId, context);
|
|
3019
|
+
const baselineMemory = getMemoryUsage();
|
|
3020
|
+
this.memoryBaselines.set(pluginId, baselineMemory.heapUsed);
|
|
3021
|
+
this.cpuBaselines.set(pluginId, process.cpuUsage());
|
|
2957
3022
|
this.startResourceMonitoring(pluginId);
|
|
2958
3023
|
this.logger.info("Sandbox created", {
|
|
2959
3024
|
pluginId,
|
|
@@ -2972,6 +3037,8 @@ var PluginSandboxRuntime = class {
|
|
|
2972
3037
|
return;
|
|
2973
3038
|
}
|
|
2974
3039
|
this.stopResourceMonitoring(pluginId);
|
|
3040
|
+
this.memoryBaselines.delete(pluginId);
|
|
3041
|
+
this.cpuBaselines.delete(pluginId);
|
|
2975
3042
|
this.sandboxes.delete(pluginId);
|
|
2976
3043
|
this.logger.info("Sandbox destroyed", { pluginId });
|
|
2977
3044
|
}
|
|
@@ -2999,45 +3066,46 @@ var PluginSandboxRuntime = class {
|
|
|
2999
3066
|
}
|
|
3000
3067
|
/**
|
|
3001
3068
|
* Check file system access
|
|
3002
|
-
*
|
|
3003
|
-
* resolution with path.resolve() and path.normalize() to prevent traversal.
|
|
3069
|
+
* Uses path.resolve() and path.normalize() to prevent directory traversal.
|
|
3004
3070
|
*/
|
|
3005
|
-
checkFileAccess(config,
|
|
3071
|
+
checkFileAccess(config, filePath) {
|
|
3006
3072
|
if (config.level === "none") {
|
|
3007
3073
|
return { allowed: true };
|
|
3008
3074
|
}
|
|
3009
3075
|
if (!config.filesystem) {
|
|
3010
3076
|
return { allowed: false, reason: "File system access not configured" };
|
|
3011
3077
|
}
|
|
3012
|
-
if (!
|
|
3078
|
+
if (!filePath) {
|
|
3013
3079
|
return { allowed: config.filesystem.mode !== "none" };
|
|
3014
3080
|
}
|
|
3015
3081
|
const allowedPaths = config.filesystem.allowedPaths || [];
|
|
3082
|
+
const resolvedPath = nodePath.normalize(nodePath.resolve(filePath));
|
|
3016
3083
|
const isAllowed = allowedPaths.some((allowed) => {
|
|
3017
|
-
|
|
3084
|
+
const resolvedAllowed = nodePath.normalize(nodePath.resolve(allowed));
|
|
3085
|
+
return resolvedPath.startsWith(resolvedAllowed);
|
|
3018
3086
|
});
|
|
3019
3087
|
if (allowedPaths.length > 0 && !isAllowed) {
|
|
3020
3088
|
return {
|
|
3021
3089
|
allowed: false,
|
|
3022
|
-
reason: `Path not in allowed list: ${
|
|
3090
|
+
reason: `Path not in allowed list: ${filePath}`
|
|
3023
3091
|
};
|
|
3024
3092
|
}
|
|
3025
3093
|
const deniedPaths = config.filesystem.deniedPaths || [];
|
|
3026
3094
|
const isDenied = deniedPaths.some((denied) => {
|
|
3027
|
-
|
|
3095
|
+
const resolvedDenied = nodePath.normalize(nodePath.resolve(denied));
|
|
3096
|
+
return resolvedPath.startsWith(resolvedDenied);
|
|
3028
3097
|
});
|
|
3029
3098
|
if (isDenied) {
|
|
3030
3099
|
return {
|
|
3031
3100
|
allowed: false,
|
|
3032
|
-
reason: `Path is explicitly denied: ${
|
|
3101
|
+
reason: `Path is explicitly denied: ${filePath}`
|
|
3033
3102
|
};
|
|
3034
3103
|
}
|
|
3035
3104
|
return { allowed: true };
|
|
3036
3105
|
}
|
|
3037
3106
|
/**
|
|
3038
3107
|
* Check network access
|
|
3039
|
-
*
|
|
3040
|
-
* parsing with new URL() and check hostname property.
|
|
3108
|
+
* Uses URL parsing to properly validate hostnames.
|
|
3041
3109
|
*/
|
|
3042
3110
|
checkNetworkAccess(config, url) {
|
|
3043
3111
|
if (config.level === "none") {
|
|
@@ -3052,10 +3120,16 @@ var PluginSandboxRuntime = class {
|
|
|
3052
3120
|
if (!url) {
|
|
3053
3121
|
return { allowed: config.network.mode !== "none" };
|
|
3054
3122
|
}
|
|
3123
|
+
let parsedHostname;
|
|
3124
|
+
try {
|
|
3125
|
+
parsedHostname = new URL(url).hostname;
|
|
3126
|
+
} catch {
|
|
3127
|
+
return { allowed: false, reason: `Invalid URL: ${url}` };
|
|
3128
|
+
}
|
|
3055
3129
|
const allowedHosts = config.network.allowedHosts || [];
|
|
3056
3130
|
if (allowedHosts.length > 0) {
|
|
3057
3131
|
const isAllowed = allowedHosts.some((host) => {
|
|
3058
|
-
return
|
|
3132
|
+
return parsedHostname === host;
|
|
3059
3133
|
});
|
|
3060
3134
|
if (!isAllowed) {
|
|
3061
3135
|
return {
|
|
@@ -3066,7 +3140,7 @@ var PluginSandboxRuntime = class {
|
|
|
3066
3140
|
}
|
|
3067
3141
|
const deniedHosts = config.network.deniedHosts || [];
|
|
3068
3142
|
const isDenied = deniedHosts.some((host) => {
|
|
3069
|
-
return
|
|
3143
|
+
return parsedHostname === host;
|
|
3070
3144
|
});
|
|
3071
3145
|
if (isDenied) {
|
|
3072
3146
|
return {
|
|
@@ -3143,7 +3217,7 @@ var PluginSandboxRuntime = class {
|
|
|
3143
3217
|
startResourceMonitoring(pluginId) {
|
|
3144
3218
|
const interval = setInterval(() => {
|
|
3145
3219
|
this.updateResourceUsage(pluginId);
|
|
3146
|
-
},
|
|
3220
|
+
}, _PluginSandboxRuntime.MONITORING_INTERVAL_MS);
|
|
3147
3221
|
this.monitoringIntervals.set(pluginId, interval);
|
|
3148
3222
|
}
|
|
3149
3223
|
/**
|
|
@@ -3159,10 +3233,9 @@ var PluginSandboxRuntime = class {
|
|
|
3159
3233
|
/**
|
|
3160
3234
|
* Update resource usage statistics
|
|
3161
3235
|
*
|
|
3162
|
-
*
|
|
3163
|
-
*
|
|
3164
|
-
* per-plugin
|
|
3165
|
-
* plugin boundaries.
|
|
3236
|
+
* Tracks per-plugin memory and CPU usage using delta from baseline
|
|
3237
|
+
* captured at sandbox creation time. This is an approximation since
|
|
3238
|
+
* true per-plugin isolation isn't possible in a single Node.js process.
|
|
3166
3239
|
*/
|
|
3167
3240
|
updateResourceUsage(pluginId) {
|
|
3168
3241
|
const context = this.sandboxes.get(pluginId);
|
|
@@ -3170,12 +3243,21 @@ var PluginSandboxRuntime = class {
|
|
|
3170
3243
|
return;
|
|
3171
3244
|
}
|
|
3172
3245
|
const memoryUsage = getMemoryUsage();
|
|
3173
|
-
|
|
3246
|
+
const memoryBaseline = this.memoryBaselines.get(pluginId) ?? 0;
|
|
3247
|
+
const memoryDelta = Math.max(0, memoryUsage.heapUsed - memoryBaseline);
|
|
3248
|
+
context.resourceUsage.memory.current = memoryDelta;
|
|
3174
3249
|
context.resourceUsage.memory.peak = Math.max(
|
|
3175
3250
|
context.resourceUsage.memory.peak,
|
|
3176
|
-
|
|
3251
|
+
memoryDelta
|
|
3177
3252
|
);
|
|
3178
|
-
|
|
3253
|
+
const cpuBaseline = this.cpuBaselines.get(pluginId) ?? { user: 0, system: 0 };
|
|
3254
|
+
const cpuCurrent = process.cpuUsage();
|
|
3255
|
+
const cpuDeltaUser = cpuCurrent.user - cpuBaseline.user;
|
|
3256
|
+
const cpuDeltaSystem = cpuCurrent.system - cpuBaseline.system;
|
|
3257
|
+
const totalCpuMicros = cpuDeltaUser + cpuDeltaSystem;
|
|
3258
|
+
const intervalMicros = _PluginSandboxRuntime.MONITORING_INTERVAL_MS * 1e3;
|
|
3259
|
+
context.resourceUsage.cpu.current = totalCpuMicros / intervalMicros * 100;
|
|
3260
|
+
this.cpuBaselines.set(pluginId, cpuCurrent);
|
|
3179
3261
|
const { withinLimits, violations } = this.checkResourceLimits(pluginId);
|
|
3180
3262
|
if (!withinLimits) {
|
|
3181
3263
|
this.logger.warn("Resource limit violations detected", {
|
|
@@ -3198,9 +3280,13 @@ var PluginSandboxRuntime = class {
|
|
|
3198
3280
|
this.stopResourceMonitoring(pluginId);
|
|
3199
3281
|
}
|
|
3200
3282
|
this.sandboxes.clear();
|
|
3283
|
+
this.memoryBaselines.clear();
|
|
3284
|
+
this.cpuBaselines.clear();
|
|
3201
3285
|
this.logger.info("Sandbox runtime shutdown complete");
|
|
3202
3286
|
}
|
|
3203
3287
|
};
|
|
3288
|
+
_PluginSandboxRuntime.MONITORING_INTERVAL_MS = 5e3;
|
|
3289
|
+
var PluginSandboxRuntime = _PluginSandboxRuntime;
|
|
3204
3290
|
|
|
3205
3291
|
// src/security/security-scanner.ts
|
|
3206
3292
|
var PluginSecurityScanner = class {
|
|
@@ -3667,6 +3753,7 @@ var PluginHealthMonitor = class {
|
|
|
3667
3753
|
};
|
|
3668
3754
|
|
|
3669
3755
|
// src/hot-reload.ts
|
|
3756
|
+
import { createHash } from "crypto";
|
|
3670
3757
|
var generateUUID = () => {
|
|
3671
3758
|
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
3672
3759
|
return crypto.randomUUID();
|
|
@@ -3757,19 +3844,11 @@ var PluginStateManager = class {
|
|
|
3757
3844
|
this.logger.debug("State cleared", { pluginId });
|
|
3758
3845
|
}
|
|
3759
3846
|
/**
|
|
3760
|
-
* Calculate
|
|
3761
|
-
* WARNING: This is a simple hash for demo purposes.
|
|
3762
|
-
* In production, use a cryptographic hash like SHA-256.
|
|
3847
|
+
* Calculate checksum for state verification using SHA-256.
|
|
3763
3848
|
*/
|
|
3764
3849
|
calculateChecksum(state) {
|
|
3765
3850
|
const stateStr = JSON.stringify(state);
|
|
3766
|
-
|
|
3767
|
-
for (let i = 0; i < stateStr.length; i++) {
|
|
3768
|
-
const char = stateStr.charCodeAt(i);
|
|
3769
|
-
hash = (hash << 5) - hash + char;
|
|
3770
|
-
hash = hash & hash;
|
|
3771
|
-
}
|
|
3772
|
-
return hash.toString(16);
|
|
3851
|
+
return createHash("sha256").update(stateStr).digest("hex");
|
|
3773
3852
|
}
|
|
3774
3853
|
/**
|
|
3775
3854
|
* Shutdown state manager
|