@vinkius-core/mcp-fusion 2.12.0 → 2.13.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.
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@
11
11
  * ├── observability/ ← Debug Observer, Tracing
12
12
  * ├── presenter/ ← MVA View Layer
13
13
  * ├── prompt/ ← Prompt Engine
14
+ * ├── sandbox/ ← Zero-Trust V8 Computation Delegation
14
15
  * ├── server/ ← Server Attachment
15
16
  * ├── exposition/ ← Flat/Grouped Topology Compiler
16
17
  * ├── state-sync/ ← Epistemic Cache-Control
@@ -95,4 +96,7 @@ export { createProbe, buildJudgePrompt, parseJudgeResponse, evaluateProbe, evalu
95
96
  export { enrichValidationError, createToolEnhancer, } from './introspection/ContractAwareSelfHealing.js';
96
97
  /** @category Governance */
97
98
  export { createGovernanceObserver, createNoopObserver, } from './introspection/GovernanceObserver.js';
99
+ // ── Sandbox (Zero-Trust V8 Compute Delegation) ──────────
100
+ /** @category Sandbox */
101
+ export { SandboxEngine, validateSandboxCode, SANDBOX_SYSTEM_INSTRUCTION } from './sandbox/index.js';
98
102
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,4DAA4D;AAC5D,8BAA8B;AAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,8BAA8B;AAC9B,OAAO,EAAa,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACzD,8BAA8B;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,8BAA8B;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,8BAA8B;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,8BAA8B;AAC9B,OAAO,EAAoB,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,8BAA8B;AAC9B,OAAO,EAAwB,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAC1F,8BAA8B;AAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,8BAA8B;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,8BAA8B;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,8BAA8B;AAC9B,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,4DAA4D;AAC5D,2BAA2B;AAC3B,OAAO,EACH,aAAa,EACQ,kBAAkB,EACnB,iBAAiB,EACf,mBAAmB,EACjB,qBAAqB,EACd,4BAA4B,EAC9D,MAAM,uBAAuB,CAAC;AAE/B,4DAA4D;AAC5D,qBAAqB;AACrB,OAAO,EACH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAChD,kBAAkB,EAAE,kBAAkB,EAAE,UAAU,EAAE,UAAU,EAC9D,YAAY,EACZ,uBAAuB,EACvB,OAAO,EAAE,IAAI,EACb,QAAQ,EACR,gBAAgB,EAAE,iBAAiB,EACnC,UAAU,EACV,WAAW,EACX,mBAAmB,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa;AACnE,aAAa;AACb,iBAAiB,EAAE,YAAY,GAClC,MAAM,iBAAiB,CAAC;AAoBzB,4DAA4D;AAC5D,uBAAuB;AACvB,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAI/F,4DAA4D;AAC5D,8BAA8B;AAC9B,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAS/E,4DAA4D;AAC5D,0BAA0B;AAC1B,OAAO,EACH,eAAe,EAAE,QAAQ,EAAE,iBAAiB,EAC5C,EAAE,EAAE,CAAC,EAAE,OAAO,EACd,SAAS,EAAE,eAAe,EAAE,WAAW,EACvC,wBAAwB,EACxB,eAAe,EACf,sBAAsB,GACzB,MAAM,sBAAsB,CAAC;AAI9B,4DAA4D;AAC5D,uBAAuB;AACvB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACpG,uBAAuB;AACvB,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAa5D,uBAAuB;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,uBAAuB;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAQpD,4DAA4D;AAC5D,0BAA0B;AAC1B,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAOhG,4DAA4D;AAC5D,wBAAwB;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAI7D,4DAA4D;AAC5D,2BAA2B;AAC3B,OAAO,EACH,mBAAmB,EACnB,gBAAgB,EAChB,MAAM,EACN,YAAY,GACf,MAAM,iCAAiC,CAAC;AAWzC,2BAA2B;AAC3B,OAAO,EACH,aAAa,EACb,gBAAgB,EAChB,iBAAiB,GACpB,MAAM,iCAAiC,CAAC;AAQzC,2BAA2B;AAC3B,OAAO,EACH,aAAa,EACb,mBAAmB,EACnB,oBAAoB,GACvB,MAAM,mCAAmC,CAAC;AAQ3C,4DAA4D;AAC5D,2BAA2B;AAC3B,OAAO,EACH,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,GAChB,MAAM,uCAAuC,CAAC;AAgB/C,2BAA2B;AAC3B,OAAO,EACH,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,GACnB,MAAM,sCAAsC,CAAC;AAQ9C,2BAA2B;AAC3B,OAAO,EACH,cAAc,EACd,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,iBAAiB,GACpB,MAAM,mCAAmC,CAAC;AAY3C,2BAA2B;AAC3B,OAAO,EACH,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,eAAe,GAClB,MAAM,uCAAuC,CAAC;AAS/C,2BAA2B;AAC3B,OAAO,EACH,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,gBAAgB,GACnB,MAAM,kCAAkC,CAAC;AAU1C,2BAA2B;AAC3B,OAAO,EACH,qBAAqB,EACrB,kBAAkB,GACrB,MAAM,6CAA6C,CAAC;AAMrD,2BAA2B;AAC3B,OAAO,EACH,wBAAwB,EACxB,kBAAkB,GACrB,MAAM,uCAAuC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,4DAA4D;AAC5D,8BAA8B;AAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,8BAA8B;AAC9B,OAAO,EAAa,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACzD,8BAA8B;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,8BAA8B;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,8BAA8B;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,8BAA8B;AAC9B,OAAO,EAAoB,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,8BAA8B;AAC9B,OAAO,EAAwB,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAC1F,8BAA8B;AAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,8BAA8B;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,8BAA8B;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,8BAA8B;AAC9B,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,4DAA4D;AAC5D,2BAA2B;AAC3B,OAAO,EACH,aAAa,EACQ,kBAAkB,EACnB,iBAAiB,EACf,mBAAmB,EACjB,qBAAqB,EACd,4BAA4B,EAC9D,MAAM,uBAAuB,CAAC;AAE/B,4DAA4D;AAC5D,qBAAqB;AACrB,OAAO,EACH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAChD,kBAAkB,EAAE,kBAAkB,EAAE,UAAU,EAAE,UAAU,EAC9D,YAAY,EACZ,uBAAuB,EACvB,OAAO,EAAE,IAAI,EACb,QAAQ,EACR,gBAAgB,EAAE,iBAAiB,EACnC,UAAU,EACV,WAAW,EACX,mBAAmB,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa;AACnE,aAAa;AACb,iBAAiB,EAAE,YAAY,GAClC,MAAM,iBAAiB,CAAC;AAqBzB,4DAA4D;AAC5D,uBAAuB;AACvB,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAI/F,4DAA4D;AAC5D,8BAA8B;AAC9B,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAS/E,4DAA4D;AAC5D,0BAA0B;AAC1B,OAAO,EACH,eAAe,EAAE,QAAQ,EAAE,iBAAiB,EAC5C,EAAE,EAAE,CAAC,EAAE,OAAO,EACd,SAAS,EAAE,eAAe,EAAE,WAAW,EACvC,wBAAwB,EACxB,eAAe,EACf,sBAAsB,GACzB,MAAM,sBAAsB,CAAC;AAI9B,4DAA4D;AAC5D,uBAAuB;AACvB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACpG,uBAAuB;AACvB,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAa5D,uBAAuB;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,uBAAuB;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAQpD,4DAA4D;AAC5D,0BAA0B;AAC1B,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAOhG,4DAA4D;AAC5D,wBAAwB;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAI7D,4DAA4D;AAC5D,2BAA2B;AAC3B,OAAO,EACH,mBAAmB,EACnB,gBAAgB,EAChB,MAAM,EACN,YAAY,GACf,MAAM,iCAAiC,CAAC;AAWzC,2BAA2B;AAC3B,OAAO,EACH,aAAa,EACb,gBAAgB,EAChB,iBAAiB,GACpB,MAAM,iCAAiC,CAAC;AAQzC,2BAA2B;AAC3B,OAAO,EACH,aAAa,EACb,mBAAmB,EACnB,oBAAoB,GACvB,MAAM,mCAAmC,CAAC;AAQ3C,4DAA4D;AAC5D,2BAA2B;AAC3B,OAAO,EACH,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,GAChB,MAAM,uCAAuC,CAAC;AAgB/C,2BAA2B;AAC3B,OAAO,EACH,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,GACnB,MAAM,sCAAsC,CAAC;AAQ9C,2BAA2B;AAC3B,OAAO,EACH,cAAc,EACd,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,iBAAiB,GACpB,MAAM,mCAAmC,CAAC;AAY3C,2BAA2B;AAC3B,OAAO,EACH,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,eAAe,GAClB,MAAM,uCAAuC,CAAC;AAS/C,2BAA2B;AAC3B,OAAO,EACH,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,gBAAgB,GACnB,MAAM,kCAAkC,CAAC;AAU1C,2BAA2B;AAC3B,OAAO,EACH,qBAAqB,EACrB,kBAAkB,GACrB,MAAM,6CAA6C,CAAC;AAMrD,2BAA2B;AAC3B,OAAO,EACH,wBAAwB,EACxB,kBAAkB,GACrB,MAAM,uCAAuC,CAAC;AAO/C,2DAA2D;AAC3D,wBAAwB;AACxB,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,188 @@
1
+ /**
2
+ * SandboxEngine — Zero-Trust V8 Isolate for Computation Delegation
3
+ *
4
+ * Allows LLMs to send JavaScript functions as strings to be executed
5
+ * in a sealed V8 isolate. The data stays on the client's machine,
6
+ * only the result travels back to the LLM.
7
+ *
8
+ * Architecture (V8 Engineering Rules):
9
+ * 1. ONE Isolate per SandboxEngine (boot ~5-10ms), reused across requests
10
+ * 2. NEW Context per execute() call (~0.1ms), pristine and empty
11
+ * 3. ExternalCopy + Script + Context are ALWAYS released in `finally`
12
+ * 4. Execution is ALWAYS async (script.run, never runSync)
13
+ * 5. Context is empty — no process, require, fs, globalThis injected
14
+ *
15
+ * The `isolated-vm` package is a peerDependency (optional).
16
+ * If not installed, the engine throws a clear error at construction time.
17
+ *
18
+ * ┌─────────────────────────────────────────────────┐
19
+ * │ SandboxEngine (owns 1 Isolate) │
20
+ * │ │
21
+ * │ execute(code, data) │
22
+ * │ ┌──────────┐ │
23
+ * │ │ Guard │ fail-fast syntax check │
24
+ * │ ├──────────┤ │
25
+ * │ │ Context │ new per request (empty!) │
26
+ * │ ├──────────┤ │
27
+ * │ │ Copy In │ ExternalCopy (deep, no refs) │
28
+ * │ ├──────────┤ │
29
+ * │ │ Compile │ isolate.compileScript │
30
+ * │ ├──────────┤ │
31
+ * │ │ Run │ script.run (ASYNC, with timeout) │
32
+ * │ ├──────────┤ │
33
+ * │ │ Copy Out │ JSON.parse result │
34
+ * │ └──────────┘ │
35
+ * │ │
36
+ * │ finally: inputCopy.release() │
37
+ * │ script.release() │
38
+ * │ context.release() │
39
+ * └─────────────────────────────────────────────────┘
40
+ *
41
+ * @module
42
+ */
43
+ /**
44
+ * Configuration for a SandboxEngine instance.
45
+ *
46
+ * All fields are optional — sensible defaults are applied.
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * const engine = new SandboxEngine({
51
+ * timeout: 3000, // Kill after 3s
52
+ * memoryLimit: 64, // 64MB per isolate
53
+ * maxOutputBytes: 512_000, // 500KB max result
54
+ * });
55
+ * ```
56
+ */
57
+ export interface SandboxConfig {
58
+ /**
59
+ * Maximum execution time in milliseconds.
60
+ * If the script exceeds this, the V8 isolate kills it.
61
+ * @default 5000
62
+ */
63
+ timeout?: number;
64
+ /**
65
+ * Maximum memory for the V8 isolate in megabytes.
66
+ * If exceeded, the isolate dies and is recreated on next call.
67
+ * @default 128
68
+ */
69
+ memoryLimit?: number;
70
+ /**
71
+ * Maximum size of the serialized output in bytes.
72
+ * Prevents a malicious script from returning gigabytes of data.
73
+ * @default 1_048_576 (1MB)
74
+ */
75
+ maxOutputBytes?: number;
76
+ }
77
+ /**
78
+ * Error codes for sandbox execution failures.
79
+ *
80
+ * - `TIMEOUT`: Script exceeded the time limit
81
+ * - `MEMORY`: Isolate ran out of memory (auto-recovered)
82
+ * - `SYNTAX`: JavaScript syntax error in the provided code
83
+ * - `RUNTIME`: Script threw an error during execution
84
+ * - `OUTPUT_TOO_LARGE`: Result exceeds `maxOutputBytes`
85
+ * - `INVALID_CODE`: Failed the SandboxGuard fail-fast check
86
+ * - `UNAVAILABLE`: `isolated-vm` is not installed
87
+ */
88
+ export type SandboxErrorCode = 'TIMEOUT' | 'MEMORY' | 'SYNTAX' | 'RUNTIME' | 'OUTPUT_TOO_LARGE' | 'INVALID_CODE' | 'UNAVAILABLE';
89
+ /**
90
+ * Result of a sandbox execution.
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * const result = await engine.execute('(data) => data.length', [1, 2, 3]);
95
+ * if (result.ok) {
96
+ * console.log(result.value); // 3
97
+ * console.log(result.executionMs); // 0.42
98
+ * } else {
99
+ * console.log(result.code); // 'TIMEOUT'
100
+ * console.log(result.error); // 'Script execution timed out (5000ms)'
101
+ * }
102
+ * ```
103
+ */
104
+ export type SandboxResult<T = unknown> = {
105
+ readonly ok: true;
106
+ readonly value: T;
107
+ readonly executionMs: number;
108
+ } | {
109
+ readonly ok: false;
110
+ readonly error: string;
111
+ readonly code: SandboxErrorCode;
112
+ };
113
+ /**
114
+ * Zero-trust V8 sandbox for executing LLM-provided JavaScript.
115
+ *
116
+ * Creates a single V8 `Isolate` at construction time and reuses it
117
+ * across all `execute()` calls. Each call gets a fresh, empty `Context`
118
+ * with no dangerous globals (no `process`, `require`, `fs`, etc.).
119
+ *
120
+ * If the isolate dies (e.g., OOM), it is automatically recreated
121
+ * on the next `execute()` call.
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * const sandbox = new SandboxEngine({ timeout: 3000, memoryLimit: 64 });
126
+ *
127
+ * const result = await sandbox.execute(
128
+ * '(data) => data.filter(d => d.risk > 90)',
129
+ * [{ name: 'A', risk: 95 }, { name: 'B', risk: 30 }],
130
+ * );
131
+ *
132
+ * if (result.ok) {
133
+ * console.log(result.value); // [{ name: 'A', risk: 95 }]
134
+ * }
135
+ *
136
+ * // IMPORTANT: dispose when no longer needed
137
+ * sandbox.dispose();
138
+ * ```
139
+ */
140
+ export declare class SandboxEngine {
141
+ private readonly _timeout;
142
+ private readonly _memoryLimit;
143
+ private readonly _maxOutputBytes;
144
+ private _isolate;
145
+ private _disposed;
146
+ constructor(config?: SandboxConfig);
147
+ /**
148
+ * Execute a JavaScript function string against the provided data.
149
+ *
150
+ * The function is compiled and run in a sealed V8 isolate with:
151
+ * - No `process`, `require`, `fs`, or network access
152
+ * - Strict timeout enforcement (async, non-blocking)
153
+ * - Memory limit enforcement
154
+ * - Automatic C++ pointer cleanup (ExternalCopy, Script, Context)
155
+ *
156
+ * @param code - A JavaScript function expression as a string.
157
+ * Must be an arrow function or function expression.
158
+ * Example: `(data) => data.filter(d => d.value > 10)`
159
+ *
160
+ * @param data - The data to pass into the function.
161
+ * Deeply copied into the isolate (no references leak).
162
+ *
163
+ * @returns A `SandboxResult` with the computed value or an error.
164
+ */
165
+ execute<T = unknown>(code: string, data: unknown): Promise<SandboxResult<T>>;
166
+ /**
167
+ * Release all resources held by this engine.
168
+ *
169
+ * After calling `dispose()`, any subsequent `execute()` calls
170
+ * will return `{ ok: false, code: 'UNAVAILABLE' }`.
171
+ */
172
+ dispose(): void;
173
+ /**
174
+ * Check if the engine has been disposed.
175
+ */
176
+ get isDisposed(): boolean;
177
+ /**
178
+ * Ensure the isolate is alive. If it died (OOM), create a new one.
179
+ * @internal
180
+ */
181
+ private _ensureIsolate;
182
+ /**
183
+ * Classify an error from V8 execution into a typed SandboxResult.
184
+ * @internal
185
+ */
186
+ private _classifyError;
187
+ }
188
+ //# sourceMappingURL=SandboxEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SandboxEngine.d.ts","sourceRoot":"","sources":["../../src/sandbox/SandboxEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAMH;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,aAAa;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,gBAAgB,GACtB,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,kBAAkB,GAClB,cAAc,GACd,aAAa,CAAC;AAEpB;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,OAAO,IAC/B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACtE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAkCtF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,aAAa;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IAEzC,OAAO,CAAC,QAAQ,CAAM;IACtB,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,CAAC,EAAE,aAAa;IAgBlC;;;;;;;;;;;;;;;;;OAiBG;IACG,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAsElF;;;;;OAKG;IACH,OAAO,IAAI,IAAI;IAUf;;OAEG;IACH,IAAI,UAAU,IAAI,OAAO,CAExB;IAID;;;OAGG;IACH,OAAO,CAAC,cAAc;IAatB;;;OAGG;IACH,OAAO,CAAC,cAAc;CA6CzB"}
@@ -0,0 +1,290 @@
1
+ /**
2
+ * SandboxEngine — Zero-Trust V8 Isolate for Computation Delegation
3
+ *
4
+ * Allows LLMs to send JavaScript functions as strings to be executed
5
+ * in a sealed V8 isolate. The data stays on the client's machine,
6
+ * only the result travels back to the LLM.
7
+ *
8
+ * Architecture (V8 Engineering Rules):
9
+ * 1. ONE Isolate per SandboxEngine (boot ~5-10ms), reused across requests
10
+ * 2. NEW Context per execute() call (~0.1ms), pristine and empty
11
+ * 3. ExternalCopy + Script + Context are ALWAYS released in `finally`
12
+ * 4. Execution is ALWAYS async (script.run, never runSync)
13
+ * 5. Context is empty — no process, require, fs, globalThis injected
14
+ *
15
+ * The `isolated-vm` package is a peerDependency (optional).
16
+ * If not installed, the engine throws a clear error at construction time.
17
+ *
18
+ * ┌─────────────────────────────────────────────────┐
19
+ * │ SandboxEngine (owns 1 Isolate) │
20
+ * │ │
21
+ * │ execute(code, data) │
22
+ * │ ┌──────────┐ │
23
+ * │ │ Guard │ fail-fast syntax check │
24
+ * │ ├──────────┤ │
25
+ * │ │ Context │ new per request (empty!) │
26
+ * │ ├──────────┤ │
27
+ * │ │ Copy In │ ExternalCopy (deep, no refs) │
28
+ * │ ├──────────┤ │
29
+ * │ │ Compile │ isolate.compileScript │
30
+ * │ ├──────────┤ │
31
+ * │ │ Run │ script.run (ASYNC, with timeout) │
32
+ * │ ├──────────┤ │
33
+ * │ │ Copy Out │ JSON.parse result │
34
+ * │ └──────────┘ │
35
+ * │ │
36
+ * │ finally: inputCopy.release() │
37
+ * │ script.release() │
38
+ * │ context.release() │
39
+ * └─────────────────────────────────────────────────┘
40
+ *
41
+ * @module
42
+ */
43
+ import { validateSandboxCode } from './SandboxGuard.js';
44
+ // ── Constants ────────────────────────────────────────────
45
+ const DEFAULT_TIMEOUT_MS = 5_000;
46
+ const DEFAULT_MEMORY_LIMIT_MB = 128;
47
+ const DEFAULT_MAX_OUTPUT_BYTES = 1_048_576; // 1MB
48
+ // ── Lazy Require ─────────────────────────────────────────
49
+ /**
50
+ * Lazy-load isolated-vm to avoid hard dependency.
51
+ * Returns `null` if the package is not installed.
52
+ * @internal
53
+ */
54
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
+ let _ivm = undefined;
56
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
+ function getIvm() {
58
+ if (_ivm !== undefined)
59
+ return _ivm;
60
+ try {
61
+ // Dynamic import would be cleaner but isolated-vm uses
62
+ // native bindings that require synchronous resolution.
63
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
64
+ _ivm = require('isolated-vm');
65
+ }
66
+ catch {
67
+ _ivm = null;
68
+ }
69
+ return _ivm;
70
+ }
71
+ // ── Engine Implementation ────────────────────────────────
72
+ /**
73
+ * Zero-trust V8 sandbox for executing LLM-provided JavaScript.
74
+ *
75
+ * Creates a single V8 `Isolate` at construction time and reuses it
76
+ * across all `execute()` calls. Each call gets a fresh, empty `Context`
77
+ * with no dangerous globals (no `process`, `require`, `fs`, etc.).
78
+ *
79
+ * If the isolate dies (e.g., OOM), it is automatically recreated
80
+ * on the next `execute()` call.
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * const sandbox = new SandboxEngine({ timeout: 3000, memoryLimit: 64 });
85
+ *
86
+ * const result = await sandbox.execute(
87
+ * '(data) => data.filter(d => d.risk > 90)',
88
+ * [{ name: 'A', risk: 95 }, { name: 'B', risk: 30 }],
89
+ * );
90
+ *
91
+ * if (result.ok) {
92
+ * console.log(result.value); // [{ name: 'A', risk: 95 }]
93
+ * }
94
+ *
95
+ * // IMPORTANT: dispose when no longer needed
96
+ * sandbox.dispose();
97
+ * ```
98
+ */
99
+ export class SandboxEngine {
100
+ _timeout;
101
+ _memoryLimit;
102
+ _maxOutputBytes;
103
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
104
+ _isolate; // ivm.Isolate
105
+ _disposed = false;
106
+ constructor(config) {
107
+ this._timeout = config?.timeout ?? DEFAULT_TIMEOUT_MS;
108
+ this._memoryLimit = config?.memoryLimit ?? DEFAULT_MEMORY_LIMIT_MB;
109
+ this._maxOutputBytes = config?.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;
110
+ const ivm = getIvm();
111
+ if (!ivm) {
112
+ throw new Error('SandboxEngine requires the "isolated-vm" package. ' +
113
+ 'Install it with: npm install isolated-vm');
114
+ }
115
+ this._isolate = new ivm.Isolate({ memoryLimit: this._memoryLimit });
116
+ }
117
+ /**
118
+ * Execute a JavaScript function string against the provided data.
119
+ *
120
+ * The function is compiled and run in a sealed V8 isolate with:
121
+ * - No `process`, `require`, `fs`, or network access
122
+ * - Strict timeout enforcement (async, non-blocking)
123
+ * - Memory limit enforcement
124
+ * - Automatic C++ pointer cleanup (ExternalCopy, Script, Context)
125
+ *
126
+ * @param code - A JavaScript function expression as a string.
127
+ * Must be an arrow function or function expression.
128
+ * Example: `(data) => data.filter(d => d.value > 10)`
129
+ *
130
+ * @param data - The data to pass into the function.
131
+ * Deeply copied into the isolate (no references leak).
132
+ *
133
+ * @returns A `SandboxResult` with the computed value or an error.
134
+ */
135
+ async execute(code, data) {
136
+ if (this._disposed) {
137
+ return { ok: false, error: 'SandboxEngine has been disposed.', code: 'UNAVAILABLE' };
138
+ }
139
+ // ── Step 1: Fail-fast guard ─────────────────────
140
+ const guard = validateSandboxCode(code);
141
+ if (!guard.ok) {
142
+ return { ok: false, error: guard.violation, code: 'INVALID_CODE' };
143
+ }
144
+ // ── Step 2: Ensure isolate is alive ─────────────
145
+ this._ensureIsolate();
146
+ const ivm = getIvm();
147
+ const isolate = this._isolate;
148
+ // ── Step 3: Execute in sealed context ───────────
149
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
150
+ let inputCopy; // ivm.ExternalCopy
151
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
152
+ let context; // ivm.Context
153
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
154
+ let script; // ivm.Script
155
+ const startMs = performance.now();
156
+ try {
157
+ // Create pristine context (NO globals injected — this IS the security)
158
+ context = await isolate.createContext();
159
+ // Deep-copy data into isolated heap (no references!)
160
+ inputCopy = new ivm.ExternalCopy(data);
161
+ await context.global.set('__input__', inputCopy.copyInto());
162
+ // Compile with wrapper: call the function and serialize result
163
+ const wrappedCode = `const __fn__ = ${code};\nJSON.stringify(__fn__(__input__));`;
164
+ script = await isolate.compileScript(wrappedCode);
165
+ // ASYNC execution — never blocks the Node.js event loop
166
+ const rawResult = await script.run(context, { timeout: this._timeout });
167
+ const executionMs = performance.now() - startMs;
168
+ // ── Step 4: Output size guard ───────────────
169
+ if (typeof rawResult === 'string' && rawResult.length > this._maxOutputBytes) {
170
+ return {
171
+ ok: false,
172
+ error: `Output size (${rawResult.length} bytes) exceeds limit (${this._maxOutputBytes} bytes). ` +
173
+ 'Use more selective filters to reduce the result set.',
174
+ code: 'OUTPUT_TOO_LARGE',
175
+ };
176
+ }
177
+ // ── Step 5: Parse result ────────────────────
178
+ const parsed = typeof rawResult === 'string' ? JSON.parse(rawResult) : rawResult;
179
+ return { ok: true, value: parsed, executionMs };
180
+ }
181
+ catch (err) {
182
+ const executionMs = performance.now() - startMs;
183
+ return this._classifyError(err, executionMs);
184
+ }
185
+ finally {
186
+ // ── MANDATORY C++ POINTER RELEASE ────────────
187
+ // Order matters: release inner resources first
188
+ try {
189
+ inputCopy?.release();
190
+ }
191
+ catch { /* already released or isolate dead */ }
192
+ try {
193
+ script?.release();
194
+ }
195
+ catch { /* already released or isolate dead */ }
196
+ try {
197
+ context?.release();
198
+ }
199
+ catch { /* already released or isolate dead */ }
200
+ }
201
+ }
202
+ /**
203
+ * Release all resources held by this engine.
204
+ *
205
+ * After calling `dispose()`, any subsequent `execute()` calls
206
+ * will return `{ ok: false, code: 'UNAVAILABLE' }`.
207
+ */
208
+ dispose() {
209
+ if (this._disposed)
210
+ return;
211
+ this._disposed = true;
212
+ try {
213
+ this._isolate?.dispose();
214
+ }
215
+ catch {
216
+ // Isolate may already be dead (OOM)
217
+ }
218
+ }
219
+ /**
220
+ * Check if the engine has been disposed.
221
+ */
222
+ get isDisposed() {
223
+ return this._disposed;
224
+ }
225
+ // ── Private ──────────────────────────────────────────
226
+ /**
227
+ * Ensure the isolate is alive. If it died (OOM), create a new one.
228
+ * @internal
229
+ */
230
+ _ensureIsolate() {
231
+ const ivm = getIvm();
232
+ // Check if isolate is still usable
233
+ try {
234
+ if (this._isolate?.isDisposed) {
235
+ this._isolate = new ivm.Isolate({ memoryLimit: this._memoryLimit });
236
+ }
237
+ }
238
+ catch {
239
+ // isDisposed threw → isolate is dead, recreate
240
+ this._isolate = new ivm.Isolate({ memoryLimit: this._memoryLimit });
241
+ }
242
+ }
243
+ /**
244
+ * Classify an error from V8 execution into a typed SandboxResult.
245
+ * @internal
246
+ */
247
+ _classifyError(err, executionMs) {
248
+ const message = err instanceof Error ? err.message : String(err);
249
+ // Timeout: isolated-vm throws a specific error
250
+ if (message.includes('Script execution timed out')) {
251
+ return {
252
+ ok: false,
253
+ error: `Script execution timed out (${this._timeout}ms). ` +
254
+ 'Simplify the computation or increase the timeout limit.',
255
+ code: 'TIMEOUT',
256
+ };
257
+ }
258
+ // Memory: V8 kills the isolate
259
+ if (message.includes('Isolate was disposed') ||
260
+ message.includes('out of memory') ||
261
+ message.includes('allocation failed')) {
262
+ // Mark isolate for recreation on next call
263
+ try {
264
+ this._isolate?.dispose();
265
+ }
266
+ catch { /* ignore */ }
267
+ return {
268
+ ok: false,
269
+ error: `Isolate ran out of memory (${this._memoryLimit}MB limit). ` +
270
+ 'Reduce the data size or simplify the computation.',
271
+ code: 'MEMORY',
272
+ };
273
+ }
274
+ // Syntax: V8 compilation error
275
+ if (message.includes('SyntaxError')) {
276
+ return {
277
+ ok: false,
278
+ error: `JavaScript syntax error: ${message}`,
279
+ code: 'SYNTAX',
280
+ };
281
+ }
282
+ // Runtime: any other V8 error (ReferenceError, TypeError, etc.)
283
+ return {
284
+ ok: false,
285
+ error: `Runtime error: ${message}`,
286
+ code: 'RUNTIME',
287
+ };
288
+ }
289
+ }
290
+ //# sourceMappingURL=SandboxEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SandboxEngine.js","sourceRoot":"","sources":["../../src/sandbox/SandboxEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * SandboxGuard — Fail-Fast Syntax Checker for LLM-Provided Code
3
+ *
4
+ * Provides quick feedback BEFORE sending code to the isolated-vm engine.
5
+ * This is NOT a security boundary — security comes from the empty V8
6
+ * Context (no `process`, `require`, `fs`, or `globalThis` injected).
7
+ *
8
+ * Purpose:
9
+ * - Validate that the code is syntactically valid JavaScript
10
+ * - Check that it looks like a function expression / arrow function
11
+ * - Provide fast, descriptive error messages to the LLM
12
+ *
13
+ * Properties:
14
+ * - Zero runtime dependencies (pure string analysis)
15
+ * - Fail-fast: rejects obviously broken code before V8 boot
16
+ * - NOT a security gate (LLMs can obfuscate; the Isolate is the real wall)
17
+ *
18
+ * @module
19
+ * @internal
20
+ */
21
+ export interface GuardResult {
22
+ /** Whether the code passed the fail-fast check */
23
+ readonly ok: boolean;
24
+ /** Human-readable reason for rejection (present when `ok` is false) */
25
+ readonly violation?: string;
26
+ }
27
+ /**
28
+ * Validate LLM-provided code before sending it to the sandbox.
29
+ *
30
+ * Performs two checks:
31
+ * 1. **Shape check**: The code must look like a function expression
32
+ * 2. **Suspicious pattern check**: Fail-fast for obviously unsandboxable patterns
33
+ *
34
+ * @param code - The JavaScript code string from the LLM
35
+ * @returns A `GuardResult` indicating whether the code passed
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const result = validateSandboxCode('(data) => data.filter(d => d.x > 5)');
40
+ * // { ok: true }
41
+ *
42
+ * const bad = validateSandboxCode('require("fs").readFileSync("/etc/passwd")');
43
+ * // { ok: false, violation: 'Code must be a function expression...' }
44
+ * ```
45
+ */
46
+ export declare function validateSandboxCode(code: string): GuardResult;
47
+ //# sourceMappingURL=SandboxGuard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SandboxGuard.d.ts","sourceRoot":"","sources":["../../src/sandbox/SandboxGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,MAAM,WAAW,WAAW;IACxB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,uEAAuE;IACvE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC/B;AA+BD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CA8B7D"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * SandboxGuard — Fail-Fast Syntax Checker for LLM-Provided Code
3
+ *
4
+ * Provides quick feedback BEFORE sending code to the isolated-vm engine.
5
+ * This is NOT a security boundary — security comes from the empty V8
6
+ * Context (no `process`, `require`, `fs`, or `globalThis` injected).
7
+ *
8
+ * Purpose:
9
+ * - Validate that the code is syntactically valid JavaScript
10
+ * - Check that it looks like a function expression / arrow function
11
+ * - Provide fast, descriptive error messages to the LLM
12
+ *
13
+ * Properties:
14
+ * - Zero runtime dependencies (pure string analysis)
15
+ * - Fail-fast: rejects obviously broken code before V8 boot
16
+ * - NOT a security gate (LLMs can obfuscate; the Isolate is the real wall)
17
+ *
18
+ * @module
19
+ * @internal
20
+ */
21
+ // ── Constants ────────────────────────────────────────────
22
+ /**
23
+ * Patterns that indicate the code is NOT a pure function.
24
+ * These are fail-fast hints, not security barriers.
25
+ * The V8 Isolate with an empty Context is the real security wall.
26
+ */
27
+ const SUSPICIOUS_PATTERNS = [
28
+ { pattern: /\bimport\s*\(/, reason: 'Dynamic import() is not available in the sandbox.' },
29
+ { pattern: /\bimport\s+/, reason: 'ES module imports are not available in the sandbox.' },
30
+ { pattern: /\brequire\s*\(/, reason: 'require() is not available in the sandbox.' },
31
+ ];
32
+ /**
33
+ * The code must start with one of these patterns to be recognized
34
+ * as a function expression or arrow function.
35
+ */
36
+ const FUNCTION_PATTERNS = [
37
+ /^\s*\(.*\)\s*=>/s, // (x) => ...
38
+ /^\s*[a-zA-Z_$]\w*\s*=>/, // x => ...
39
+ /^\s*function\s*\(/, // function(x) { ... }
40
+ /^\s*function\s+\w+\s*\(/, // function name(x) { ... }
41
+ /^\s*async\s+\(.*\)\s*=>/s, // async (x) => ...
42
+ /^\s*async\s+function\s*\(/, // async function(x) { ... }
43
+ /^\s*async\s+[a-zA-Z_$]\w*\s*=>/, // async x => ...
44
+ ];
45
+ // ── Guard Implementation ─────────────────────────────────
46
+ /**
47
+ * Validate LLM-provided code before sending it to the sandbox.
48
+ *
49
+ * Performs two checks:
50
+ * 1. **Shape check**: The code must look like a function expression
51
+ * 2. **Suspicious pattern check**: Fail-fast for obviously unsandboxable patterns
52
+ *
53
+ * @param code - The JavaScript code string from the LLM
54
+ * @returns A `GuardResult` indicating whether the code passed
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * const result = validateSandboxCode('(data) => data.filter(d => d.x > 5)');
59
+ * // { ok: true }
60
+ *
61
+ * const bad = validateSandboxCode('require("fs").readFileSync("/etc/passwd")');
62
+ * // { ok: false, violation: 'Code must be a function expression...' }
63
+ * ```
64
+ */
65
+ export function validateSandboxCode(code) {
66
+ if (!code || typeof code !== 'string') {
67
+ return { ok: false, violation: 'Code must be a non-empty string.' };
68
+ }
69
+ const trimmed = code.trim();
70
+ if (trimmed.length === 0) {
71
+ return { ok: false, violation: 'Code must be a non-empty string.' };
72
+ }
73
+ // Shape check: must look like a function
74
+ const looksLikeFunction = FUNCTION_PATTERNS.some(p => p.test(trimmed));
75
+ if (!looksLikeFunction) {
76
+ return {
77
+ ok: false,
78
+ violation: 'Code must be a function expression or arrow function. ' +
79
+ 'Example: (data) => data.filter(d => d.value > 10)',
80
+ };
81
+ }
82
+ // Suspicious pattern check (fail-fast hints, not security)
83
+ for (const { pattern, reason } of SUSPICIOUS_PATTERNS) {
84
+ if (pattern.test(trimmed)) {
85
+ return { ok: false, violation: reason };
86
+ }
87
+ }
88
+ return { ok: true };
89
+ }
90
+ //# sourceMappingURL=SandboxGuard.js.map