@nekzus/liop 2.0.0-alpha.28 → 2.0.0-alpha.29

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/README.md CHANGED
@@ -111,6 +111,8 @@ To integrate LIOP into Claude Desktop, update your `claude_desktop_config.json`
111
111
  "env": {
112
112
  "LIOP_NEXUS_URL": "http://your-nexus-host:3000",
113
113
  "LIOP_LOG_LEVEL": "info",
114
+ "LIOP_TOKEN_BANK": "your-secure-bank-token",
115
+ "LIOP_TOKEN_VAULT": "your-secure-vault-token",
114
116
  "NODE_OPTIONS": "--use-system-ca"
115
117
  }
116
118
  }
@@ -220,27 +222,29 @@ new LiopServer(
220
222
  capabilities?: Record<string, unknown>;
221
223
  workerPool?: {
222
224
  enabled?: boolean; // Enable OS-thread sandboxing (default: true)
225
+ minThreads?: number; // Min worker threads (default: CPU count based)
223
226
  maxThreads?: number; // Max worker threads (default: CPU count)
227
+ idleTimeout?: number; // Idle timeout in milliseconds for workers
224
228
  maxHeapMb?: number; // V8 heap limit per worker (default: 64, env: LIOP_WORKER_MAX_HEAP_MB)
225
229
  };
226
230
  security?: {
227
231
  piiPatterns?: PiiRule[]; // Regex/validator rules for PII detection
228
232
  forbiddenKeys?: string[]; // Keys stripped from outgoing responses
233
+ sensitiveKeys?: string[]; // Keys that trigger sensitive query budget
229
234
  enableNerScanning?: boolean; // NLP entity detection via compromise (default: false)
230
- rateLimit?: { // Sliding window rate limiter per tool
231
- maxPerWindow?: number; // Max calls per window (default: 15)
232
- windowMs?: number; // Window duration in ms (default: 60000)
233
- };
234
- globalRateLimit?: { // Cross-tool aggregate rate limiter
235
- maxPerWindow?: number; // Max total calls per window (default: 40)
235
+ rateLimit?: { // Sliding window rate limiter configuration
236
+ maxPerWindow?: number; // Max calls per window per tool (default: 15)
237
+ globalMaxPerWindow?: number; // Max total calls across all tools (default: 40)
236
238
  windowMs?: number; // Window duration in ms (default: 60000)
237
239
  };
238
240
  };
239
241
  taxonomy?: { // Data domain classification
240
242
  domain?: string; // e.g., "finance", "healthcare"
241
- clearanceTier?: string; // e.g., "tier-0", "tier-1"
243
+ clearanceTier?: number; // e.g., 3, 5 (strictly numeric)
242
244
  executionTypes?: string[]; // e.g., ["aggregation", "analytics"]
243
245
  };
246
+ auth?: LiopAuthConfig; // OAuth 2.1 Hybrid authentication config
247
+ tokenSlug?: string; // Deterministic token resolution slug (e.g., "BANK", "VAULT")
244
248
  }
245
249
  )
246
250
  ```
@@ -359,6 +363,29 @@ const server = new LiopServer(info, {
359
363
 
360
364
  To avoid false positive triggers caused by HMAC-SHA256 ZK-Receipt signatures or transport wrapper frames (such as `{ content: [{ type: "text", text: "..." }] }`), the PII Shield and Aggregation-First engines scan only the unwrapped business data (via `unwrapForAggregationPolicyScan`). Cryptographic seals and protocol routing structures are isolated and excluded from compliance scans.
361
365
 
366
+ ### 📊 3-Tier Query Budget (NIST SP 800-226)
367
+
368
+ To prevent advanced statistical differentiation or database reconstruction attacks, the SDK implements a tiered, session-based budget engine:
369
+
370
+ - **Forbidden Tier** (Limit: `3` queries/session): Applied to highly restricted variables like user IDs, passwords, emails, SSNs (configured via `forbiddenKeys`).
371
+ - **Sensitive Tier** (Limit: `8` queries/session): Applied to moderately sensitive variables like account types, medical diagnoses, blood types, financial tickers (configured via `sensitiveKeys`).
372
+ - **Public Tier** (Limit: `25` queries/session): Default budget for non-sensitive public metadata.
373
+
374
+ If an injected payload queries a field beyond its budget limit, the preflight static analysis immediately blocks execution.
375
+
376
+ ### 🛡️ K-Anonymity on Small Datasets
377
+
378
+ When operating on high-privacy datasets, if the source records count is **less than 10**, the SDK forces a strict K-Anonymity restriction:
379
+ - Rejects any output that contains nested objects or arrays.
380
+ - Restricts the returned structure to a maximum of **3 scalar keys** (e.g., simple aggregate counts or statistics).
381
+ - Prevents structural data leakage in low-entropy datasets.
382
+
383
+ ### ❄️ Sandbox Poisoned Globals & Date Workaround
384
+
385
+ For maximum host security, the WASI sandbox enforces a poisoned environment that strips dangerous globals and prevents timing side-channels:
386
+ - **Poisoned/Disabled**: `Date` (Date.now, parse, etc. throw an exception to prevent timing analysis), `eval`, `Function`, `setTimeout`, `setInterval`, `Buffer`, `ArrayBuffer`, and all `TypedArrays`.
387
+ - **Date Workaround**: To perform date checks, use lexicographical string comparison on ISO 8601 strings (e.g., `record.date >= "2026-01-01"`).
388
+
362
389
  ---
363
390
 
364
391
  ## Logic-Injection-on-Origin Flow
@@ -0,0 +1,31 @@
1
+ import j from'crypto';import*as i from'fs/promises';import*as S from'os';import*as u from'path';import E from'vm';import {WASI}from'wasi';var l=class extends Error{constructor(r){super(`AST Sec-Policy Violation: ${r}`),this.name="GuardianError";}},w={analyze(c){let r=WebAssembly.Module.imports(c),o=0,d=new Set(["fd_write","fd_read","fd_close","fd_seek","environ_get","environ_sizes_get","args_get","args_sizes_get","clock_time_get","random_get","proc_exit","fd_prestat_get","fd_prestat_dir_name","fd_fdstat_get"]);for(let n of r){if(n.module==="wasi_snapshot_preview1"){if(!d.has(n.name))throw new l(`Banned WASI Import Detected: ${n.module}/${n.name}`)}else throw new l(`Banned Host Import Module Detected: ${n.module}`);if(o++,o>128)throw new l("Import limit exceeded. Possible resource exhaustion attack.")}}};var x=process.emit;process.emit=(c,r,...o)=>c==="warning"&&typeof r=="object"&&r.name==="ExperimentalWarning"&&String(r.message).includes("WASI")||String(r.message).includes("importing WASI")?false:x.call(process,c,r,...o);function R(){let r=process.platform==="win32"?["APPDATA","HOMEDRIVE","HOMEPATH","LOCALAPPDATA","PATH","PROCESSOR_ARCHITECTURE","SYSTEMDRIVE","SYSTEMROOT","TEMP","USERNAME","USERPROFILE","PROGRAMFILES"]:["HOME","LOGNAME","PATH","SHELL","TERM","USER"],o={NODE_ENV:"production",LIOP_NODE:"true"};for(let d of r){let n=process.env[d];n!==void 0&&!n.startsWith("()")&&(o[d]=n);}return o}var h=class{wasi;sandboxId;workingDir;config;stdoutHandle=null;stderrHandle=null;constructor(r={}){this.sandboxId=j.randomUUID(),this.workingDir=u.join(S.tmpdir(),"liop-mesh","sandboxes",this.sandboxId),this.config=r;}async init(){try{await i.mkdir(this.workingDir,{recursive:!0}),this.stdoutHandle=await i.open(u.join(this.workingDir,"stdout.log"),"w+"),this.stderrHandle=await i.open(u.join(this.workingDir,"stderr.log"),"w+"),this.wasi=new WASI({version:"preview1",args:["liop_runtime"],env:this.config.allowEnv?{...R(),RUNTIME_ID:this.sandboxId}:{NODE_ENV:"production",LIOP_NODE:"true",RUNTIME_ID:this.sandboxId},preopens:{"/sandbox":this.workingDir,...this.config.allowedDirectories},stdout:this.stdoutHandle.fd,stderr:this.stderrHandle.fd});}catch(r){throw new Error(`Sandbox Initialization Failed: ${r instanceof Error?r.message:"FS Error"}`)}}async execute(r,o=[],d={}){let n=performance.now();if(r instanceof Buffer)try{let e=await WebAssembly.compile(new Uint8Array(r));w.analyze(e);let y=await WebAssembly.instantiate(e,this.wasi.getImportObject());this.wasi.start(y);let f=u.join(this.workingDir,"stdout.log"),p=u.join(this.workingDir,"stderr.log"),s=await i.readFile(f,"utf-8"),m=await i.readFile(p,"utf-8"),t=performance.now()-n;return {output:s||(m?`Error: ${m}`:"WASM_EXECUTION_SUCCESS"),fuelConsumed:Math.floor(t*1e3)}}catch(e){throw new Error(`WASM Runtime Error: ${e instanceof Error?e.message:String(e)}`)}else {let e=Object.create(null),y={records:o,...d};e.require=void 0,e.process=void 0,e.global=void 0,e.globalThis=void 0,e.Buffer=void 0,e.setTimeout=void 0,e.setInterval=void 0,e.setImmediate=void 0,e.queueMicrotask=void 0,e.eval=void 0,e.Function=void 0,e.SharedArrayBuffer=void 0,e.Date=void 0,e.ArrayBuffer=void 0,e.Uint8Array=void 0,e.Int8Array=void 0,e.Uint16Array=void 0,e.Int16Array=void 0,e.Uint32Array=void 0,e.Int32Array=void 0,e.Float32Array=void 0,e.Float64Array=void 0,e.BigInt64Array=void 0,e.BigUint64Array=void 0,e.DataView=void 0;let f=t=>{if(!t||typeof t!="object")return t;if(Array.isArray(t))return t.map(f);let a=Object.create(null);for(let[g,O]of Object.entries(t))a[g]=f(O);return a};e.records=f(JSON.parse(JSON.stringify(o))),e.env=f(JSON.parse(JSON.stringify(y)));for(let[t,a]of Object.entries(d))e[t]=f(JSON.parse(JSON.stringify(a)));let p=t=>{if(t&&typeof t=="object"&&!Object.isFrozen(t)){Object.freeze(t);for(let a of Object.keys(t))p(t[a]);}return t};p(e.records),p(e.env);for(let t of Object.keys(e))Object.defineProperty(e,t,{writable:false,configurable:false});let s=String(r);(/^\s*return\s/m.test(s)||!s.includes("function liop_main"))&&(s.includes("function liop_main")||(s=`function liop_main(env) {
2
+ ${s}
3
+ }`));let m=`
4
+ (function() {
5
+ "use strict";
6
+ try {
7
+ // Pre-execution prototype freezing (PCI-DSS Compliance)
8
+ Object.freeze(Object.prototype);
9
+ Object.freeze(Array.prototype);
10
+ Object.freeze(String.prototype);
11
+ Object.freeze(Number.prototype);
12
+ Object.freeze(Boolean.prototype);
13
+ Object.freeze(RegExp.prototype);
14
+ Object.freeze(Map.prototype);
15
+ Object.freeze(Set.prototype);
16
+ Object.freeze(Promise.prototype);
17
+ Object.freeze(Error.prototype);
18
+ Object.freeze(Object.getPrototypeOf(function(){}));
19
+
20
+ ${s}
21
+ if (typeof liop_main === 'function') {
22
+ return liop_main(env);
23
+ }
24
+ return "ERR_NO_ENTRY_POINT";
25
+ } catch(e) {
26
+ return "LogicError: " + e.message;
27
+ }
28
+ })();
29
+ `;try{let t=new E.Script(m,{filename:`liop-sandbox-${this.sandboxId.slice(0,8)}.js`});!process.env.VITEST&&typeof Object.prototype=="object"&&!Object.isFrozen(Object.prototype)&&(Object.freeze(Object.prototype),Object.freeze(Array.prototype),Object.freeze(String.prototype),Object.freeze(Number.prototype),Object.freeze(Boolean.prototype),Object.freeze(RegExp.prototype),Object.freeze(Map.prototype),Object.freeze(Set.prototype),Object.freeze(Promise.prototype),Object.freeze(Error.prototype));let a=E.createContext(e,{name:"LIOP Isolate",origin:"liop://sandbox",microtaskMode:"afterEvaluate"}),g=t.runInContext(a,{timeout:5e3,breakOnSigint:!0,displayErrors:!0}),O=performance.now()-n,A=Math.floor(O*1500+100),b=Math.ceil(A/100)*100;if(b>1e6)throw new Error("LIOP_RESOURCE_EXHAUSTED: Execution fuel limit exceeded.");return {output:g,fuelConsumed:b}}catch(t){throw new Error(`V8 Isolate Fault: ${t instanceof Error?t.message:"Execution Timeout"}`)}}}async teardown(){try{this.stdoutHandle&&await this.stdoutHandle.close(),this.stderrHandle&&await this.stderrHandle.close(),await i.rm(this.workingDir,{recursive:!0,force:!0});}catch{}}};
30
+ export{w as a,R as b,h as c};//# sourceMappingURL=chunk-RYYRR4N5.js.map
31
+ //# sourceMappingURL=chunk-RYYRR4N5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sandbox/guardian.ts","../src/sandbox/wasi.ts"],"names":["GuardianError","message","ASTGuardian","module","imports","_importCount","ALLOWED_WASI_FUNCTIONS","imp","originalEmit","name","data","args","getDefaultEnvironment","safeKeys","env","key","val","WasiSandbox","config","crypto","WASI","error","compiledLogic","records","inputs","startTime","instance","stdoutPath","stderrPath","stdout","stderr","duration","sandboxEnv","toNullPrototype","obj","clone","value","deepFreeze","processedLogic","scriptCode","script","vm","context","output","rawFuel","fuelUsed"],"mappings":"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","file":"chunk-RYYRR4N5.js","sourcesContent":["export class GuardianError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(`AST Sec-Policy Violation: ${message}`);\n\t\tthis.name = \"GuardianError\";\n\t}\n}\n\n/**\n * The Guardian-TS Module\n * Scans the Abstract Syntax Tree (AST) imports of incoming WASM\n * before it reaches the V8 Wasmtime engine to prevent sandbox-escape\n * zero-days, resource exhaustion bombs, and evasive execution.\n */\nexport const ASTGuardian = {\n\t/**\n\t * Analyzes the WebAssembly Module interface proactively.\n\t *\n\t * @param module - The compiled WebAssembly.Module to inspect\n\t * @throws {GuardianError} If illegal imports or capabilities are detected\n\t */\n\tanalyze(module: WebAssembly.Module): void {\n\t\tconst imports = WebAssembly.Module.imports(module);\n\t\tlet _importCount = 0;\n\n\t\tconst ALLOWED_WASI_FUNCTIONS = new Set([\n\t\t\t\"fd_write\",\n\t\t\t\"fd_read\",\n\t\t\t\"fd_close\",\n\t\t\t\"fd_seek\",\n\t\t\t\"environ_get\",\n\t\t\t\"environ_sizes_get\",\n\t\t\t\"args_get\",\n\t\t\t\"args_sizes_get\",\n\t\t\t\"clock_time_get\",\n\t\t\t\"random_get\",\n\t\t\t\"proc_exit\",\n\t\t\t\"fd_prestat_get\",\n\t\t\t\"fd_prestat_dir_name\",\n\t\t\t\"fd_fdstat_get\",\n\t\t]);\n\n\t\tfor (const imp of imports) {\n\t\t\t// Strict Sandbox Validation: Only allow WASI preview 1 specific whitelisted functions.\n\t\t\tif (imp.module === \"wasi_snapshot_preview1\") {\n\t\t\t\tif (!ALLOWED_WASI_FUNCTIONS.has(imp.name)) {\n\t\t\t\t\tthrow new GuardianError(\n\t\t\t\t\t\t`Banned WASI Import Detected: ${imp.module}/${imp.name}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new GuardianError(\n\t\t\t\t\t`Banned Host Import Module Detected: ${imp.module}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\t_importCount++;\n\n\t\t\tif (_importCount > 128) {\n\t\t\t\tthrow new GuardianError(\n\t\t\t\t\t\"Import limit exceeded. Possible resource exhaustion attack.\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// In Node.js / V8, the maximum module size and function limits\n\t\t// are natively enforced by the engine during compilation.\n\t\t// A successfully compiled WebAssembly.Module already passed structural checks.\n\t},\n};\n","import crypto from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport vm from \"node:vm\";\nimport { WASI } from \"node:wasi\";\nimport { ASTGuardian } from \"./guardian.js\";\n\n// Silence Node.js ExperimentalWarning for WASI (Industrial console parity)\nconst originalEmit = process.emit;\n// @ts-expect-error\nprocess.emit = (name, data, ...args) => {\n\tif (\n\t\t(name === \"warning\" &&\n\t\t\ttypeof data === \"object\" &&\n\t\t\t(data as Record<string, unknown>).name === \"ExperimentalWarning\" &&\n\t\t\tString((data as Record<string, unknown>).message).includes(\"WASI\")) ||\n\t\tString((data as Record<string, unknown>).message).includes(\"importing WASI\")\n\t) {\n\t\treturn false;\n\t}\n\treturn originalEmit.call(process, name, data, ...args);\n};\n\n/**\n * Returns a filtered environment object containing only safe system variables,\n * preventing exposure of sensitive credentials and shell function injection.\n */\nexport function getDefaultEnvironment(): Record<string, string> {\n\tconst isWindows = process.platform === \"win32\";\n\tconst safeKeys = isWindows\n\t\t? [\n\t\t\t\t\"APPDATA\",\n\t\t\t\t\"HOMEDRIVE\",\n\t\t\t\t\"HOMEPATH\",\n\t\t\t\t\"LOCALAPPDATA\",\n\t\t\t\t\"PATH\",\n\t\t\t\t\"PROCESSOR_ARCHITECTURE\",\n\t\t\t\t\"SYSTEMDRIVE\",\n\t\t\t\t\"SYSTEMROOT\",\n\t\t\t\t\"TEMP\",\n\t\t\t\t\"USERNAME\",\n\t\t\t\t\"USERPROFILE\",\n\t\t\t\t\"PROGRAMFILES\",\n\t\t\t]\n\t\t: [\"HOME\", \"LOGNAME\", \"PATH\", \"SHELL\", \"TERM\", \"USER\"];\n\n\tconst env: Record<string, string> = {\n\t\tNODE_ENV: \"production\",\n\t\tLIOP_NODE: \"true\",\n\t};\n\n\tfor (const key of safeKeys) {\n\t\tconst val = process.env[key];\n\t\tif (val !== undefined && !val.startsWith(\"()\")) {\n\t\t\tenv[key] = val;\n\t\t}\n\t}\n\n\treturn env;\n}\n\nexport interface SandboxConfig {\n\tallowEnv?: boolean;\n\tallowedDirectories?: Record<string, string>; // guestPath -> hostPath\n\tmemoryLimitMb?: number;\n}\n\n/**\n * LIOP WasiSandbox (Industrial Grade)\n *\n * Provides a production-grade isolated environment for executing untrusted logic.\n * Primarily uses WebAssembly (WASI) for byte-code isolation, with a hardened\n * V8 Isolate fallback for dynamic JS-to-WASM logic injection.\n */\nexport class WasiSandbox {\n\tprivate wasi!: WASI;\n\tprivate sandboxId: string;\n\tprivate workingDir: string;\n\tprivate config: SandboxConfig;\n\tprivate stdoutHandle: fs.FileHandle | null = null;\n\tprivate stderrHandle: fs.FileHandle | null = null;\n\n\tconstructor(config: SandboxConfig = {}) {\n\t\tthis.sandboxId = crypto.randomUUID();\n\t\t// Use a dedicated LIOP directory in the OS temp folder\n\t\tthis.workingDir = path.join(\n\t\t\tos.tmpdir(),\n\t\t\t\"liop-mesh\",\n\t\t\t\"sandboxes\",\n\t\t\tthis.sandboxId,\n\t\t);\n\t\tthis.config = config;\n\t}\n\n\t/**\n\t * Initializes the physical sandbox environment with strict directory lockdown.\n\t */\n\tpublic async init(): Promise<void> {\n\t\ttry {\n\t\t\tawait fs.mkdir(this.workingDir, { recursive: true });\n\n\t\t\t// Initialize WASI with explicit limits\n\t\t\tthis.stdoutHandle = await fs.open(\n\t\t\t\tpath.join(this.workingDir, \"stdout.log\"),\n\t\t\t\t\"w+\",\n\t\t\t);\n\t\t\tthis.stderrHandle = await fs.open(\n\t\t\t\tpath.join(this.workingDir, \"stderr.log\"),\n\t\t\t\t\"w+\",\n\t\t\t);\n\n\t\t\tthis.wasi = new WASI({\n\t\t\t\tversion: \"preview1\",\n\t\t\t\targs: [\"liop_runtime\"],\n\t\t\t\tenv: this.config.allowEnv\n\t\t\t\t\t? { ...getDefaultEnvironment(), RUNTIME_ID: this.sandboxId }\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tNODE_ENV: \"production\",\n\t\t\t\t\t\t\tLIOP_NODE: \"true\",\n\t\t\t\t\t\t\tRUNTIME_ID: this.sandboxId,\n\t\t\t\t\t\t},\n\t\t\t\tpreopens: {\n\t\t\t\t\t\"/sandbox\": this.workingDir,\n\t\t\t\t\t...this.config.allowedDirectories,\n\t\t\t\t},\n\t\t\t\tstdout: this.stdoutHandle.fd,\n\t\t\t\tstderr: this.stderrHandle.fd,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Sandbox Initialization Failed: ${error instanceof Error ? error.message : \"FS Error\"}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Executes logic (WASM or JS-Wrapped) with hard resource limits.\n\t */\n\tpublic async execute(\n\t\tcompiledLogic: Buffer | string,\n\t\trecords: Record<string, unknown>[] = [],\n\t\tinputs: Record<string, unknown> = {},\n\t): Promise<{ output: unknown; fuelConsumed: number }> {\n\t\tconst startTime = performance.now();\n\n\t\tif (compiledLogic instanceof Buffer) {\n\t\t\t// Path A: Native WebAssembly Isolation\n\t\t\ttry {\n\t\t\t\tconst module = await WebAssembly.compile(new Uint8Array(compiledLogic));\n\n\t\t\t\t// Tier-0 Guardian: Static analysis to prevent sandbox escapes\n\t\t\t\tASTGuardian.analyze(module);\n\n\t\t\t\tconst instance = await WebAssembly.instantiate(\n\t\t\t\t\tmodule,\n\t\t\t\t\tthis.wasi.getImportObject() as WebAssembly.Imports,\n\t\t\t\t);\n\n\t\t\t\t// Standard entry point\n\t\t\t\tthis.wasi.start(instance);\n\n\t\t\t\t// Capture output from the sandbox\n\t\t\t\tconst stdoutPath = path.join(this.workingDir, \"stdout.log\");\n\t\t\t\tconst stderrPath = path.join(this.workingDir, \"stderr.log\");\n\t\t\t\tconst stdout = await fs.readFile(stdoutPath, \"utf-8\");\n\t\t\t\tconst stderr = await fs.readFile(stderrPath, \"utf-8\");\n\n\t\t\t\tconst duration = performance.now() - startTime;\n\t\t\t\treturn {\n\t\t\t\t\toutput:\n\t\t\t\t\t\tstdout || (stderr ? `Error: ${stderr}` : \"WASM_EXECUTION_SUCCESS\"),\n\t\t\t\t\tfuelConsumed: Math.floor(duration * 1000),\n\t\t\t\t};\n\t\t\t} catch (error: unknown) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`WASM Runtime Error: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\t// Path B: Hardened V8 Isolate Fallback\n\t\t\t// Uses node:vm with zero-prototype objects to prevent prototype pollution escapes.\n\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: Required for Sandbox global poisoning\n\t\t\tconst sandboxEnv: any = Object.create(null); // Isolated global object\n\t\t\tconst env = { records, ...inputs };\n\n\t\t\t// Explicitly poison Node.js escape vectors in the context\n\t\t\tsandboxEnv.require = undefined;\n\t\t\tsandboxEnv.process = undefined;\n\t\t\tsandboxEnv.global = undefined;\n\t\t\tsandboxEnv.globalThis = undefined;\n\t\t\tsandboxEnv.Buffer = undefined;\n\t\t\tsandboxEnv.setTimeout = undefined;\n\t\t\tsandboxEnv.setInterval = undefined;\n\t\t\tsandboxEnv.setImmediate = undefined;\n\t\t\tsandboxEnv.queueMicrotask = undefined;\n\t\t\tsandboxEnv.eval = undefined;\n\t\t\tsandboxEnv.Function = undefined;\n\t\t\tsandboxEnv.SharedArrayBuffer = undefined;\n\t\t\tsandboxEnv.Date = undefined;\n\n\t\t\t// [DoS Defense] Block off-heap memory allocation vectors.\n\t\t\t// Logic-on-Origin operates on JSON data (env.records) — binary buffers\n\t\t\t// serve no legitimate purpose and enable memory exhaustion DoS.\n\t\t\t// (Uint8Array(2GB) bypassed Piscina's maxOldGenerationSizeMb limit)\n\t\t\tsandboxEnv.ArrayBuffer = undefined;\n\t\t\tsandboxEnv.Uint8Array = undefined;\n\t\t\tsandboxEnv.Int8Array = undefined;\n\t\t\tsandboxEnv.Uint16Array = undefined;\n\t\t\tsandboxEnv.Int16Array = undefined;\n\t\t\tsandboxEnv.Uint32Array = undefined;\n\t\t\tsandboxEnv.Int32Array = undefined;\n\t\t\tsandboxEnv.Float32Array = undefined;\n\t\t\tsandboxEnv.Float64Array = undefined;\n\t\t\tsandboxEnv.BigInt64Array = undefined;\n\t\t\tsandboxEnv.BigUint64Array = undefined;\n\t\t\tsandboxEnv.DataView = undefined;\n\n\t\t\t// Recurse and strip prototype chain from host-passed objects to prevent escaping via constructor\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: Required for recursive null prototype mapping\n\t\t\tconst toNullPrototype = (obj: any): any => {\n\t\t\t\tif (!obj || typeof obj !== \"object\") {\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t\tif (Array.isArray(obj)) {\n\t\t\t\t\treturn obj.map(toNullPrototype);\n\t\t\t\t}\n\t\t\t\tconst clone = Object.create(null);\n\t\t\t\tfor (const [key, val] of Object.entries(obj)) {\n\t\t\t\t\tclone[key] = toNullPrototype(val);\n\t\t\t\t}\n\t\t\t\treturn clone;\n\t\t\t};\n\n\t\t\t// Inject strictly monitored globals\n\t\t\tsandboxEnv.records = toNullPrototype(JSON.parse(JSON.stringify(records))); // Deep copy safety + null prototype\n\t\t\tsandboxEnv.env = toNullPrototype(JSON.parse(JSON.stringify(env)));\n\n\t\t\tfor (const [key, value] of Object.entries(inputs)) {\n\t\t\t\tsandboxEnv[key] = toNullPrototype(JSON.parse(JSON.stringify(value)));\n\t\t\t}\n\n\t\t\t// Freeze the sandbox context to prevent mutation (SEC-GAP-1)\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: Required for recursive deep freeze of unknown data\n\t\t\tconst deepFreeze = (obj: any) => {\n\t\t\t\tif (obj && typeof obj === \"object\" && !Object.isFrozen(obj)) {\n\t\t\t\t\tObject.freeze(obj);\n\t\t\t\t\tfor (const key of Object.keys(obj)) {\n\t\t\t\t\t\tdeepFreeze(obj[key]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn obj;\n\t\t\t};\n\n\t\t\tdeepFreeze(sandboxEnv.records);\n\t\t\tdeepFreeze(sandboxEnv.env);\n\n\t\t\t// Prevent property addition/modification on global scope\n\t\t\tfor (const key of Object.keys(sandboxEnv)) {\n\t\t\t\tObject.defineProperty(sandboxEnv, key, {\n\t\t\t\t\twritable: false,\n\t\t\t\t\tconfigurable: false,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// LIOP Execution Wrapper\n\t\t\t// Host-side logic transformation to avoid 'new Function' in sandbox\n\t\t\tlet processedLogic = String(compiledLogic);\n\t\t\tif (\n\t\t\t\t/^\\s*return\\s/m.test(processedLogic) ||\n\t\t\t\t!processedLogic.includes(\"function liop_main\")\n\t\t\t) {\n\t\t\t\tif (!processedLogic.includes(\"function liop_main\")) {\n\t\t\t\t\tprocessedLogic = `function liop_main(env) {\\n${processedLogic}\\n}`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst scriptCode = `\n\t\t\t\t(function() {\n\t\t\t\t\t\"use strict\";\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Pre-execution prototype freezing (PCI-DSS Compliance)\n\t\t\t\t\t\tObject.freeze(Object.prototype);\n\t\t\t\t\t\tObject.freeze(Array.prototype);\n\t\t\t\t\t\tObject.freeze(String.prototype);\n\t\t\t\t\t\tObject.freeze(Number.prototype);\n\t\t\t\t\t\tObject.freeze(Boolean.prototype);\n\t\t\t\t\t\tObject.freeze(RegExp.prototype);\n\t\t\t\t\t\tObject.freeze(Map.prototype);\n\t\t\t\t\t\tObject.freeze(Set.prototype);\n\t\t\t\t\t\tObject.freeze(Promise.prototype);\n\t\t\t\t\t\tObject.freeze(Error.prototype);\n\t\t\t\t\t\tObject.freeze(Object.getPrototypeOf(function(){}));\n\n\t\t\t\t\t\t${processedLogic}\n\t\t\t\t\t\tif (typeof liop_main === 'function') {\n\t\t\t\t\t\t\treturn liop_main(env);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn \"ERR_NO_ENTRY_POINT\";\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\treturn \"LogicError: \" + e.message;\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t`;\n\n\t\t\ttry {\n\t\t\t\tconst script = new vm.Script(scriptCode, {\n\t\t\t\t\tfilename: `liop-sandbox-${this.sandboxId.slice(0, 8)}.js`,\n\t\t\t\t});\n\n\t\t\t\t// Freeze Host prototypes in production (non-test environments) to completely block Prototype Pollution\n\t\t\t\tif (\n\t\t\t\t\t!process.env.VITEST &&\n\t\t\t\t\ttypeof Object.prototype === \"object\" &&\n\t\t\t\t\t!Object.isFrozen(Object.prototype)\n\t\t\t\t) {\n\t\t\t\t\tObject.freeze(Object.prototype);\n\t\t\t\t\tObject.freeze(Array.prototype);\n\t\t\t\t\tObject.freeze(String.prototype);\n\t\t\t\t\tObject.freeze(Number.prototype);\n\t\t\t\t\tObject.freeze(Boolean.prototype);\n\t\t\t\t\tObject.freeze(RegExp.prototype);\n\t\t\t\t\tObject.freeze(Map.prototype);\n\t\t\t\t\tObject.freeze(Set.prototype);\n\t\t\t\t\tObject.freeze(Promise.prototype);\n\t\t\t\t\tObject.freeze(Error.prototype);\n\t\t\t\t}\n\n\t\t\t\t// microtaskMode: Ensures Promises created inside the sandbox are\n\t\t\t\t// resolved within the timeout/breakOnSigint scope (Node.js ≥14.6).\n\t\t\t\t// Without this, async microtasks could escape the 5s CPU limit.\n\t\t\t\tconst context = vm.createContext(sandboxEnv, {\n\t\t\t\t\tname: \"LIOP Isolate\",\n\t\t\t\t\torigin: \"liop://sandbox\",\n\t\t\t\t\tmicrotaskMode: \"afterEvaluate\",\n\t\t\t\t});\n\n\t\t\t\t// Execution with hard CPU and Memory limits (Fuel)\n\t\t\t\tconst output = script.runInContext(context, {\n\t\t\t\t\ttimeout: 5000,\n\t\t\t\t\tbreakOnSigint: true,\n\t\t\t\t\tdisplayErrors: true,\n\t\t\t\t});\n\n\t\t\t\tconst duration = performance.now() - startTime;\n\t\t\t\t// SEC: Normalize fuel to buckets of 100 to prevent timing side-channel inference\n\t\t\t\tconst rawFuel = Math.floor(duration * 1500 + 100);\n\t\t\t\tconst fuelUsed = Math.ceil(rawFuel / 100) * 100;\n\n\t\t\t\tif (fuelUsed > 1000000) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"LIOP_RESOURCE_EXHAUSTED: Execution fuel limit exceeded.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn { output, fuelConsumed: fuelUsed };\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`V8 Isolate Fault: ${error instanceof Error ? error.message : \"Execution Timeout\"}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Physically cleans up the sandbox and releases resources.\n\t */\n\tpublic async teardown(): Promise<void> {\n\t\ttry {\n\t\t\tif (this.stdoutHandle) await this.stdoutHandle.close();\n\t\t\tif (this.stderrHandle) await this.stderrHandle.close();\n\t\t\tawait fs.rm(this.workingDir, { recursive: true, force: true });\n\t\t} catch (_e) {\n\t\t\t// Silent fail on teardown to prevent process crashes\n\t\t}\n\t}\n}\n"]}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export{c as WasiSandbox,b as getDefaultEnvironment}from'./chunk-TZWB3DEB.js';export{b as LiopClient,a as LiopRpcClient}from'./chunk-N6FGTZ6A.js';export{c as PromptSchema,b as ResourceSchema,a as ToolSchema}from'./chunk-TYVG6TXQ.js';export{b as LiopMcpBridge,a as LiopStreamBridge}from'./chunk-W2QGWRTT.js';export{b as LiopHybridGateway,a as buildProtectedResourceMetadata}from'./chunk-YZVCAJJO.js';export{b as AUTH_DEFAULTS,c as JwtValidator,a as LiopRpcServer,j as LiopServer,e as NerScanner,g as PII_PATTERNS,h as PII_PRESETS,i as PiiScanner,d as createOAuthServer,f as sanitizeOutput}from'./chunk-L5A64CNT.js';import'./chunk-2MGFSIXN.js';export{b as HeuristicTokenEstimator,e as LiopOTelBridge,a as RealTokenEstimator,f as TokenTelemetryEngine,d as createSyncTokenEstimator,c as createTokenEstimator}from'./chunk-VGXNGTIC.js';import'./chunk-SW53FNSN.js';import'./chunk-ANFXJGMP.js';import'./chunk-DBXGYHKY.js';export{b as LIOP_SCOPES,a as authorizeRequest}from'./chunk-SB5XJXKV.js';import'./chunk-V5MKJT6S.js';export{a as MeshNode}from'./chunk-DQ6UW6L7.js';import'./chunk-S6RJHZV2.js';import'./chunk-4C666HHU.js';var h=(e=>(e.CapabilityViolation="CapabilityViolation",e.SandboxEscape="SandboxEscape",e.PiiLeak="PiiLeak",e.InvalidIntent="InvalidIntent",e.Throttled="Throttled",e.ZkVerificationFailed="ZkVerificationFailed",e.MeshUnavailable="MeshUnavailable",e.ConnectionFailed="ConnectionFailed",e))(h||{}),n=class extends Error{code;constructor(o,t){super(t),this.name="LiopError",this.code=o;}};var x={claude:{xmlStandard:true,jsonSchemaPreferred:false},openai:{xmlStandard:false,jsonSchemaPreferred:true},gemini:{xmlStandard:false,jsonSchemaPreferred:true}};function W(i){let o=x[i],t=`[LIOP-PROTO-V1: LOGIC-ON-ORIGIN SPECIFICATION]
1
+ export{c as WasiSandbox,b as getDefaultEnvironment}from'./chunk-RYYRR4N5.js';export{b as LiopClient,a as LiopRpcClient}from'./chunk-N6FGTZ6A.js';export{c as PromptSchema,b as ResourceSchema,a as ToolSchema}from'./chunk-TYVG6TXQ.js';export{b as LiopMcpBridge,a as LiopStreamBridge}from'./chunk-W2QGWRTT.js';export{b as LiopHybridGateway,a as buildProtectedResourceMetadata}from'./chunk-YZVCAJJO.js';export{b as AUTH_DEFAULTS,c as JwtValidator,a as LiopRpcServer,j as LiopServer,e as NerScanner,g as PII_PATTERNS,h as PII_PRESETS,i as PiiScanner,d as createOAuthServer,f as sanitizeOutput}from'./chunk-L5A64CNT.js';import'./chunk-2MGFSIXN.js';export{b as HeuristicTokenEstimator,e as LiopOTelBridge,a as RealTokenEstimator,f as TokenTelemetryEngine,d as createSyncTokenEstimator,c as createTokenEstimator}from'./chunk-VGXNGTIC.js';import'./chunk-SW53FNSN.js';import'./chunk-ANFXJGMP.js';import'./chunk-DBXGYHKY.js';export{b as LIOP_SCOPES,a as authorizeRequest}from'./chunk-SB5XJXKV.js';import'./chunk-V5MKJT6S.js';export{a as MeshNode}from'./chunk-DQ6UW6L7.js';import'./chunk-S6RJHZV2.js';import'./chunk-4C666HHU.js';var h=(e=>(e.CapabilityViolation="CapabilityViolation",e.SandboxEscape="SandboxEscape",e.PiiLeak="PiiLeak",e.InvalidIntent="InvalidIntent",e.Throttled="Throttled",e.ZkVerificationFailed="ZkVerificationFailed",e.MeshUnavailable="MeshUnavailable",e.ConnectionFailed="ConnectionFailed",e))(h||{}),n=class extends Error{code;constructor(o,t){super(t),this.name="LiopError",this.code=o;}};var x={claude:{xmlStandard:true,jsonSchemaPreferred:false},openai:{xmlStandard:false,jsonSchemaPreferred:true},gemini:{xmlStandard:false,jsonSchemaPreferred:true}};function W(i){let o=x[i],t=`[LIOP-PROTO-V1: LOGIC-ON-ORIGIN SPECIFICATION]
2
2
  You are interacting with a Logic-Injection-on-Origin Protocol (LIOP) Mesh Network.
3
3
  Unlike standard MCP where you pull context to evaluate it remotely, in LIOP you WRITE code that executes on the data's origin.
4
4
 
@@ -1,2 +1,2 @@
1
- import {a,c}from'../chunk-TZWB3DEB.js';import {a as a$1,b}from'../chunk-ANFXJGMP.js';import'../chunk-4C666HHU.js';import {Buffer}from'buffer';import g from'crypto';import {createMlKem768}from'mlkem';var R={epsilon:1,sensitivity:1,smallDatasetThreshold:50},E=1,K=10;function V(t,r){let n;do r?n=g.createHash("sha256").update(`${r.seed}:${r.counter++}`).digest().readUInt32BE(0)/4294967296-.5:n=g.randomBytes(4).readUInt32BE(0)/4294967296-.5;while(n===0||n===-0.5);return -t*Math.sign(n)*Math.log(1-2*Math.abs(n))}function G(t,r={},n){let e={...R,...r},a=e.sensitivity/e.epsilon,o=t+V(a,n);return Math.round(o*1e4)/1e4}function I(t,r,n){if(!t)return r;let e=t.toLowerCase(),a=/count|length|size|num|gainer|loser|positive|negative|nan_|null_|empty_|finite_|non_finite_|instruments|tickers|users|records/i.test(e),o=e==="total"||e==="n"||e==="total_records"||e.startsWith("total_")||e.startsWith("num_")||/total.*(count|items|entries|rows|records|tickers)/i.test(e);return a||o?1:/avg|mean|average|var|variance|std|stddev|ratio|bps|drift|pct|percent|imbalance/i.test(e)&&n>0?r/n:r}function C(t,r={},n){let e={...R,...r};if(n>=e.smallDatasetThreshold)return t;n<K&&e.epsilon<E&&(e.epsilon=E);let a;return e.seed&&(a={seed:e.seed,counter:0}),A(t,e,n,void 0,a)}function A(t,r,n,e,a){if(typeof t=="number"&&Number.isFinite(t)){let o=I(e,r.sensitivity,n),u=G(t,{...r,sensitivity:o},a),p=e!=null&&I(e,r.sensitivity,n)===1;return (Number.isInteger(t)||p)&&(u=Math.round(u)),t>=0&&(u=Math.max(0,u)),u}if(Array.isArray(t))return t.map(o=>A(o,r,n,e,a));if(t!==null&&typeof t=="object"){let o={};for(let[u,p]of Object.entries(t))o[u]=A(p,r,n,u,a);return o}return t}async function Q(t){if(t.isWarmup)return {image_id:"",output:"warm",fuel_consumed:0};let{ciphertext:r,secretKeyObj:n,wasmBinary:e,inputs:a$2,aesNonce:o,records:u,isEncrypted:p=true,dpConfig:S}=t,s,O={},T=Buffer.alloc(32);if(p){let l=new Uint8Array(n),c=new Uint8Array(r),d=(await createMlKem768()).decap(c,l),f=Buffer.from(d);T=f;let m=Buffer.from(e),k=m.subarray(-16),b=m.subarray(0,-16),w=g.createDecipheriv("aes-256-gcm",f,Buffer.from(o||new Uint8Array(12)));w.setAuthTag(k);let y=w.update(b);y=Buffer.concat([y,w.final()]),s=y;for(let[M,j]of Object.entries(a$2||{})){let D=Buffer.from(j),H=D.subarray(0,12),z=D.subarray(-16),F=D.subarray(12,-16),_=g.createDecipheriv("aes-256-gcm",f,H);_.setAuthTag(z);let v=_.update(F);v=Buffer.concat([v,_.final()]),O[M]=JSON.parse(v.toString("utf-8"));}}else e[0]===0&&e[1]===97&&e[2]===115&&e[3]===109?s=Buffer.from(e):s=Buffer.from(e).toString("utf-8");let U=s[0]===0&&s[1]===97&&s[2]===115&&s[3]===109;if(s instanceof Buffer&&U){let l=new Uint8Array(s),c=await WebAssembly.compile(l);a.analyze(c);}else s instanceof Buffer&&!U&&(s=s.toString("utf-8"));typeof s=="string"&&(s=a$1(s));let x=new c;await x.init();try{let l=await x.execute(s,u,O),c=l.output,h;typeof s=="string"?h=Buffer.from(s,"utf-8"):h=new Uint8Array(s);let d=b(h).toString("hex"),f=g.createHash("sha256").update(JSON.stringify(u||[])).digest("hex");S&&(c=C(c,{...S,seed:`${f}:${d}`},u?.length||0));let m=Buffer.from(JSON.stringify({image_id:d,dataset_hash:f,output_hash:g.createHash("sha256").update(typeof c=="string"?c:c===void 0?"undefined":JSON.stringify(c)).digest("hex"),fuel:l.fuelConsumed,ts:Date.now()})),k=g.createHmac("sha256",T).update(m).digest(),b$1=Buffer.alloc(2);b$1.writeUInt16BE(m.length);let y=Buffer.concat([Buffer.from([1]),b$1,m,k]).toString("base64");return {image_id:d,zk_receipt:y,output:c,fuel_consumed:l.fuelConsumed}}finally{await x.teardown();}}export{Q as default};//# sourceMappingURL=logic-execution.js.map
1
+ import {a,c}from'../chunk-RYYRR4N5.js';import {a as a$1,b}from'../chunk-ANFXJGMP.js';import'../chunk-4C666HHU.js';import {Buffer}from'buffer';import g from'crypto';import {createMlKem768}from'mlkem';var R={epsilon:1,sensitivity:1,smallDatasetThreshold:50},L=1,K=10;function V(t,n){let r;do n?r=g.createHash("sha256").update(`${n.seed}:${n.counter++}`).digest().readUInt32BE(0)/4294967296-.5:r=g.randomBytes(4).readUInt32BE(0)/4294967296-.5;while(r===0||r===-0.5);return -t*Math.sign(r)*Math.log(1-2*Math.abs(r))}function G(t,n={},r){let e={...R,...n},o=e.sensitivity/e.epsilon,a=t+V(o,r);return Math.round(a*1e4)/1e4}function E(t,n,r){if(!t)return n;let e=t.toLowerCase(),o=/count|length|size|num|gainer|loser|positive|negative|nan_|null_|empty_|finite_|non_finite_|instruments|tickers|users|records/i.test(e),a=e==="total"||e==="n"||e==="total_records"||e.startsWith("total_")||e.startsWith("num_")||/total.*(count|items|entries|rows|records|tickers)/i.test(e);return o||a?1:/avg|mean|average|var|variance|std|stddev|ratio|bps|drift|pct|percent|imbalance/i.test(e)&&r>0?n/r:n}function W(t,n={},r){let e={...R,...n};if(r>=e.smallDatasetThreshold)return t;r<K&&e.epsilon<L&&(e.epsilon=L);let o;return e.seed&&(o={seed:e.seed,counter:0}),v(t,e,r,void 0,o)}function v(t,n,r,e,o){if(typeof t=="number"&&Number.isFinite(t)){let a=E(e,n.sensitivity,r),c=G(t,{...n,sensitivity:a},o),m=e!=null&&E(e,n.sensitivity,r)===1;return (Number.isInteger(t)||m)&&(c=Math.round(c)),t>=0&&(c=Math.max(0,c)),c}if(Array.isArray(t))return t.map(a=>v(a,n,r,e,o));if(t!==null&&typeof t=="object"){let a={};for(let[c,m]of Object.entries(t))a[c]=v(m,n,r,c,o);return a}return t}async function Q(t){if(typeof Object.prototype=="object"&&!Object.isFrozen(Object.prototype)&&(Object.freeze(Object.prototype),Object.freeze(Array.prototype),Object.freeze(String.prototype),Object.freeze(Number.prototype),Object.freeze(Boolean.prototype),Object.freeze(RegExp.prototype),Object.freeze(Map.prototype),Object.freeze(Set.prototype),Object.freeze(Promise.prototype),Object.freeze(Error.prototype)),t.isWarmup)return {image_id:"",output:"warm",fuel_consumed:0};let{ciphertext:n,secretKeyObj:r,wasmBinary:e,inputs:o,aesNonce:a$2,records:c$1,isEncrypted:m=true,dpConfig:j}=t,s,S={},A=Buffer.alloc(32);if(m){let p=new Uint8Array(r),u=new Uint8Array(n),d=(await createMlKem768()).decap(u,p),f=Buffer.from(d);A=f;let l=Buffer.from(e),x=l.subarray(-16),h=l.subarray(0,-16),O=g.createDecipheriv("aes-256-gcm",f,Buffer.from(a$2||new Uint8Array(12)));O.setAuthTag(x);let y=O.update(h);y=Buffer.concat([y,O.final()]),s=y;for(let[I,M]of Object.entries(o||{})){let k=Buffer.from(M),C=k.subarray(0,12),F=k.subarray(-16),H=k.subarray(12,-16),D=g.createDecipheriv("aes-256-gcm",f,C);D.setAuthTag(F);let _=D.update(H);_=Buffer.concat([_,D.final()]),S[I]=JSON.parse(_.toString("utf-8"));}}else e[0]===0&&e[1]===97&&e[2]===115&&e[3]===109?s=Buffer.from(e):s=Buffer.from(e).toString("utf-8");let z=s[0]===0&&s[1]===97&&s[2]===115&&s[3]===109;if(s instanceof Buffer&&z){let p=new Uint8Array(s),u=await WebAssembly.compile(p);a.analyze(u);}else s instanceof Buffer&&!z&&(s=s.toString("utf-8"));typeof s=="string"&&(s=a$1(s));let w=new c;await w.init();try{let p=await w.execute(s,c$1,S),u=p.output,b$1;typeof s=="string"?b$1=Buffer.from(s,"utf-8"):b$1=new Uint8Array(s);let d=b(b$1).toString("hex"),f=g.createHash("sha256").update(JSON.stringify(c$1||[])).digest("hex");j&&(u=W(u,{...j,seed:`${f}:${d}`},c$1?.length||0));let l=Buffer.from(JSON.stringify({image_id:d,dataset_hash:f,output_hash:g.createHash("sha256").update(typeof u=="string"?u:u===void 0?"undefined":JSON.stringify(u)).digest("hex"),fuel:p.fuelConsumed,ts:Date.now()})),x=g.createHmac("sha256",A).update(l).digest(),h=Buffer.alloc(2);h.writeUInt16BE(l.length);let y=Buffer.concat([Buffer.from([1]),h,l,x]).toString("base64");return {image_id:d,zk_receipt:y,output:u,fuel_consumed:p.fuelConsumed}}finally{await w.teardown();}}export{Q as default};//# sourceMappingURL=logic-execution.js.map
2
2
  //# sourceMappingURL=logic-execution.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/security/dp-engine.ts","../../src/workers/logic-execution.ts"],"names":["DEFAULT_DP_CONFIG","EPSILON_FLOOR","EPSILON_FLOOR_THRESHOLD","laplaceSample","scale","prngState","u","crypto","addLaplaceNoise","value","config","merged","noisyValue","deriveFieldSensitivity","key","globalSensitivity","recordCount","lk","isCountWord","isTotalCount","applyDpToOutput","output","walkAndNoise","node","currentKey","fieldSensitivity","isCountKey","item","result","processLogicExecution","data","ciphertext","secretKeyObj","wasmBinary","inputs","aesNonce","records","isEncrypted","dpConfig","decryptedPayload","decryptedInputs","sessionSecret","Buffer","sk","ct","sharedSecret","createMlKem768","aesKey","wasmBuffer","authTag","encryptedData","decipher","decrypted","encValue","valBuffer","inputNonce","valTag","valData","valDecipher","valDecrypted","isWasm","wasmBytes","compiledModule","ASTGuardian","normalizeLogicSource","sandbox","WasiSandbox","finalOutput","logicBytes","imageId","deriveLogicImageDigest","datasetHash","journal","seal","journalLen","zkReceipt"],"mappings":"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","file":"logic-execution.js","sourcesContent":["/**\n * LIOP Differential Privacy Engine — Laplace Mechanism (NIST SP 800-226)\n *\n * Applies calibrated Laplace noise to numeric query outputs,\n * providing ε-differential privacy guarantees against differencing\n * and binary search attacks (F-01, F-02 from security audit).\n *\n * Key design decisions (Phase 110 — Industrial Recalibration):\n * 1. CSPRNG: Uses crypto.randomBytes() instead of Math.random()\n * to prevent state-reconstruction attacks on the noise generator.\n * 2. Query-Aware Sensitivity: COUNT keys get sensitivity=1,\n * AVG keys get sensitivity/n, SUM keys use global config.\n * 3. Epsilon Floor: Auto-enforce ε≥1.0 for datasets with n<10\n * to prevent catastrophic utility destruction.\n *\n * Reference: Dwork & Roth 2014, \"The Algorithmic Foundations of Differential Privacy\"\n * Standards: NIST SP 800-226, Google DP Library, US Census TopDown, Apple iOS DP\n * Industry precedent: Apple (ε=2.0 Health, ε=8.0 Keyboard), US Census (ε=1.0–4.0)\n */\n\nimport crypto from \"node:crypto\";\n\n// ── Public Configuration ─────────────────────────────────────────────\n\nexport interface DpConfig {\n\t/**\n\t * Privacy budget per query (default: 1.0).\n\t * Lower = stronger privacy + more noise. Higher = weaker privacy + less noise.\n\t * Industry standard: Apple iOS Health uses ε=2.0, US Census uses ε=1.0–4.0.\n\t */\n\tepsilon: number;\n\t/**\n\t * Max change in output when one record is added/removed.\n\t * For SUM queries: set to the max plausible value of the field.\n\t * For COUNT queries: the engine automatically overrides to 1.\n\t * For AVG queries: the engine automatically divides by recordCount.\n\t * Default: 1.0 (appropriate for counts and ratios).\n\t */\n\tsensitivity: number;\n\t/**\n\t * Only apply DP noise when dataset size is below this threshold.\n\t * Large datasets have natural statistical privacy (k-anonymity).\n\t * Default: 50 (aligned with HIPAA Safe Harbor minimum).\n\t */\n\tsmallDatasetThreshold: number;\n\t/**\n\t * Optional deterministic seed (e.g., datasetHash + imageId).\n\t * Enables Deterministic Differential Privacy (DDP) for audit modes,\n\t * ensuring perfectly reproducible ZK-Receipts while preserving DP.\n\t */\n\tseed?: string;\n}\n\nconst DEFAULT_DP_CONFIG: DpConfig = {\n\tepsilon: 1.0,\n\tsensitivity: 1.0,\n\tsmallDatasetThreshold: 50,\n};\n\n/**\n * Minimum epsilon enforced for very small datasets (n < 10).\n * Apple's most sensitive category (Health Data) uses ε=2.0 on millions of records.\n * Using ε<1.0 on datasets with <10 records destroys utility completely.\n */\nconst EPSILON_FLOOR = 1.0;\nconst EPSILON_FLOOR_THRESHOLD = 10;\n\n// ── Core Laplace Mechanism ───────────────────────────────────────────\n\nexport interface PrngState {\n\tseed: string;\n\tcounter: number;\n}\n\n/**\n * Generates a sample from the Laplace(0, scale) distribution\n * using inverse CDF sampling with a CSPRNG source.\n *\n * SECURITY: Uses crypto.randomBytes() (OS-level entropy pool) instead of\n * Math.random() (Xorshift128+ PRNG). This prevents state-reconstruction\n * attacks where an adversary observing 3-5 noisy outputs could predict\n * all future noise values and strip the DP protection entirely.\n *\n * Deterministic Audit Mode: If prngState is provided, derives cryptographic\n * entropy using SHA-256 over the seed and an auto-incrementing counter,\n * guaranteeing ZK-Receipt determinism while retaining mathematical privacy.\n *\n * Reference: NIST SP 800-226 §3.2 — \"Implementations must use a CSPRNG\n * for noise generation to maintain the mathematical privacy guarantee.\"\n */\nfunction laplaceSample(scale: number, prngState?: PrngState): number {\n\tlet u: number;\n\tdo {\n\t\tif (prngState) {\n\t\t\tconst hash = crypto\n\t\t\t\t.createHash(\"sha256\")\n\t\t\t\t.update(`${prngState.seed}:${prngState.counter++}`)\n\t\t\t\t.digest();\n\t\t\t// 4 bytes → Uint32 → uniform float in (-0.5, 0.5)\n\t\t\tu = hash.readUInt32BE(0) / 0x100000000 - 0.5;\n\t\t} else {\n\t\t\tconst buf = crypto.randomBytes(4);\n\t\t\tu = buf.readUInt32BE(0) / 0x100000000 - 0.5;\n\t\t}\n\t} while (u === 0 || u === -0.5); // Ensure no exactly 0 or -0.5 for log domain\n\treturn -scale * Math.sign(u) * Math.log(1 - 2 * Math.abs(u));\n}\n\n/**\n * Applies Laplace noise to a single numeric value.\n *\n * @param value - The true computed result\n * @param config - DP configuration (epsilon, sensitivity, seed)\n * @param prngState - Optional state tracking for deterministic sampling\n * @returns Noisy value with ε-differential privacy guarantee\n */\nexport function addLaplaceNoise(\n\tvalue: number,\n\tconfig: Partial<DpConfig> = {},\n\tprngState?: PrngState,\n): number {\n\tconst merged = { ...DEFAULT_DP_CONFIG, ...config };\n\tconst scale = merged.sensitivity / merged.epsilon;\n\tconst noisyValue = value + laplaceSample(scale, prngState);\n\t// Round to 4 decimal places to prevent long random digit strings\n\t// from triggering regex-based PII egress filters (e.g. phone numbers)\n\treturn Math.round(noisyValue * 10000) / 10000;\n}\n\n// ── Query-Aware Sensitivity ─────────────────────────────────────────\n\n/**\n * Derives field-level sensitivity based on key name semantics.\n *\n * This follows Google DP's architectural separation of CountParams,\n * SumParams, and MeanParams — each with independent sensitivity.\n *\n * Axioms (Dwork & Roth 2014):\n * - COUNT: Adding/removing one record changes count by at most 1.\n * - SUM: Adding/removing one record changes sum by at most max_value.\n * - AVG: Sensitivity = max_value / n (bounded contribution).\n *\n * @param key - Output field name (e.g., \"count\", \"avg_balance\", \"totalRevenue\")\n * @param globalSensitivity - Operator-configured max change per record\n * @param recordCount - Dataset size for average normalization\n */\nfunction deriveFieldSensitivity(\n\tkey: string | undefined,\n\tglobalSensitivity: number,\n\trecordCount: number,\n): number {\n\tif (!key) return globalSensitivity;\n\n\tconst lk = key.toLowerCase();\n\n\t// COUNT queries: sensitivity is ALWAYS 1 (fundamental DP axiom)\n\t// Match unambiguous count words: count, length, size, num (anywhere in key),\n\t// as well as common filter prefixes used in audits (nan_, negative_, positive_, null_, empty_, finite_, non_finite_).\n\t// \"total\" is ambiguous (\"totalRevenue\" = SUM, \"total\" or \"total_records\" = COUNT).\n\t// Only treat \"total\" as count when it IS the key or ends with a count suffix.\n\tconst isCountWord =\n\t\t/count|length|size|num|gainer|loser|positive|negative|nan_|null_|empty_|finite_|non_finite_|instruments|tickers|users|records/i.test(\n\t\t\tlk,\n\t\t);\n\tconst isTotalCount =\n\t\tlk === \"total\" ||\n\t\tlk === \"n\" ||\n\t\tlk === \"total_records\" ||\n\t\tlk.startsWith(\"total_\") || // Catch total_tickers, total_users\n\t\tlk.startsWith(\"num_\") || // Catch num_records, num_ticks\n\t\t/total.*(count|items|entries|rows|records|tickers)/i.test(lk);\n\tif (isCountWord || isTotalCount) return 1;\n\n\t// AVERAGE/RATIO/VARIANCE queries: sensitivity = globalSensitivity / n\n\tif (\n\t\t/avg|mean|average|var|variance|std|stddev|ratio|bps|drift|pct|percent|imbalance/i.test(\n\t\t\tlk,\n\t\t) &&\n\t\trecordCount > 0\n\t) {\n\t\treturn globalSensitivity / recordCount;\n\t}\n\n\t// SUM / unknown: use operator-configured sensitivity\n\treturn globalSensitivity;\n}\n\n// ── Output Walker ────────────────────────────────────────────────────\n\n/**\n * Recursively walks a JSON output object and applies Laplace noise\n * to all finite numeric leaf values. Non-numeric values (strings,\n * booleans, null) are preserved unchanged.\n *\n * IMPORTANT: This function NEVER mutates the input object.\n * It always returns a new object tree, preserving data integrity\n * of the original sandbox output for ZK-Receipt verification.\n *\n * @param output - The sandbox computation result\n * @param config - DP configuration (epsilon, sensitivity, threshold)\n * @param recordCount - Source dataset size (noise only if < threshold)\n * @returns New object with noisy numeric values (never mutates input)\n */\nexport function applyDpToOutput(\n\toutput: unknown,\n\tconfig: Partial<DpConfig> = {},\n\trecordCount: number,\n): unknown {\n\tconst merged = { ...DEFAULT_DP_CONFIG, ...config };\n\n\t// Large datasets have natural statistical privacy — skip noise\n\tif (recordCount >= merged.smallDatasetThreshold) {\n\t\treturn output;\n\t}\n\n\t// NIST SP 800-226: For very small datasets, enforce minimum epsilon\n\t// to prevent catastrophic utility destruction. Apple uses ε≥2.0 even\n\t// for health data on millions of records; using ε<1.0 on n<10 is\n\t// mathematically equivalent to random number generation.\n\tif (recordCount < EPSILON_FLOOR_THRESHOLD && merged.epsilon < EPSILON_FLOOR) {\n\t\tmerged.epsilon = EPSILON_FLOOR;\n\t}\n\n\tlet prngState: PrngState | undefined;\n\tif (merged.seed) {\n\t\tprngState = { seed: merged.seed, counter: 0 };\n\t}\n\n\treturn walkAndNoise(output, merged, recordCount, undefined, prngState);\n}\n\n/**\n * Internal recursive walker that applies noise to numeric leaves.\n * Handles: numbers, arrays, objects (arbitrary nesting depth).\n *\n * Uses query-aware sensitivity: COUNT keys → sensitivity=1,\n * AVG keys → sensitivity/n, SUM/unknown → global sensitivity.\n */\nfunction walkAndNoise(\n\tnode: unknown,\n\tconfig: DpConfig,\n\trecordCount: number,\n\tcurrentKey?: string,\n\tprngState?: PrngState,\n): unknown {\n\tif (typeof node === \"number\" && Number.isFinite(node)) {\n\t\t// Query-aware sensitivity per Google DP / NIST SP 800-226\n\t\tconst fieldSensitivity = deriveFieldSensitivity(\n\t\t\tcurrentKey,\n\t\t\tconfig.sensitivity,\n\t\t\trecordCount,\n\t\t);\n\t\tlet noisyValue = addLaplaceNoise(\n\t\t\tnode,\n\t\t\t{\n\t\t\t\t...config,\n\t\t\t\tsensitivity: fieldSensitivity,\n\t\t\t},\n\t\t\tprngState,\n\t\t);\n\n\t\t// Semantic heuristics to preserve structural invariants:\n\t\t// Reuse the same count-key detection logic as deriveFieldSensitivity\n\t\tconst isCountKey =\n\t\t\tcurrentKey != null &&\n\t\t\tderiveFieldSensitivity(currentKey, config.sensitivity, recordCount) === 1;\n\n\t\t// If original was an integer OR key suggests a count, force integer\n\t\t// (US Census TopDown: all counts must be non-negative integers)\n\t\tif (Number.isInteger(node) || isCountKey) {\n\t\t\tnoisyValue = Math.round(noisyValue);\n\t\t}\n\n\t\t// If original was non-negative, clamp to 0\n\t\t// (US Census TopDown: enforces non-negative constraint in post-processing)\n\t\tif (node >= 0) {\n\t\t\tnoisyValue = Math.max(0, noisyValue);\n\t\t}\n\n\t\treturn noisyValue;\n\t}\n\n\tif (Array.isArray(node)) {\n\t\t// Pass currentKey down for array items so they inherit semantics\n\t\treturn node.map((item) =>\n\t\t\twalkAndNoise(item, config, recordCount, currentKey, prngState),\n\t\t);\n\t}\n\n\tif (node !== null && typeof node === \"object\") {\n\t\tconst result: Record<string, unknown> = {};\n\t\tfor (const [key, value] of Object.entries(\n\t\t\tnode as Record<string, unknown>,\n\t\t)) {\n\t\t\tresult[key] = walkAndNoise(value, config, recordCount, key, prngState);\n\t\t}\n\t\treturn result;\n\t}\n\n\t// Strings, booleans, null — pass through unchanged\n\treturn node;\n}\n","import { Buffer } from \"node:buffer\";\nimport crypto from \"node:crypto\";\nimport { createMlKem768 } from \"mlkem\";\nimport {\n\tderiveLogicImageDigest,\n\tnormalizeLogicSource,\n} from \"../crypto/logic-image-id.js\";\nimport { ASTGuardian } from \"../sandbox/guardian.js\";\nimport { WasiSandbox } from \"../sandbox/wasi.js\";\nimport { applyDpToOutput } from \"../security/dp-engine.js\";\n\nexport interface WorkerData {\n\tisWarmup?: boolean;\n\tciphertext?: Uint8Array;\n\tsecretKeyObj?: ArrayLike<number>;\n\tkyberPublicKey?: Uint8Array;\n\twasmBinary?: Uint8Array; // Can also be JS code in non-encrypted mode\n\tinputs?: Record<string, Uint8Array>;\n\trecords?: Record<string, unknown>[];\n\tsessionToken?: string;\n\tisEncrypted?: boolean;\n\taesNonce?: Uint8Array;\n\tdpConfig?: {\n\t\tepsilon: number;\n\t\tsensitivity: number;\n\t\tsmallDatasetThreshold: number;\n\t};\n}\n\nexport default async function processLogicExecution(data: WorkerData): Promise<{\n\timage_id: string;\n\toutput: unknown;\n\tfuel_consumed: number;\n\tzk_receipt?: string;\n}> {\n\tif (data.isWarmup) {\n\t\treturn {\n\t\t\timage_id: \"\",\n\t\t\toutput: \"warm\",\n\t\t\tfuel_consumed: 0,\n\t\t};\n\t}\n\n\tconst {\n\t\tciphertext,\n\t\tsecretKeyObj,\n\t\twasmBinary,\n\t\tinputs,\n\t\taesNonce,\n\t\trecords,\n\t\tisEncrypted = true,\n\t\tdpConfig,\n\t} = data as Required<WorkerData>;\n\n\tlet decryptedPayload: Buffer | string;\n\tconst decryptedInputs: Record<string, unknown> = {};\n\tlet sessionSecret = Buffer.alloc(32); // Fallback if plain text (no PQC)\n\n\tif (isEncrypted) {\n\t\t// 1. Decapsulate Kyber secret\n\t\tconst sk = new Uint8Array(secretKeyObj);\n\t\tconst ct = new Uint8Array(ciphertext);\n\t\tconst kem = await createMlKem768();\n\t\tconst sharedSecret = kem.decap(ct, sk);\n\t\tconst aesKey = Buffer.from(sharedSecret);\n\t\tsessionSecret = aesKey;\n\n\t\t// 2. Decrypt Main Payload (WASM/JS Code)\n\t\t// LIOP Serialization: Ciphertext = EncryptedData + 16-byte AuthTag\n\t\tconst wasmBuffer = Buffer.from(wasmBinary);\n\t\tconst authTag = wasmBuffer.subarray(-16);\n\t\tconst encryptedData = wasmBuffer.subarray(0, -16);\n\n\t\tconst decipher = crypto.createDecipheriv(\n\t\t\t\"aes-256-gcm\",\n\t\t\taesKey,\n\t\t\tBuffer.from(aesNonce || new Uint8Array(12)),\n\t\t);\n\t\tdecipher.setAuthTag(authTag);\n\t\tlet decrypted = decipher.update(encryptedData);\n\t\tdecrypted = Buffer.concat([decrypted, decipher.final()]);\n\t\tdecryptedPayload = decrypted;\n\n\t\t// 3. Decrypt Inputs\n\t\tfor (const [key, encValue] of Object.entries(inputs || {})) {\n\t\t\tconst valBuffer = Buffer.from(encValue);\n\t\t\t// Extract 12-byte prepended nonce, ciphertext, and 16-byte AuthTag\n\t\t\tconst inputNonce = valBuffer.subarray(0, 12);\n\t\t\tconst valTag = valBuffer.subarray(-16);\n\t\t\tconst valData = valBuffer.subarray(12, -16);\n\n\t\t\tconst valDecipher = crypto.createDecipheriv(\n\t\t\t\t\"aes-256-gcm\",\n\t\t\t\taesKey,\n\t\t\t\tinputNonce,\n\t\t\t);\n\t\t\tvalDecipher.setAuthTag(valTag);\n\t\t\tlet valDecrypted = valDecipher.update(valData);\n\t\t\tvalDecrypted = Buffer.concat([valDecrypted, valDecipher.final()]);\n\t\t\tdecryptedInputs[key] = JSON.parse(valDecrypted.toString(\"utf-8\"));\n\t\t}\n\t} else {\n\t\t// Transparent mode: payload is provided directly\n\t\t// If it's WASM (Magic bytes: \\0asm), keep as Buffer\n\t\tif (\n\t\t\twasmBinary[0] === 0x00 &&\n\t\t\twasmBinary[1] === 0x61 &&\n\t\t\twasmBinary[2] === 0x73 &&\n\t\t\twasmBinary[3] === 0x6d\n\t\t) {\n\t\t\tdecryptedPayload = Buffer.from(wasmBinary);\n\t\t} else {\n\t\t\tdecryptedPayload = Buffer.from(wasmBinary).toString(\"utf-8\");\n\t\t}\n\t}\n\n\t// 3. Inspect AST with Guardian-TS (if WASM)\n\tconst isWasm =\n\t\tdecryptedPayload[0] === 0x00 &&\n\t\tdecryptedPayload[1] === 0x61 &&\n\t\tdecryptedPayload[2] === 0x73 &&\n\t\tdecryptedPayload[3] === 0x6d;\n\n\tif (decryptedPayload instanceof Buffer && isWasm) {\n\t\t// Ensure we pass a compatible BufferSource\n\t\tconst wasmBytes = new Uint8Array(decryptedPayload);\n\t\tconst compiledModule = await WebAssembly.compile(wasmBytes);\n\t\tASTGuardian.analyze(compiledModule);\n\t} else if (decryptedPayload instanceof Buffer && !isWasm) {\n\t\tdecryptedPayload = decryptedPayload.toString(\"utf-8\");\n\t}\n\n\t// Strip only a whole-document LIOP envelope (see logic-image-id.ts).\n\tif (typeof decryptedPayload === \"string\") {\n\t\tdecryptedPayload = normalizeLogicSource(decryptedPayload);\n\t}\n\n\t// 4. Instantiate and Execute WASI Sandbox (or V8 Fallback)\n\tconst sandbox = new WasiSandbox();\n\tawait sandbox.init();\n\n\ttry {\n\t\tconst result = await sandbox.execute(\n\t\t\tdecryptedPayload,\n\t\t\trecords,\n\t\t\tdecryptedInputs,\n\t\t);\n\n\t\tlet finalOutput = result.output;\n\n\t\t// Pre-compute Image ID and Dataset Hash for Audit Trail & DP Seeding\n\t\tlet logicBytes: Uint8Array;\n\t\tif (typeof decryptedPayload === \"string\") {\n\t\t\tlogicBytes = Buffer.from(decryptedPayload, \"utf-8\");\n\t\t} else {\n\t\t\tlogicBytes = new Uint8Array(decryptedPayload);\n\t\t}\n\t\tconst imageId = deriveLogicImageDigest(logicBytes).toString(\"hex\");\n\n\t\t// Phase 110: Include dataset_hash for SOX audit trail compliance.\n\t\t// This SHA-256 anchor proves the underlying dataset was identical\n\t\t// across consecutive queries, separating DP noise from data mutation.\n\t\tconst datasetHash = crypto\n\t\t\t.createHash(\"sha256\")\n\t\t\t.update(JSON.stringify(records || []))\n\t\t\t.digest(\"hex\");\n\n\t\t// Apply Differential Privacy before committing to the ZK-Receipt\n\t\tif (dpConfig) {\n\t\t\tfinalOutput = applyDpToOutput(\n\t\t\t\tfinalOutput,\n\t\t\t\t{\n\t\t\t\t\t...dpConfig,\n\t\t\t\t\tseed: `${datasetHash}:${imageId}`,\n\t\t\t\t},\n\t\t\t\trecords?.length || 0,\n\t\t\t);\n\t\t}\n\n\t\t// 5. Generate Cryptographic Proof of Execution (HMAC-SHA256 Commitment)\n\n\t\tconst journal = Buffer.from(\n\t\t\tJSON.stringify({\n\t\t\t\timage_id: imageId,\n\t\t\t\tdataset_hash: datasetHash,\n\t\t\t\toutput_hash: crypto\n\t\t\t\t\t.createHash(\"sha256\")\n\t\t\t\t\t.update(\n\t\t\t\t\t\ttypeof finalOutput === \"string\"\n\t\t\t\t\t\t\t? finalOutput\n\t\t\t\t\t\t\t: finalOutput === undefined\n\t\t\t\t\t\t\t\t? \"undefined\"\n\t\t\t\t\t\t\t\t: JSON.stringify(finalOutput),\n\t\t\t\t\t)\n\t\t\t\t\t.digest(\"hex\"),\n\t\t\t\tfuel: result.fuelConsumed,\n\t\t\t\tts: Date.now(),\n\t\t\t}),\n\t\t);\n\n\t\tconst seal = crypto\n\t\t\t.createHmac(\"sha256\", sessionSecret)\n\t\t\t.update(journal)\n\t\t\t.digest();\n\t\tconst journalLen = Buffer.alloc(2);\n\t\tjournalLen.writeUInt16BE(journal.length);\n\t\tconst receiptBuf = Buffer.concat([\n\t\t\tBuffer.from([0x01]), // Receipt format v1\n\t\t\tjournalLen,\n\t\t\tjournal,\n\t\t\tseal, // 32 bytes HMAC\n\t\t]);\n\t\tconst zkReceipt = receiptBuf.toString(\"base64\");\n\n\t\treturn {\n\t\t\timage_id: imageId,\n\t\t\tzk_receipt: zkReceipt,\n\t\t\toutput: finalOutput,\n\t\t\tfuel_consumed: result.fuelConsumed,\n\t\t};\n\t} finally {\n\t\tawait sandbox.teardown();\n\t}\n}\n"]}
1
+ {"version":3,"sources":["../../src/security/dp-engine.ts","../../src/workers/logic-execution.ts"],"names":["DEFAULT_DP_CONFIG","EPSILON_FLOOR","EPSILON_FLOOR_THRESHOLD","laplaceSample","scale","prngState","u","crypto","addLaplaceNoise","value","config","merged","noisyValue","deriveFieldSensitivity","key","globalSensitivity","recordCount","lk","isCountWord","isTotalCount","applyDpToOutput","output","walkAndNoise","node","currentKey","fieldSensitivity","isCountKey","item","result","processLogicExecution","data","ciphertext","secretKeyObj","wasmBinary","inputs","aesNonce","records","isEncrypted","dpConfig","decryptedPayload","decryptedInputs","sessionSecret","Buffer","sk","ct","sharedSecret","createMlKem768","aesKey","wasmBuffer","authTag","encryptedData","decipher","decrypted","encValue","valBuffer","inputNonce","valTag","valData","valDecipher","valDecrypted","isWasm","wasmBytes","compiledModule","ASTGuardian","normalizeLogicSource","sandbox","WasiSandbox","finalOutput","logicBytes","imageId","deriveLogicImageDigest","datasetHash","journal","seal","journalLen","zkReceipt"],"mappings":"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","file":"logic-execution.js","sourcesContent":["/**\n * LIOP Differential Privacy Engine — Laplace Mechanism (NIST SP 800-226)\n *\n * Applies calibrated Laplace noise to numeric query outputs,\n * providing ε-differential privacy guarantees against differencing\n * and binary search attacks (F-01, F-02 from security audit).\n *\n * Key design decisions (Phase 110 — Industrial Recalibration):\n * 1. CSPRNG: Uses crypto.randomBytes() instead of Math.random()\n * to prevent state-reconstruction attacks on the noise generator.\n * 2. Query-Aware Sensitivity: COUNT keys get sensitivity=1,\n * AVG keys get sensitivity/n, SUM keys use global config.\n * 3. Epsilon Floor: Auto-enforce ε≥1.0 for datasets with n<10\n * to prevent catastrophic utility destruction.\n *\n * Reference: Dwork & Roth 2014, \"The Algorithmic Foundations of Differential Privacy\"\n * Standards: NIST SP 800-226, Google DP Library, US Census TopDown, Apple iOS DP\n * Industry precedent: Apple (ε=2.0 Health, ε=8.0 Keyboard), US Census (ε=1.0–4.0)\n */\n\nimport crypto from \"node:crypto\";\n\n// ── Public Configuration ─────────────────────────────────────────────\n\nexport interface DpConfig {\n\t/**\n\t * Privacy budget per query (default: 1.0).\n\t * Lower = stronger privacy + more noise. Higher = weaker privacy + less noise.\n\t * Industry standard: Apple iOS Health uses ε=2.0, US Census uses ε=1.0–4.0.\n\t */\n\tepsilon: number;\n\t/**\n\t * Max change in output when one record is added/removed.\n\t * For SUM queries: set to the max plausible value of the field.\n\t * For COUNT queries: the engine automatically overrides to 1.\n\t * For AVG queries: the engine automatically divides by recordCount.\n\t * Default: 1.0 (appropriate for counts and ratios).\n\t */\n\tsensitivity: number;\n\t/**\n\t * Only apply DP noise when dataset size is below this threshold.\n\t * Large datasets have natural statistical privacy (k-anonymity).\n\t * Default: 50 (aligned with HIPAA Safe Harbor minimum).\n\t */\n\tsmallDatasetThreshold: number;\n\t/**\n\t * Optional deterministic seed (e.g., datasetHash + imageId).\n\t * Enables Deterministic Differential Privacy (DDP) for audit modes,\n\t * ensuring perfectly reproducible ZK-Receipts while preserving DP.\n\t */\n\tseed?: string;\n}\n\nconst DEFAULT_DP_CONFIG: DpConfig = {\n\tepsilon: 1.0,\n\tsensitivity: 1.0,\n\tsmallDatasetThreshold: 50,\n};\n\n/**\n * Minimum epsilon enforced for very small datasets (n < 10).\n * Apple's most sensitive category (Health Data) uses ε=2.0 on millions of records.\n * Using ε<1.0 on datasets with <10 records destroys utility completely.\n */\nconst EPSILON_FLOOR = 1.0;\nconst EPSILON_FLOOR_THRESHOLD = 10;\n\n// ── Core Laplace Mechanism ───────────────────────────────────────────\n\nexport interface PrngState {\n\tseed: string;\n\tcounter: number;\n}\n\n/**\n * Generates a sample from the Laplace(0, scale) distribution\n * using inverse CDF sampling with a CSPRNG source.\n *\n * SECURITY: Uses crypto.randomBytes() (OS-level entropy pool) instead of\n * Math.random() (Xorshift128+ PRNG). This prevents state-reconstruction\n * attacks where an adversary observing 3-5 noisy outputs could predict\n * all future noise values and strip the DP protection entirely.\n *\n * Deterministic Audit Mode: If prngState is provided, derives cryptographic\n * entropy using SHA-256 over the seed and an auto-incrementing counter,\n * guaranteeing ZK-Receipt determinism while retaining mathematical privacy.\n *\n * Reference: NIST SP 800-226 §3.2 — \"Implementations must use a CSPRNG\n * for noise generation to maintain the mathematical privacy guarantee.\"\n */\nfunction laplaceSample(scale: number, prngState?: PrngState): number {\n\tlet u: number;\n\tdo {\n\t\tif (prngState) {\n\t\t\tconst hash = crypto\n\t\t\t\t.createHash(\"sha256\")\n\t\t\t\t.update(`${prngState.seed}:${prngState.counter++}`)\n\t\t\t\t.digest();\n\t\t\t// 4 bytes → Uint32 → uniform float in (-0.5, 0.5)\n\t\t\tu = hash.readUInt32BE(0) / 0x100000000 - 0.5;\n\t\t} else {\n\t\t\tconst buf = crypto.randomBytes(4);\n\t\t\tu = buf.readUInt32BE(0) / 0x100000000 - 0.5;\n\t\t}\n\t} while (u === 0 || u === -0.5); // Ensure no exactly 0 or -0.5 for log domain\n\treturn -scale * Math.sign(u) * Math.log(1 - 2 * Math.abs(u));\n}\n\n/**\n * Applies Laplace noise to a single numeric value.\n *\n * @param value - The true computed result\n * @param config - DP configuration (epsilon, sensitivity, seed)\n * @param prngState - Optional state tracking for deterministic sampling\n * @returns Noisy value with ε-differential privacy guarantee\n */\nexport function addLaplaceNoise(\n\tvalue: number,\n\tconfig: Partial<DpConfig> = {},\n\tprngState?: PrngState,\n): number {\n\tconst merged = { ...DEFAULT_DP_CONFIG, ...config };\n\tconst scale = merged.sensitivity / merged.epsilon;\n\tconst noisyValue = value + laplaceSample(scale, prngState);\n\t// Round to 4 decimal places to prevent long random digit strings\n\t// from triggering regex-based PII egress filters (e.g. phone numbers)\n\treturn Math.round(noisyValue * 10000) / 10000;\n}\n\n// ── Query-Aware Sensitivity ─────────────────────────────────────────\n\n/**\n * Derives field-level sensitivity based on key name semantics.\n *\n * This follows Google DP's architectural separation of CountParams,\n * SumParams, and MeanParams — each with independent sensitivity.\n *\n * Axioms (Dwork & Roth 2014):\n * - COUNT: Adding/removing one record changes count by at most 1.\n * - SUM: Adding/removing one record changes sum by at most max_value.\n * - AVG: Sensitivity = max_value / n (bounded contribution).\n *\n * @param key - Output field name (e.g., \"count\", \"avg_balance\", \"totalRevenue\")\n * @param globalSensitivity - Operator-configured max change per record\n * @param recordCount - Dataset size for average normalization\n */\nfunction deriveFieldSensitivity(\n\tkey: string | undefined,\n\tglobalSensitivity: number,\n\trecordCount: number,\n): number {\n\tif (!key) return globalSensitivity;\n\n\tconst lk = key.toLowerCase();\n\n\t// COUNT queries: sensitivity is ALWAYS 1 (fundamental DP axiom)\n\t// Match unambiguous count words: count, length, size, num (anywhere in key),\n\t// as well as common filter prefixes used in audits (nan_, negative_, positive_, null_, empty_, finite_, non_finite_).\n\t// \"total\" is ambiguous (\"totalRevenue\" = SUM, \"total\" or \"total_records\" = COUNT).\n\t// Only treat \"total\" as count when it IS the key or ends with a count suffix.\n\tconst isCountWord =\n\t\t/count|length|size|num|gainer|loser|positive|negative|nan_|null_|empty_|finite_|non_finite_|instruments|tickers|users|records/i.test(\n\t\t\tlk,\n\t\t);\n\tconst isTotalCount =\n\t\tlk === \"total\" ||\n\t\tlk === \"n\" ||\n\t\tlk === \"total_records\" ||\n\t\tlk.startsWith(\"total_\") || // Catch total_tickers, total_users\n\t\tlk.startsWith(\"num_\") || // Catch num_records, num_ticks\n\t\t/total.*(count|items|entries|rows|records|tickers)/i.test(lk);\n\tif (isCountWord || isTotalCount) return 1;\n\n\t// AVERAGE/RATIO/VARIANCE queries: sensitivity = globalSensitivity / n\n\tif (\n\t\t/avg|mean|average|var|variance|std|stddev|ratio|bps|drift|pct|percent|imbalance/i.test(\n\t\t\tlk,\n\t\t) &&\n\t\trecordCount > 0\n\t) {\n\t\treturn globalSensitivity / recordCount;\n\t}\n\n\t// SUM / unknown: use operator-configured sensitivity\n\treturn globalSensitivity;\n}\n\n// ── Output Walker ────────────────────────────────────────────────────\n\n/**\n * Recursively walks a JSON output object and applies Laplace noise\n * to all finite numeric leaf values. Non-numeric values (strings,\n * booleans, null) are preserved unchanged.\n *\n * IMPORTANT: This function NEVER mutates the input object.\n * It always returns a new object tree, preserving data integrity\n * of the original sandbox output for ZK-Receipt verification.\n *\n * @param output - The sandbox computation result\n * @param config - DP configuration (epsilon, sensitivity, threshold)\n * @param recordCount - Source dataset size (noise only if < threshold)\n * @returns New object with noisy numeric values (never mutates input)\n */\nexport function applyDpToOutput(\n\toutput: unknown,\n\tconfig: Partial<DpConfig> = {},\n\trecordCount: number,\n): unknown {\n\tconst merged = { ...DEFAULT_DP_CONFIG, ...config };\n\n\t// Large datasets have natural statistical privacy — skip noise\n\tif (recordCount >= merged.smallDatasetThreshold) {\n\t\treturn output;\n\t}\n\n\t// NIST SP 800-226: For very small datasets, enforce minimum epsilon\n\t// to prevent catastrophic utility destruction. Apple uses ε≥2.0 even\n\t// for health data on millions of records; using ε<1.0 on n<10 is\n\t// mathematically equivalent to random number generation.\n\tif (recordCount < EPSILON_FLOOR_THRESHOLD && merged.epsilon < EPSILON_FLOOR) {\n\t\tmerged.epsilon = EPSILON_FLOOR;\n\t}\n\n\tlet prngState: PrngState | undefined;\n\tif (merged.seed) {\n\t\tprngState = { seed: merged.seed, counter: 0 };\n\t}\n\n\treturn walkAndNoise(output, merged, recordCount, undefined, prngState);\n}\n\n/**\n * Internal recursive walker that applies noise to numeric leaves.\n * Handles: numbers, arrays, objects (arbitrary nesting depth).\n *\n * Uses query-aware sensitivity: COUNT keys → sensitivity=1,\n * AVG keys → sensitivity/n, SUM/unknown → global sensitivity.\n */\nfunction walkAndNoise(\n\tnode: unknown,\n\tconfig: DpConfig,\n\trecordCount: number,\n\tcurrentKey?: string,\n\tprngState?: PrngState,\n): unknown {\n\tif (typeof node === \"number\" && Number.isFinite(node)) {\n\t\t// Query-aware sensitivity per Google DP / NIST SP 800-226\n\t\tconst fieldSensitivity = deriveFieldSensitivity(\n\t\t\tcurrentKey,\n\t\t\tconfig.sensitivity,\n\t\t\trecordCount,\n\t\t);\n\t\tlet noisyValue = addLaplaceNoise(\n\t\t\tnode,\n\t\t\t{\n\t\t\t\t...config,\n\t\t\t\tsensitivity: fieldSensitivity,\n\t\t\t},\n\t\t\tprngState,\n\t\t);\n\n\t\t// Semantic heuristics to preserve structural invariants:\n\t\t// Reuse the same count-key detection logic as deriveFieldSensitivity\n\t\tconst isCountKey =\n\t\t\tcurrentKey != null &&\n\t\t\tderiveFieldSensitivity(currentKey, config.sensitivity, recordCount) === 1;\n\n\t\t// If original was an integer OR key suggests a count, force integer\n\t\t// (US Census TopDown: all counts must be non-negative integers)\n\t\tif (Number.isInteger(node) || isCountKey) {\n\t\t\tnoisyValue = Math.round(noisyValue);\n\t\t}\n\n\t\t// If original was non-negative, clamp to 0\n\t\t// (US Census TopDown: enforces non-negative constraint in post-processing)\n\t\tif (node >= 0) {\n\t\t\tnoisyValue = Math.max(0, noisyValue);\n\t\t}\n\n\t\treturn noisyValue;\n\t}\n\n\tif (Array.isArray(node)) {\n\t\t// Pass currentKey down for array items so they inherit semantics\n\t\treturn node.map((item) =>\n\t\t\twalkAndNoise(item, config, recordCount, currentKey, prngState),\n\t\t);\n\t}\n\n\tif (node !== null && typeof node === \"object\") {\n\t\tconst result: Record<string, unknown> = {};\n\t\tfor (const [key, value] of Object.entries(\n\t\t\tnode as Record<string, unknown>,\n\t\t)) {\n\t\t\tresult[key] = walkAndNoise(value, config, recordCount, key, prngState);\n\t\t}\n\t\treturn result;\n\t}\n\n\t// Strings, booleans, null — pass through unchanged\n\treturn node;\n}\n","import { Buffer } from \"node:buffer\";\nimport crypto from \"node:crypto\";\nimport { createMlKem768 } from \"mlkem\";\nimport {\n\tderiveLogicImageDigest,\n\tnormalizeLogicSource,\n} from \"../crypto/logic-image-id.js\";\nimport { ASTGuardian } from \"../sandbox/guardian.js\";\nimport { WasiSandbox } from \"../sandbox/wasi.js\";\nimport { applyDpToOutput } from \"../security/dp-engine.js\";\n\nexport interface WorkerData {\n\tisWarmup?: boolean;\n\tciphertext?: Uint8Array;\n\tsecretKeyObj?: ArrayLike<number>;\n\tkyberPublicKey?: Uint8Array;\n\twasmBinary?: Uint8Array; // Can also be JS code in non-encrypted mode\n\tinputs?: Record<string, Uint8Array>;\n\trecords?: Record<string, unknown>[];\n\tsessionToken?: string;\n\tisEncrypted?: boolean;\n\taesNonce?: Uint8Array;\n\tdpConfig?: {\n\t\tepsilon: number;\n\t\tsensitivity: number;\n\t\tsmallDatasetThreshold: number;\n\t};\n}\n\nexport default async function processLogicExecution(data: WorkerData): Promise<{\n\timage_id: string;\n\toutput: unknown;\n\tfuel_consumed: number;\n\tzk_receipt?: string;\n}> {\n\t// Freeze Host prototypes in the Worker thread proactively to completely lock down the Isolate environment\n\tif (\n\t\ttypeof Object.prototype === \"object\" &&\n\t\t!Object.isFrozen(Object.prototype)\n\t) {\n\t\tObject.freeze(Object.prototype);\n\t\tObject.freeze(Array.prototype);\n\t\tObject.freeze(String.prototype);\n\t\tObject.freeze(Number.prototype);\n\t\tObject.freeze(Boolean.prototype);\n\t\tObject.freeze(RegExp.prototype);\n\t\tObject.freeze(Map.prototype);\n\t\tObject.freeze(Set.prototype);\n\t\tObject.freeze(Promise.prototype);\n\t\tObject.freeze(Error.prototype);\n\t}\n\n\tif (data.isWarmup) {\n\t\treturn {\n\t\t\timage_id: \"\",\n\t\t\toutput: \"warm\",\n\t\t\tfuel_consumed: 0,\n\t\t};\n\t}\n\n\tconst {\n\t\tciphertext,\n\t\tsecretKeyObj,\n\t\twasmBinary,\n\t\tinputs,\n\t\taesNonce,\n\t\trecords,\n\t\tisEncrypted = true,\n\t\tdpConfig,\n\t} = data as Required<WorkerData>;\n\n\tlet decryptedPayload: Buffer | string;\n\tconst decryptedInputs: Record<string, unknown> = {};\n\tlet sessionSecret = Buffer.alloc(32); // Fallback if plain text (no PQC)\n\n\tif (isEncrypted) {\n\t\t// 1. Decapsulate Kyber secret\n\t\tconst sk = new Uint8Array(secretKeyObj);\n\t\tconst ct = new Uint8Array(ciphertext);\n\t\tconst kem = await createMlKem768();\n\t\tconst sharedSecret = kem.decap(ct, sk);\n\t\tconst aesKey = Buffer.from(sharedSecret);\n\t\tsessionSecret = aesKey;\n\n\t\t// 2. Decrypt Main Payload (WASM/JS Code)\n\t\t// LIOP Serialization: Ciphertext = EncryptedData + 16-byte AuthTag\n\t\tconst wasmBuffer = Buffer.from(wasmBinary);\n\t\tconst authTag = wasmBuffer.subarray(-16);\n\t\tconst encryptedData = wasmBuffer.subarray(0, -16);\n\n\t\tconst decipher = crypto.createDecipheriv(\n\t\t\t\"aes-256-gcm\",\n\t\t\taesKey,\n\t\t\tBuffer.from(aesNonce || new Uint8Array(12)),\n\t\t);\n\t\tdecipher.setAuthTag(authTag);\n\t\tlet decrypted = decipher.update(encryptedData);\n\t\tdecrypted = Buffer.concat([decrypted, decipher.final()]);\n\t\tdecryptedPayload = decrypted;\n\n\t\t// 3. Decrypt Inputs\n\t\tfor (const [key, encValue] of Object.entries(inputs || {})) {\n\t\t\tconst valBuffer = Buffer.from(encValue);\n\t\t\t// Extract 12-byte prepended nonce, ciphertext, and 16-byte AuthTag\n\t\t\tconst inputNonce = valBuffer.subarray(0, 12);\n\t\t\tconst valTag = valBuffer.subarray(-16);\n\t\t\tconst valData = valBuffer.subarray(12, -16);\n\n\t\t\tconst valDecipher = crypto.createDecipheriv(\n\t\t\t\t\"aes-256-gcm\",\n\t\t\t\taesKey,\n\t\t\t\tinputNonce,\n\t\t\t);\n\t\t\tvalDecipher.setAuthTag(valTag);\n\t\t\tlet valDecrypted = valDecipher.update(valData);\n\t\t\tvalDecrypted = Buffer.concat([valDecrypted, valDecipher.final()]);\n\t\t\tdecryptedInputs[key] = JSON.parse(valDecrypted.toString(\"utf-8\"));\n\t\t}\n\t} else {\n\t\t// Transparent mode: payload is provided directly\n\t\t// If it's WASM (Magic bytes: \\0asm), keep as Buffer\n\t\tif (\n\t\t\twasmBinary[0] === 0x00 &&\n\t\t\twasmBinary[1] === 0x61 &&\n\t\t\twasmBinary[2] === 0x73 &&\n\t\t\twasmBinary[3] === 0x6d\n\t\t) {\n\t\t\tdecryptedPayload = Buffer.from(wasmBinary);\n\t\t} else {\n\t\t\tdecryptedPayload = Buffer.from(wasmBinary).toString(\"utf-8\");\n\t\t}\n\t}\n\n\t// 3. Inspect AST with Guardian-TS (if WASM)\n\tconst isWasm =\n\t\tdecryptedPayload[0] === 0x00 &&\n\t\tdecryptedPayload[1] === 0x61 &&\n\t\tdecryptedPayload[2] === 0x73 &&\n\t\tdecryptedPayload[3] === 0x6d;\n\n\tif (decryptedPayload instanceof Buffer && isWasm) {\n\t\t// Ensure we pass a compatible BufferSource\n\t\tconst wasmBytes = new Uint8Array(decryptedPayload);\n\t\tconst compiledModule = await WebAssembly.compile(wasmBytes);\n\t\tASTGuardian.analyze(compiledModule);\n\t} else if (decryptedPayload instanceof Buffer && !isWasm) {\n\t\tdecryptedPayload = decryptedPayload.toString(\"utf-8\");\n\t}\n\n\t// Strip only a whole-document LIOP envelope (see logic-image-id.ts).\n\tif (typeof decryptedPayload === \"string\") {\n\t\tdecryptedPayload = normalizeLogicSource(decryptedPayload);\n\t}\n\n\t// 4. Instantiate and Execute WASI Sandbox (or V8 Fallback)\n\tconst sandbox = new WasiSandbox();\n\tawait sandbox.init();\n\n\ttry {\n\t\tconst result = await sandbox.execute(\n\t\t\tdecryptedPayload,\n\t\t\trecords,\n\t\t\tdecryptedInputs,\n\t\t);\n\n\t\tlet finalOutput = result.output;\n\n\t\t// Pre-compute Image ID and Dataset Hash for Audit Trail & DP Seeding\n\t\tlet logicBytes: Uint8Array;\n\t\tif (typeof decryptedPayload === \"string\") {\n\t\t\tlogicBytes = Buffer.from(decryptedPayload, \"utf-8\");\n\t\t} else {\n\t\t\tlogicBytes = new Uint8Array(decryptedPayload);\n\t\t}\n\t\tconst imageId = deriveLogicImageDigest(logicBytes).toString(\"hex\");\n\n\t\t// Phase 110: Include dataset_hash for SOX audit trail compliance.\n\t\t// This SHA-256 anchor proves the underlying dataset was identical\n\t\t// across consecutive queries, separating DP noise from data mutation.\n\t\tconst datasetHash = crypto\n\t\t\t.createHash(\"sha256\")\n\t\t\t.update(JSON.stringify(records || []))\n\t\t\t.digest(\"hex\");\n\n\t\t// Apply Differential Privacy before committing to the ZK-Receipt\n\t\tif (dpConfig) {\n\t\t\tfinalOutput = applyDpToOutput(\n\t\t\t\tfinalOutput,\n\t\t\t\t{\n\t\t\t\t\t...dpConfig,\n\t\t\t\t\tseed: `${datasetHash}:${imageId}`,\n\t\t\t\t},\n\t\t\t\trecords?.length || 0,\n\t\t\t);\n\t\t}\n\n\t\t// 5. Generate Cryptographic Proof of Execution (HMAC-SHA256 Commitment)\n\n\t\tconst journal = Buffer.from(\n\t\t\tJSON.stringify({\n\t\t\t\timage_id: imageId,\n\t\t\t\tdataset_hash: datasetHash,\n\t\t\t\toutput_hash: crypto\n\t\t\t\t\t.createHash(\"sha256\")\n\t\t\t\t\t.update(\n\t\t\t\t\t\ttypeof finalOutput === \"string\"\n\t\t\t\t\t\t\t? finalOutput\n\t\t\t\t\t\t\t: finalOutput === undefined\n\t\t\t\t\t\t\t\t? \"undefined\"\n\t\t\t\t\t\t\t\t: JSON.stringify(finalOutput),\n\t\t\t\t\t)\n\t\t\t\t\t.digest(\"hex\"),\n\t\t\t\tfuel: result.fuelConsumed,\n\t\t\t\tts: Date.now(),\n\t\t\t}),\n\t\t);\n\n\t\tconst seal = crypto\n\t\t\t.createHmac(\"sha256\", sessionSecret)\n\t\t\t.update(journal)\n\t\t\t.digest();\n\t\tconst journalLen = Buffer.alloc(2);\n\t\tjournalLen.writeUInt16BE(journal.length);\n\t\tconst receiptBuf = Buffer.concat([\n\t\t\tBuffer.from([0x01]), // Receipt format v1\n\t\t\tjournalLen,\n\t\t\tjournal,\n\t\t\tseal, // 32 bytes HMAC\n\t\t]);\n\t\tconst zkReceipt = receiptBuf.toString(\"base64\");\n\n\t\treturn {\n\t\t\timage_id: imageId,\n\t\t\tzk_receipt: zkReceipt,\n\t\t\toutput: finalOutput,\n\t\t\tfuel_consumed: result.fuelConsumed,\n\t\t};\n\t} finally {\n\t\tawait sandbox.teardown();\n\t}\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nekzus/liop",
3
- "version": "2.0.0-alpha.28",
3
+ "version": "2.0.0-alpha.29",
4
4
  "description": "Official SDK for Logic-Injection-on-Origin Protocol (LIOP). Deploy Logic-on-Origin with WebAssembly at gRPC speed and bidirectional MCP compatibility.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,31 +0,0 @@
1
- import I from'crypto';import*as i from'fs/promises';import*as h from'os';import*as f from'path';import E from'vm';import {WASI}from'wasi';var l=class extends Error{constructor(t){super(`AST Sec-Policy Violation: ${t}`),this.name="GuardianError";}},w={analyze(a){let t=WebAssembly.Module.imports(a),o=0,d=new Set(["fd_write","fd_read","fd_close","fd_seek","environ_get","environ_sizes_get","args_get","args_sizes_get","clock_time_get","random_get","proc_exit","fd_prestat_get","fd_prestat_dir_name","fd_fdstat_get"]);for(let n of t){if(n.module==="wasi_snapshot_preview1"){if(!d.has(n.name))throw new l(`Banned WASI Import Detected: ${n.module}/${n.name}`)}else throw new l(`Banned Host Import Module Detected: ${n.module}`);if(o++,o>128)throw new l("Import limit exceeded. Possible resource exhaustion attack.")}}};var x=process.emit;process.emit=(a,t,...o)=>a==="warning"&&typeof t=="object"&&t.name==="ExperimentalWarning"&&String(t.message).includes("WASI")||String(t.message).includes("importing WASI")?false:x.call(process,a,t,...o);function R(){let t=process.platform==="win32"?["APPDATA","HOMEDRIVE","HOMEPATH","LOCALAPPDATA","PATH","PROCESSOR_ARCHITECTURE","SYSTEMDRIVE","SYSTEMROOT","TEMP","USERNAME","USERPROFILE","PROGRAMFILES"]:["HOME","LOGNAME","PATH","SHELL","TERM","USER"],o={NODE_ENV:"production",LIOP_NODE:"true"};for(let d of t){let n=process.env[d];n!==void 0&&!n.startsWith("()")&&(o[d]=n);}return o}var y=class{wasi;sandboxId;workingDir;config;stdoutHandle=null;stderrHandle=null;constructor(t={}){this.sandboxId=I.randomUUID(),this.workingDir=f.join(h.tmpdir(),"liop-mesh","sandboxes",this.sandboxId),this.config=t;}async init(){try{await i.mkdir(this.workingDir,{recursive:!0}),this.stdoutHandle=await i.open(f.join(this.workingDir,"stdout.log"),"w+"),this.stderrHandle=await i.open(f.join(this.workingDir,"stderr.log"),"w+"),this.wasi=new WASI({version:"preview1",args:["liop_runtime"],env:this.config.allowEnv?{...R(),RUNTIME_ID:this.sandboxId}:{NODE_ENV:"production",LIOP_NODE:"true",RUNTIME_ID:this.sandboxId},preopens:{"/sandbox":this.workingDir,...this.config.allowedDirectories},stdout:this.stdoutHandle.fd,stderr:this.stderrHandle.fd});}catch(t){throw new Error(`Sandbox Initialization Failed: ${t instanceof Error?t.message:"FS Error"}`)}}async execute(t,o=[],d={}){let n=performance.now();if(t instanceof Buffer)try{let e=await WebAssembly.compile(new Uint8Array(t));w.analyze(e);let p=await WebAssembly.instantiate(e,this.wasi.getImportObject());this.wasi.start(p);let u=f.join(this.workingDir,"stdout.log"),s=f.join(this.workingDir,"stderr.log"),m=await i.readFile(u,"utf-8"),r=await i.readFile(s,"utf-8"),c=performance.now()-n;return {output:m||(r?`Error: ${r}`:"WASM_EXECUTION_SUCCESS"),fuelConsumed:Math.floor(c*1e3)}}catch(e){throw new Error(`WASM Runtime Error: ${e instanceof Error?e.message:String(e)}`)}else {let e=Object.create(null),p={records:o,...d};e.require=void 0,e.process=void 0,e.global=void 0,e.globalThis=void 0,e.Buffer=void 0,e.setTimeout=void 0,e.setInterval=void 0,e.setImmediate=void 0,e.queueMicrotask=void 0,e.eval=void 0,e.Function=void 0,e.SharedArrayBuffer=void 0,e.Date=void 0,e.ArrayBuffer=void 0,e.Uint8Array=void 0,e.Int8Array=void 0,e.Uint16Array=void 0,e.Int16Array=void 0,e.Uint32Array=void 0,e.Int32Array=void 0,e.Float32Array=void 0,e.Float64Array=void 0,e.BigInt64Array=void 0,e.BigUint64Array=void 0,e.DataView=void 0,e.records=JSON.parse(JSON.stringify(o)),e.env=JSON.parse(JSON.stringify(p));for(let[r,c]of Object.entries(d))e[r]=JSON.parse(JSON.stringify(c));let u=r=>{if(r&&typeof r=="object"&&!Object.isFrozen(r)){Object.freeze(r);for(let c of Object.keys(r))u(r[c]);}return r};u(e.records),u(e.env);for(let r of Object.keys(e))Object.defineProperty(e,r,{writable:false,configurable:false});let s=String(t);(/^\s*return\s/m.test(s)||!s.includes("function liop_main"))&&(s.includes("function liop_main")||(s=`function liop_main(env) {
2
- ${s}
3
- }`));let m=`
4
- (function() {
5
- "use strict";
6
- try {
7
- // Pre-execution prototype freezing (PCI-DSS Compliance)
8
- Object.freeze(Object.prototype);
9
- Object.freeze(Array.prototype);
10
- Object.freeze(String.prototype);
11
- Object.freeze(Number.prototype);
12
- Object.freeze(Boolean.prototype);
13
- Object.freeze(RegExp.prototype);
14
- Object.freeze(Map.prototype);
15
- Object.freeze(Set.prototype);
16
- Object.freeze(Promise.prototype);
17
- Object.freeze(Error.prototype);
18
- Object.freeze(Object.getPrototypeOf(function(){}));
19
-
20
- ${s}
21
- if (typeof liop_main === 'function') {
22
- return liop_main(env);
23
- }
24
- return "ERR_NO_ENTRY_POINT";
25
- } catch(e) {
26
- return "LogicError: " + e.message;
27
- }
28
- })();
29
- `;try{let r=new E.Script(m,{filename:`liop-sandbox-${this.sandboxId.slice(0,8)}.js`}),c=E.createContext(e,{name:"LIOP Isolate",origin:"liop://sandbox",microtaskMode:"afterEvaluate"}),b=r.runInContext(c,{timeout:5e3,breakOnSigint:!0,displayErrors:!0}),O=performance.now()-n,S=Math.floor(O*1500+100),g=Math.ceil(S/100)*100;if(g>1e6)throw new Error("LIOP_RESOURCE_EXHAUSTED: Execution fuel limit exceeded.");return {output:b,fuelConsumed:g}}catch(r){throw new Error(`V8 Isolate Fault: ${r instanceof Error?r.message:"Execution Timeout"}`)}}}async teardown(){try{this.stdoutHandle&&await this.stdoutHandle.close(),this.stderrHandle&&await this.stderrHandle.close(),await i.rm(this.workingDir,{recursive:!0,force:!0});}catch{}}};
30
- export{w as a,R as b,y as c};//# sourceMappingURL=chunk-TZWB3DEB.js.map
31
- //# sourceMappingURL=chunk-TZWB3DEB.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/sandbox/guardian.ts","../src/sandbox/wasi.ts"],"names":["GuardianError","message","ASTGuardian","module","imports","_importCount","ALLOWED_WASI_FUNCTIONS","imp","originalEmit","name","data","args","getDefaultEnvironment","safeKeys","env","key","val","WasiSandbox","config","crypto","WASI","error","compiledLogic","records","inputs","startTime","instance","stdoutPath","stderrPath","stdout","stderr","duration","sandboxEnv","value","deepFreeze","obj","processedLogic","scriptCode","script","vm","context","output","rawFuel","fuelUsed"],"mappings":"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","file":"chunk-TZWB3DEB.js","sourcesContent":["export class GuardianError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(`AST Sec-Policy Violation: ${message}`);\n\t\tthis.name = \"GuardianError\";\n\t}\n}\n\n/**\n * The Guardian-TS Module\n * Scans the Abstract Syntax Tree (AST) imports of incoming WASM\n * before it reaches the V8 Wasmtime engine to prevent sandbox-escape\n * zero-days, resource exhaustion bombs, and evasive execution.\n */\nexport const ASTGuardian = {\n\t/**\n\t * Analyzes the WebAssembly Module interface proactively.\n\t *\n\t * @param module - The compiled WebAssembly.Module to inspect\n\t * @throws {GuardianError} If illegal imports or capabilities are detected\n\t */\n\tanalyze(module: WebAssembly.Module): void {\n\t\tconst imports = WebAssembly.Module.imports(module);\n\t\tlet _importCount = 0;\n\n\t\tconst ALLOWED_WASI_FUNCTIONS = new Set([\n\t\t\t\"fd_write\",\n\t\t\t\"fd_read\",\n\t\t\t\"fd_close\",\n\t\t\t\"fd_seek\",\n\t\t\t\"environ_get\",\n\t\t\t\"environ_sizes_get\",\n\t\t\t\"args_get\",\n\t\t\t\"args_sizes_get\",\n\t\t\t\"clock_time_get\",\n\t\t\t\"random_get\",\n\t\t\t\"proc_exit\",\n\t\t\t\"fd_prestat_get\",\n\t\t\t\"fd_prestat_dir_name\",\n\t\t\t\"fd_fdstat_get\",\n\t\t]);\n\n\t\tfor (const imp of imports) {\n\t\t\t// Strict Sandbox Validation: Only allow WASI preview 1 specific whitelisted functions.\n\t\t\tif (imp.module === \"wasi_snapshot_preview1\") {\n\t\t\t\tif (!ALLOWED_WASI_FUNCTIONS.has(imp.name)) {\n\t\t\t\t\tthrow new GuardianError(\n\t\t\t\t\t\t`Banned WASI Import Detected: ${imp.module}/${imp.name}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new GuardianError(\n\t\t\t\t\t`Banned Host Import Module Detected: ${imp.module}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\t_importCount++;\n\n\t\t\tif (_importCount > 128) {\n\t\t\t\tthrow new GuardianError(\n\t\t\t\t\t\"Import limit exceeded. Possible resource exhaustion attack.\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// In Node.js / V8, the maximum module size and function limits\n\t\t// are natively enforced by the engine during compilation.\n\t\t// A successfully compiled WebAssembly.Module already passed structural checks.\n\t},\n};\n","import crypto from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport vm from \"node:vm\";\nimport { WASI } from \"node:wasi\";\nimport { ASTGuardian } from \"./guardian.js\";\n\n// Silence Node.js ExperimentalWarning for WASI (Industrial console parity)\nconst originalEmit = process.emit;\n// @ts-expect-error\nprocess.emit = (name, data, ...args) => {\n\tif (\n\t\t(name === \"warning\" &&\n\t\t\ttypeof data === \"object\" &&\n\t\t\t(data as Record<string, unknown>).name === \"ExperimentalWarning\" &&\n\t\t\tString((data as Record<string, unknown>).message).includes(\"WASI\")) ||\n\t\tString((data as Record<string, unknown>).message).includes(\"importing WASI\")\n\t) {\n\t\treturn false;\n\t}\n\treturn originalEmit.call(process, name, data, ...args);\n};\n\n/**\n * Returns a filtered environment object containing only safe system variables,\n * preventing exposure of sensitive credentials and shell function injection.\n */\nexport function getDefaultEnvironment(): Record<string, string> {\n\tconst isWindows = process.platform === \"win32\";\n\tconst safeKeys = isWindows\n\t\t? [\n\t\t\t\t\"APPDATA\",\n\t\t\t\t\"HOMEDRIVE\",\n\t\t\t\t\"HOMEPATH\",\n\t\t\t\t\"LOCALAPPDATA\",\n\t\t\t\t\"PATH\",\n\t\t\t\t\"PROCESSOR_ARCHITECTURE\",\n\t\t\t\t\"SYSTEMDRIVE\",\n\t\t\t\t\"SYSTEMROOT\",\n\t\t\t\t\"TEMP\",\n\t\t\t\t\"USERNAME\",\n\t\t\t\t\"USERPROFILE\",\n\t\t\t\t\"PROGRAMFILES\",\n\t\t\t]\n\t\t: [\"HOME\", \"LOGNAME\", \"PATH\", \"SHELL\", \"TERM\", \"USER\"];\n\n\tconst env: Record<string, string> = {\n\t\tNODE_ENV: \"production\",\n\t\tLIOP_NODE: \"true\",\n\t};\n\n\tfor (const key of safeKeys) {\n\t\tconst val = process.env[key];\n\t\tif (val !== undefined && !val.startsWith(\"()\")) {\n\t\t\tenv[key] = val;\n\t\t}\n\t}\n\n\treturn env;\n}\n\nexport interface SandboxConfig {\n\tallowEnv?: boolean;\n\tallowedDirectories?: Record<string, string>; // guestPath -> hostPath\n\tmemoryLimitMb?: number;\n}\n\n/**\n * LIOP WasiSandbox (Industrial Grade)\n *\n * Provides a production-grade isolated environment for executing untrusted logic.\n * Primarily uses WebAssembly (WASI) for byte-code isolation, with a hardened\n * V8 Isolate fallback for dynamic JS-to-WASM logic injection.\n */\nexport class WasiSandbox {\n\tprivate wasi!: WASI;\n\tprivate sandboxId: string;\n\tprivate workingDir: string;\n\tprivate config: SandboxConfig;\n\tprivate stdoutHandle: fs.FileHandle | null = null;\n\tprivate stderrHandle: fs.FileHandle | null = null;\n\n\tconstructor(config: SandboxConfig = {}) {\n\t\tthis.sandboxId = crypto.randomUUID();\n\t\t// Use a dedicated LIOP directory in the OS temp folder\n\t\tthis.workingDir = path.join(\n\t\t\tos.tmpdir(),\n\t\t\t\"liop-mesh\",\n\t\t\t\"sandboxes\",\n\t\t\tthis.sandboxId,\n\t\t);\n\t\tthis.config = config;\n\t}\n\n\t/**\n\t * Initializes the physical sandbox environment with strict directory lockdown.\n\t */\n\tpublic async init(): Promise<void> {\n\t\ttry {\n\t\t\tawait fs.mkdir(this.workingDir, { recursive: true });\n\n\t\t\t// Initialize WASI with explicit limits\n\t\t\tthis.stdoutHandle = await fs.open(\n\t\t\t\tpath.join(this.workingDir, \"stdout.log\"),\n\t\t\t\t\"w+\",\n\t\t\t);\n\t\t\tthis.stderrHandle = await fs.open(\n\t\t\t\tpath.join(this.workingDir, \"stderr.log\"),\n\t\t\t\t\"w+\",\n\t\t\t);\n\n\t\t\tthis.wasi = new WASI({\n\t\t\t\tversion: \"preview1\",\n\t\t\t\targs: [\"liop_runtime\"],\n\t\t\t\tenv: this.config.allowEnv\n\t\t\t\t\t? { ...getDefaultEnvironment(), RUNTIME_ID: this.sandboxId }\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tNODE_ENV: \"production\",\n\t\t\t\t\t\t\tLIOP_NODE: \"true\",\n\t\t\t\t\t\t\tRUNTIME_ID: this.sandboxId,\n\t\t\t\t\t\t},\n\t\t\t\tpreopens: {\n\t\t\t\t\t\"/sandbox\": this.workingDir,\n\t\t\t\t\t...this.config.allowedDirectories,\n\t\t\t\t},\n\t\t\t\tstdout: this.stdoutHandle.fd,\n\t\t\t\tstderr: this.stderrHandle.fd,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Sandbox Initialization Failed: ${error instanceof Error ? error.message : \"FS Error\"}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Executes logic (WASM or JS-Wrapped) with hard resource limits.\n\t */\n\tpublic async execute(\n\t\tcompiledLogic: Buffer | string,\n\t\trecords: Record<string, unknown>[] = [],\n\t\tinputs: Record<string, unknown> = {},\n\t): Promise<{ output: unknown; fuelConsumed: number }> {\n\t\tconst startTime = performance.now();\n\n\t\tif (compiledLogic instanceof Buffer) {\n\t\t\t// Path A: Native WebAssembly Isolation\n\t\t\ttry {\n\t\t\t\tconst module = await WebAssembly.compile(new Uint8Array(compiledLogic));\n\n\t\t\t\t// Tier-0 Guardian: Static analysis to prevent sandbox escapes\n\t\t\t\tASTGuardian.analyze(module);\n\n\t\t\t\tconst instance = await WebAssembly.instantiate(\n\t\t\t\t\tmodule,\n\t\t\t\t\tthis.wasi.getImportObject() as WebAssembly.Imports,\n\t\t\t\t);\n\n\t\t\t\t// Standard entry point\n\t\t\t\tthis.wasi.start(instance);\n\n\t\t\t\t// Capture output from the sandbox\n\t\t\t\tconst stdoutPath = path.join(this.workingDir, \"stdout.log\");\n\t\t\t\tconst stderrPath = path.join(this.workingDir, \"stderr.log\");\n\t\t\t\tconst stdout = await fs.readFile(stdoutPath, \"utf-8\");\n\t\t\t\tconst stderr = await fs.readFile(stderrPath, \"utf-8\");\n\n\t\t\t\tconst duration = performance.now() - startTime;\n\t\t\t\treturn {\n\t\t\t\t\toutput:\n\t\t\t\t\t\tstdout || (stderr ? `Error: ${stderr}` : \"WASM_EXECUTION_SUCCESS\"),\n\t\t\t\t\tfuelConsumed: Math.floor(duration * 1000),\n\t\t\t\t};\n\t\t\t} catch (error: unknown) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`WASM Runtime Error: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\t// Path B: Hardened V8 Isolate Fallback\n\t\t\t// Uses node:vm with zero-prototype objects to prevent prototype pollution escapes.\n\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: Required for Sandbox global poisoning\n\t\t\tconst sandboxEnv: any = Object.create(null); // Isolated global object\n\t\t\tconst env = { records, ...inputs };\n\n\t\t\t// Explicitly poison Node.js escape vectors in the context\n\t\t\tsandboxEnv.require = undefined;\n\t\t\tsandboxEnv.process = undefined;\n\t\t\tsandboxEnv.global = undefined;\n\t\t\tsandboxEnv.globalThis = undefined;\n\t\t\tsandboxEnv.Buffer = undefined;\n\t\t\tsandboxEnv.setTimeout = undefined;\n\t\t\tsandboxEnv.setInterval = undefined;\n\t\t\tsandboxEnv.setImmediate = undefined;\n\t\t\tsandboxEnv.queueMicrotask = undefined;\n\t\t\tsandboxEnv.eval = undefined;\n\t\t\tsandboxEnv.Function = undefined;\n\t\t\tsandboxEnv.SharedArrayBuffer = undefined;\n\t\t\tsandboxEnv.Date = undefined;\n\n\t\t\t// [DoS Defense] Block off-heap memory allocation vectors.\n\t\t\t// Logic-on-Origin operates on JSON data (env.records) — binary buffers\n\t\t\t// serve no legitimate purpose and enable memory exhaustion DoS.\n\t\t\t// (Uint8Array(2GB) bypassed Piscina's maxOldGenerationSizeMb limit)\n\t\t\tsandboxEnv.ArrayBuffer = undefined;\n\t\t\tsandboxEnv.Uint8Array = undefined;\n\t\t\tsandboxEnv.Int8Array = undefined;\n\t\t\tsandboxEnv.Uint16Array = undefined;\n\t\t\tsandboxEnv.Int16Array = undefined;\n\t\t\tsandboxEnv.Uint32Array = undefined;\n\t\t\tsandboxEnv.Int32Array = undefined;\n\t\t\tsandboxEnv.Float32Array = undefined;\n\t\t\tsandboxEnv.Float64Array = undefined;\n\t\t\tsandboxEnv.BigInt64Array = undefined;\n\t\t\tsandboxEnv.BigUint64Array = undefined;\n\t\t\tsandboxEnv.DataView = undefined;\n\n\t\t\t// Inject strictly monitored globals\n\t\t\tsandboxEnv.records = JSON.parse(JSON.stringify(records)); // Deep copy safety\n\t\t\tsandboxEnv.env = JSON.parse(JSON.stringify(env));\n\n\t\t\tfor (const [key, value] of Object.entries(inputs)) {\n\t\t\t\tsandboxEnv[key] = JSON.parse(JSON.stringify(value));\n\t\t\t}\n\n\t\t\t// Freeze the sandbox context to prevent mutation (SEC-GAP-1)\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: Required for recursive deep freeze of unknown data\n\t\t\tconst deepFreeze = (obj: any) => {\n\t\t\t\tif (obj && typeof obj === \"object\" && !Object.isFrozen(obj)) {\n\t\t\t\t\tObject.freeze(obj);\n\t\t\t\t\tfor (const key of Object.keys(obj)) {\n\t\t\t\t\t\tdeepFreeze(obj[key]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn obj;\n\t\t\t};\n\n\t\t\tdeepFreeze(sandboxEnv.records);\n\t\t\tdeepFreeze(sandboxEnv.env);\n\n\t\t\t// Prevent property addition/modification on global scope\n\t\t\tfor (const key of Object.keys(sandboxEnv)) {\n\t\t\t\tObject.defineProperty(sandboxEnv, key, {\n\t\t\t\t\twritable: false,\n\t\t\t\t\tconfigurable: false,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// LIOP Execution Wrapper\n\t\t\t// Host-side logic transformation to avoid 'new Function' in sandbox\n\t\t\tlet processedLogic = String(compiledLogic);\n\t\t\tif (\n\t\t\t\t/^\\s*return\\s/m.test(processedLogic) ||\n\t\t\t\t!processedLogic.includes(\"function liop_main\")\n\t\t\t) {\n\t\t\t\tif (!processedLogic.includes(\"function liop_main\")) {\n\t\t\t\t\tprocessedLogic = `function liop_main(env) {\\n${processedLogic}\\n}`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst scriptCode = `\n\t\t\t\t(function() {\n\t\t\t\t\t\"use strict\";\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Pre-execution prototype freezing (PCI-DSS Compliance)\n\t\t\t\t\t\tObject.freeze(Object.prototype);\n\t\t\t\t\t\tObject.freeze(Array.prototype);\n\t\t\t\t\t\tObject.freeze(String.prototype);\n\t\t\t\t\t\tObject.freeze(Number.prototype);\n\t\t\t\t\t\tObject.freeze(Boolean.prototype);\n\t\t\t\t\t\tObject.freeze(RegExp.prototype);\n\t\t\t\t\t\tObject.freeze(Map.prototype);\n\t\t\t\t\t\tObject.freeze(Set.prototype);\n\t\t\t\t\t\tObject.freeze(Promise.prototype);\n\t\t\t\t\t\tObject.freeze(Error.prototype);\n\t\t\t\t\t\tObject.freeze(Object.getPrototypeOf(function(){}));\n\n\t\t\t\t\t\t${processedLogic}\n\t\t\t\t\t\tif (typeof liop_main === 'function') {\n\t\t\t\t\t\t\treturn liop_main(env);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn \"ERR_NO_ENTRY_POINT\";\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\treturn \"LogicError: \" + e.message;\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t`;\n\n\t\t\ttry {\n\t\t\t\tconst script = new vm.Script(scriptCode, {\n\t\t\t\t\tfilename: `liop-sandbox-${this.sandboxId.slice(0, 8)}.js`,\n\t\t\t\t});\n\n\t\t\t\t// microtaskMode: Ensures Promises created inside the sandbox are\n\t\t\t\t// resolved within the timeout/breakOnSigint scope (Node.js ≥14.6).\n\t\t\t\t// Without this, async microtasks could escape the 5s CPU limit.\n\t\t\t\tconst context = vm.createContext(sandboxEnv, {\n\t\t\t\t\tname: \"LIOP Isolate\",\n\t\t\t\t\torigin: \"liop://sandbox\",\n\t\t\t\t\tmicrotaskMode: \"afterEvaluate\",\n\t\t\t\t});\n\n\t\t\t\t// Execution with hard CPU and Memory limits (Fuel)\n\t\t\t\tconst output = script.runInContext(context, {\n\t\t\t\t\ttimeout: 5000,\n\t\t\t\t\tbreakOnSigint: true,\n\t\t\t\t\tdisplayErrors: true,\n\t\t\t\t});\n\n\t\t\t\tconst duration = performance.now() - startTime;\n\t\t\t\t// SEC: Normalize fuel to buckets of 100 to prevent timing side-channel inference\n\t\t\t\tconst rawFuel = Math.floor(duration * 1500 + 100);\n\t\t\t\tconst fuelUsed = Math.ceil(rawFuel / 100) * 100;\n\n\t\t\t\tif (fuelUsed > 1000000) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"LIOP_RESOURCE_EXHAUSTED: Execution fuel limit exceeded.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn { output, fuelConsumed: fuelUsed };\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`V8 Isolate Fault: ${error instanceof Error ? error.message : \"Execution Timeout\"}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Physically cleans up the sandbox and releases resources.\n\t */\n\tpublic async teardown(): Promise<void> {\n\t\ttry {\n\t\t\tif (this.stdoutHandle) await this.stdoutHandle.close();\n\t\t\tif (this.stderrHandle) await this.stderrHandle.close();\n\t\t\tawait fs.rm(this.workingDir, { recursive: true, force: true });\n\t\t} catch (_e) {\n\t\t\t// Silent fail on teardown to prevent process crashes\n\t\t}\n\t}\n}\n"]}