@nekzus/liop 2.1.0-alpha.3 → 2.1.0-alpha.4
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 +10 -0
- package/dist/bin/agent.js +1 -1
- package/dist/bin/agent.js.map +1 -1
- package/dist/bridge.js +1 -1
- package/dist/chunk-AEWYQWVZ.js +42 -0
- package/dist/chunk-AEWYQWVZ.js.map +1 -0
- package/dist/chunk-CPLE5VZ5.js +33 -0
- package/dist/chunk-CPLE5VZ5.js.map +1 -0
- package/dist/{chunk-GI2LSJYZ.js → chunk-JIUFKRVG.js} +3 -3
- package/dist/{chunk-GI2LSJYZ.js.map → chunk-JIUFKRVG.js.map} +1 -1
- package/dist/chunk-TNBXOZNG.js +2 -0
- package/dist/chunk-TNBXOZNG.js.map +1 -0
- package/dist/{chunk-G45SRWLR.js → chunk-VDNV2I4I.js} +3 -3
- package/dist/{chunk-G45SRWLR.js.map → chunk-VDNV2I4I.js.map} +1 -1
- package/dist/client.js +1 -1
- package/dist/gateway.js +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/kyber-2WDOTUQX.js +2 -0
- package/dist/{kyber-NONMBQNH.js.map → kyber-2WDOTUQX.js.map} +1 -1
- package/dist/mesh.js +1 -1
- package/dist/server.js +1 -1
- package/dist/types.js +1 -1
- package/dist/verifier-KZ4QYF5M.js +2 -0
- package/dist/{verifier-XU2DB56Z.js.map → verifier-KZ4QYF5M.js.map} +1 -1
- package/dist/workers/logic-execution.js +1 -1
- package/dist/workers/logic-execution.js.map +1 -1
- package/dist/workers/zk-verifier.js +1 -1
- package/dist/workers/zk-verifier.js.map +1 -1
- package/package.json +7 -7
- package/dist/chunk-4C666HHU.js +0 -2
- package/dist/chunk-4C666HHU.js.map +0 -1
- package/dist/chunk-I46YEWND.js +0 -33
- package/dist/chunk-I46YEWND.js.map +0 -1
- package/dist/chunk-QNFD36B7.js +0 -54
- package/dist/chunk-QNFD36B7.js.map +0 -1
- package/dist/chunk-VQUSWD4U.js +0 -2
- package/dist/chunk-VQUSWD4U.js.map +0 -1
- package/dist/chunk-XOITNPU3.js +0 -2
- package/dist/chunk-XOITNPU3.js.map +0 -1
- package/dist/kyber-NONMBQNH.js +0 -2
- package/dist/verifier-XU2DB56Z.js +0 -2
package/README.md
CHANGED
|
@@ -536,6 +536,16 @@ This package is continuously tested across multiple platforms and Node.js versio
|
|
|
536
536
|
|
|
537
537
|
> To run tests locally or contribute, clone the [repository](https://github.com/Nekzus/LIOP) and follow the [Contributing Guide](https://github.com/Nekzus/LIOP/blob/main/CONTRIBUTING.md).
|
|
538
538
|
|
|
539
|
+
## Security Auditing & Supply Chain
|
|
540
|
+
|
|
541
|
+
This repository is integrated with [Socket.dev](https://socket.dev) to continuously monitor and secure the software supply chain against malicious packages, hidden telemetry, and dependency vulnerabilities.
|
|
542
|
+
|
|
543
|
+
You can run security audits and check package health scores directly from the monorepo root:
|
|
544
|
+
|
|
545
|
+
- **Scan Monorepo Dependencies:** `pnpm socket:scan` (performs a security scan and generates a report)
|
|
546
|
+
- **Check SDK Security Score:** `pnpm socket:score` (shows the detailed package score for the SDK in Markdown format)
|
|
547
|
+
- **Fix Vulnerabilities:** `pnpm socket:fix` (automatically remediates known CVEs in package.json)
|
|
548
|
+
|
|
539
549
|
---
|
|
540
550
|
|
|
541
551
|
## Related
|
package/dist/bin/agent.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {j}from'../chunk-
|
|
2
|
+
import {j}from'../chunk-AEWYQWVZ.js';import {g}from'../chunk-CPLE5VZ5.js';import'../chunk-PWCXZWSE.js';import'../chunk-ANFXJGMP.js';import'../chunk-DBXGYHKY.js';import'../chunk-SB5XJXKV.js';import'../chunk-V5MKJT6S.js';import'../chunk-RWRRBYG4.js';import {a as a$1}from'../chunk-DQ6UW6L7.js';import {a}from'../chunk-S6RJHZV2.js';import*as l from'fs';import*as w from'os';import*as u from'path';import {multiaddr}from'@multiformats/multiaddr';async function x(t){try{let o=t.endsWith("/health")?t:`${t}/health`,d=await fetch(o,{headers:{Accept:"application/json"},signal:AbortSignal.timeout(1e4)});if(!d.ok)return null;let e=await d.json();if(!e.mesh?.multiaddrs?.length||!e.mesh?.peerId)return null;let p=e.mesh.multiaddrs.find(c=>c.includes("/tcp/")&&!c.includes("/ws")&&!c.includes("/ip4/127.0.0.1/"));if(!p)return null;let r=E()?R(p):p;if(!r||r===p){let c=new URL(t).hostname;r=p.replace(/\/ip4\/[^/]+/,`/ip4/${c}`);}return r?(r+=r.includes("/p2p/")?"":`/p2p/${e.mesh.peerId}`,r):null}catch{return null}}function L(t){let o=t.trim(),d=/\/ip4\/172\.(1[6-9]|2[0-9]|3[0-1])\.[0-9]{1,3}\.[0-9]{1,3}/,e=/\/ip4\/127\.0\.0\.1/,p=/\/ip4\/192\.168\.[0-9]{1,3}\.[0-9]{1,3}/;if(d.test(o)||e.test(o)||p.test(o)){let r="127.0.0.1",c=o.replace(d,`/ip4/${r}`).replace(e,`/ip4/${r}`).replace(p,`/ip4/${r}`);return c!==o&&a.info(`[LIOP-Agent] \u{1F504} Local Routing Hack \u2192 Forced 127.0.0.1: ${c}`),c}return o}function R(t){return t.includes("/ip4/172.20.0.10")?t.replace(/\/ip4\/172\.20\.0\.10\/tcp\/[0-9]+/,"/ip4/127.0.0.1/tcp/13001"):t.includes("/ip4/172.20.0.11")?t.replace(/\/ip4\/172\.20\.0\.11\/tcp\/[0-9]+/,"/ip4/127.0.0.1/tcp/13003"):t.includes("/ip4/172.20.0.12")?t.replace(/\/ip4\/172\.20\.0\.12\/tcp\/[0-9]+/,"/ip4/127.0.0.1/tcp/13004"):t.includes("/ip4/172.20.0.13")?t.replace(/\/ip4\/172\.20\.0\.13\/tcp\/[0-9]+/,"/ip4/127.0.0.1/tcp/13005"):t.includes("/ip4/127.0.0.1/tcp/4000")||t.includes("/ip4/127.0.0.1/tcp/3000")?null:t}function D(t){try{let o=new URL(t);return (o.hostname==="127.0.0.1"||o.hostname==="localhost")&&(o.port==="13000"||o.port==="13001")}catch{return false}}function E(){return process.env.NODE_ENV==="development"||process.env.NODE_ENV==="test"||process.env.LIOP_DOCKER_MAP==="true"||process.env.LIOP_DEV_MODE==="true"||!!process.env.LIOP_NEXUS_URL&&D(process.env.LIOP_NEXUS_URL)}async function M(){if((process.platform==="win32"||process.platform==="darwin")&&!process.execArgv.includes("--use-system-ca")&&!(process.env.NODE_OPTIONS??"").includes("--use-system-ca")){let{spawn:s}=await import('child_process'),n=s(process.execPath,["--use-system-ca",...process.argv.slice(1)],{stdio:"inherit",env:process.env});n.on("exit",a=>process.exit(a??1)),n.on("error",()=>process.exit(1)),await new Promise(()=>{});return}let t=new Date().toISOString();a.info(`[LIOP-Agent] \u{1F680} Version 1.2.0-alpha.9 | Build: ${t}`);let o=u.join(w.homedir(),".liop"),d=u.join(o,"identity.json");l.existsSync(o)||l.mkdirSync(o,{recursive:true});let e=[],p=process.argv.slice(2);if(p.length>0&&(e=p.filter(s=>s.startsWith("/"))),e.length===0){let s=[];if(process.env.LIOP_BOOTSTRAP_FILE){a.warn("LIOP_BOOTSTRAP_FILE is deprecated and will be removed in the next major version. Use LIOP_NEXUS_URL for Auto-Discovery instead.");let n=u.resolve(process.env.LIOP_BOOTSTRAP_FILE);if(l.existsSync(n)){let a=l.readFileSync(n,"utf8").trim();a&&e.push(L(a));}}s.push(process.cwd(),u.join(process.cwd(),"tests/infra/nexus-data"),o,u.join(u.dirname(new URL(import.meta.url).pathname).replace(/^\/([A-Z]:)/,"$1"),"../../tests/infra/nexus-data"));for(let n of s)try{if(l.existsSync(n)){let h=l.readdirSync(n).filter(g=>g.endsWith(".multiaddr"));for(let g of h){let $=u.join(n,g),v=l.readFileSync($,"utf8").trim();if(v){let S=L(v);e.includes(S)||(e.push(S),a.info(`[LIOP-Agent] \u2705 Loaded beacon: ${g} from ${n}`));}}if(e.length>0)break}}catch{}}if(process.env.LIOP_NEXUS_URL){let s=process.env.LIOP_NEXUS_URL;a.info(`[LIOP-Agent] \u{1F310} Running parallel discovery from: ${s} (Sources Found: ${e.length})`);let n=await x(s);if(n){let a$1=L(n);e.includes(a$1)||(e.push(a$1),a.info(`[LIOP-Agent] \u2705 Added bootstrap from URL discovery: ${a$1}`));}}e.length===0&&process.env.LIOP_BOOTSTRAP&&e.push(process.env.LIOP_BOOTSTRAP.trim()),e.length===0&&e.push("/ip4/127.0.0.1/tcp/13001/p2p/12D3KooWD8FUFdnLQzzLFNdicsaTknM5cpD7os9sK9NWVSVABJMD"),e=e.filter(s=>{try{return multiaddr(s),!0}catch{return a.warn(`[LIOP-Agent] Ignoring invalid bootstrap multiaddr: ${s}`),false}}),e.length===0&&(a.info("[LIOP-Agent] No bootstrap nodes configured. Operating in standalone mode."),a.info("[LIOP-Agent] Pass a multiaddr as argument or create 'nexus.multiaddr' file."));let r=new j({name:"@nekzus/liop",version:"1.0.0"});r.enableZeroShotAutonomy();let c=new a$1({identityPath:d,bootstrapNodes:e,addressMapper:E()?R:void 0});await c.start();let f=new g(r,c);f.onToolsChanged=()=>{process.stdout.write(`{"jsonrpc":"2.0","method":"notifications/tools/list_changed"}
|
|
3
3
|
`),process.stdout.write(`{"jsonrpc":"2.0","method":"notifications/resources/list_changed"}
|
|
4
4
|
`);},setTimeout(()=>{let s=c.getRoutingTableSize?.()||0;a.info(`[LIOP-Agent] Warm-up complete. Routing Table size: ${s}`),f.refreshManifestCache(true).catch(()=>{});},2e3);let O=1e4,T=12e4,m=O,P=()=>{setTimeout(async()=>{let s=f.getCacheSize();await f.refreshManifestCache(true).catch(()=>{});let n=f.getCacheSize();n!==s?(m=O,a.info(`[LIOP-Agent] Topology change detected (${s} \u2192 ${n}). Resetting poll to ${O/1e3}s.`)):m=Math.min(Math.round(m*1.5),T),P();},m);};P();let I=(await import('readline')).createInterface({input:process.stdin,terminal:false});process.stdout.on("error",s=>{s.code==="EPIPE"&&process.exit(0);}),I.on("line",async s=>{let n=s.trim();if(n)try{let a=JSON.parse(n);if(a.method){let h=await f.dispatch(a);h&&process.stdout.write(`${JSON.stringify(h)}
|
|
5
5
|
`);}}catch{}}),I.on("close",()=>{process.exit(0);}),a.info("[LIOP-Agent] Guarding Claude Desktop via STDIO."),a.info(`[LIOP-Agent] P2P Mesh: Joined (${e.length} bootstraps)`),a.info("[LIOP-Agent] Tool discovery: Dynamic via /liop/manifest/1.0.0"),process.on("SIGINT",async()=>{await c.stop(),process.exit(0);});}M().catch(t=>{a.error(`[LIOP-Agent] Fatal Error: ${t.message}`),process.exit(1);});//# sourceMappingURL=agent.js.map
|
package/dist/bin/agent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/bin/agent.ts"],"names":["resolveBootstrapFromUrl","url","healthUrl","response","data","tcpAddr","a","resolved","shouldEnableDockerMap","industrialAddressMapper","urlHost","normalizeBootstrap","addr","trimmed","dockerIpRegex","loopbackRegex","physicalIpRegex","targetIp","normalized","log","isDockerDemoHost","urlStr","u","main","spawn","child","code","buildTime","liopDir","identityPath","bootstrapNodes","args","searchDirs","filePath","dir","multiaddrFiles","f","file","nexusUrl","multiaddr","liopServer","LiopServer","meshNode","MeshNode","router","LiopMcpRouter","rtSize","POLL_BASE_MS","POLL_MAX_MS","pollIntervalMs","scheduleAdaptivePoll","prevSize","newSize","rl","err","line","request"],"mappings":"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","file":"agent.js","sourcesContent":["#!/usr/bin/env node\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { multiaddr } from \"@multiformats/multiaddr\";\nimport { LiopMcpRouter } from \"../gateway/router.js\";\nimport { MeshNode } from \"../mesh/index.js\";\nimport { LiopServer } from \"../server/index.js\";\nimport type { McpRequest } from \"../types.js\";\nimport { log } from \"../utils/logger.js\";\n\n/**\n * Resolves a full libp2p multiaddr (with PeerID) from a LIOP node's\n * HTTP health endpoint. This enables zero-config bootstrap — users\n * only need to provide a URL, not a cryptographic PeerID.\n *\n * @param url - HTTP URL of a LIOP node's health endpoint (e.g. \"http://host:3000\")\n * @returns Full multiaddr string with PeerID, or null if resolution fails\n */\nasync function resolveBootstrapFromUrl(url: string): Promise<string | null> {\n\ttry {\n\t\tconst healthUrl = url.endsWith(\"/health\") ? url : `${url}/health`;\n\t\tconst response = await fetch(healthUrl, {\n\t\t\theaders: { Accept: \"application/json\" },\n\t\t\tsignal: AbortSignal.timeout(10000), // Increased to 10s\n\t\t});\n\t\tif (!response.ok) return null;\n\n\t\tconst data = await response.json();\n\t\tif (!data.mesh?.multiaddrs?.length || !data.mesh?.peerId) return null;\n\n\t\t// Find TCP multiaddr (prefer non-websocket for stability)\n\t\tconst tcpAddr = data.mesh.multiaddrs.find(\n\t\t\t(a: string) =>\n\t\t\t\ta.includes(\"/tcp/\") &&\n\t\t\t\t!a.includes(\"/ws\") &&\n\t\t\t\t!a.includes(\"/ip4/127.0.0.1/\"),\n\t\t);\n\t\tif (!tcpAddr) return null;\n\n\t\t// Rewrite internal Docker IP using the address mapper if enabled\n\t\tlet resolved = shouldEnableDockerMap()\n\t\t\t? industrialAddressMapper(tcpAddr)\n\t\t\t: tcpAddr;\n\t\tif (!resolved || resolved === tcpAddr) {\n\t\t\tconst urlHost = new URL(url).hostname;\n\t\t\tresolved = tcpAddr.replace(/\\/ip4\\/[^/]+/, `/ip4/${urlHost}`);\n\t\t}\n\n\t\tif (!resolved) return null;\n\n\t\tresolved += resolved.includes(\"/p2p/\") ? \"\" : `/p2p/${data.mesh.peerId}`;\n\n\t\treturn resolved;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Normalizes a bootstrap multiaddr string.\n * If the address contains a Docker bridge IP (172.16-31.x.x) or Loopback (127.0.0.1),\n * rewrites it to the host accessible via LIOP_NEXUS_URL (e.g. WSL2 IP).\n * This is critical when WSL2 mirror-mode networking is broken.\n */\nfunction normalizeBootstrap(addr: string): string {\n\tconst trimmed = addr.trim();\n\t// Remap Docker bridge IPs and ANY external physical IPs to 127.0.0.1\n\t// because Test-NetConnection confirmed 127.0.0.1 is the only reliable path to Docker ports.\n\tconst dockerIpRegex =\n\t\t/\\/ip4\\/172\\.(1[6-9]|2[0-9]|3[0-1])\\.[0-9]{1,3}\\.[0-9]{1,3}/;\n\tconst loopbackRegex = /\\/ip4\\/127\\.0\\.0\\.1/;\n\tconst physicalIpRegex = /\\/ip4\\/192\\.168\\.[0-9]{1,3}\\.[0-9]{1,3}/;\n\n\tif (\n\t\tdockerIpRegex.test(trimmed) ||\n\t\tloopbackRegex.test(trimmed) ||\n\t\tphysicalIpRegex.test(trimmed)\n\t) {\n\t\tconst targetIp = \"127.0.0.1\";\n\t\tconst normalized = trimmed\n\t\t\t.replace(dockerIpRegex, `/ip4/${targetIp}`)\n\t\t\t.replace(loopbackRegex, `/ip4/${targetIp}`)\n\t\t\t.replace(physicalIpRegex, `/ip4/${targetIp}`);\n\n\t\tif (normalized !== trimmed) {\n\t\t\tlog.info(\n\t\t\t\t`[LIOP-Agent] 🔄 Local Routing Hack → Forced 127.0.0.1: ${normalized}`,\n\t\t\t);\n\t\t}\n\t\treturn normalized;\n\t}\n\n\treturn trimmed;\n}\n\n/**\n * industrialAddressMapper\n *\n * Maps Docker-internal IPs to host-published ports for local demo environments.\n * Activated when any of the following conditions are met:\n * - NODE_ENV is \"development\" or \"test\"\n * - LIOP_DOCKER_MAP=\"true\" or LIOP_DEV_MODE=\"true\" is set\n * - LIOP_NEXUS_URL points to a local Docker demo port (127.0.0.1:13000|13001)\n *\n * Nexus (172.20.0.10) -> 13001\n * Vault (172.20.0.11) -> 13003\n * Bank (172.20.0.12) -> 13004\n * Oracle(172.20.0.13) -> 13005\n */\nfunction industrialAddressMapper(addr: string): string | null {\n\tif (addr.includes(\"/ip4/172.20.0.10\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.10\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13001\",\n\t\t);\n\tif (addr.includes(\"/ip4/172.20.0.11\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.11\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13003\",\n\t\t);\n\tif (addr.includes(\"/ip4/172.20.0.12\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.12\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13004\",\n\t\t);\n\tif (addr.includes(\"/ip4/172.20.0.13\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.13\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13005\",\n\t\t);\n\n\t// Drop container-internal loopbacks to prevent the Host Agent from dialing itself or conflicting ports\n\tif (\n\t\taddr.includes(\"/ip4/127.0.0.1/tcp/4000\") ||\n\t\taddr.includes(\"/ip4/127.0.0.1/tcp/3000\")\n\t) {\n\t\treturn null;\n\t}\n\n\treturn addr;\n}\n\n/**\n * Checks if a URL points to the local Docker demo environment\n * (loopback address on known demo ports).\n */\nfunction isDockerDemoHost(urlStr: string): boolean {\n\ttry {\n\t\tconst u = new URL(urlStr);\n\t\treturn (\n\t\t\t(u.hostname === \"127.0.0.1\" || u.hostname === \"localhost\") &&\n\t\t\t(u.port === \"13000\" || u.port === \"13001\")\n\t\t);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Determines whether Docker address mapping should be enabled.\n * True when running in development/test mode, when explicitly requested\n * via LIOP_DOCKER_MAP/LIOP_DEV_MODE, or when the Nexus URL points to\n * a local Docker demo port.\n */\nfunction shouldEnableDockerMap(): boolean {\n\treturn (\n\t\tprocess.env.NODE_ENV === \"development\" ||\n\t\tprocess.env.NODE_ENV === \"test\" ||\n\t\tprocess.env.LIOP_DOCKER_MAP === \"true\" ||\n\t\tprocess.env.LIOP_DEV_MODE === \"true\" ||\n\t\t(!!process.env.LIOP_NEXUS_URL &&\n\t\t\tisDockerDemoHost(process.env.LIOP_NEXUS_URL))\n\t);\n}\n\n/**\n * LIOP Agent (Zero-Config CLI)\n *\n * Secure Logic-on-Origin gateway for Claude Desktop.\n * Communicates via STDIO / JSON-RPC.\n *\n * All tool discovery is DYNAMIC via the /liop/manifest/1.0.0 protocol.\n * No hardcoded tools, PeerIDs, or port mappings.\n */\nasync function main() {\n\t// Auto-Relaunch: Ensure system CA certificates are loaded for TLS compatibility.\n\t// Corporate proxies (Cloudflare WARP, Zscaler) inject custom root CAs into the\n\t// OS certificate store. Node.js ignores these by default, causing UNABLE_TO_VERIFY_LEAF_SIGNATURE.\n\t// Pattern: if --use-system-ca is not active, re-spawn with the flag transparently.\n\t// stdio: \"inherit\" ensures Claude Desktop's JSON-RPC pipe is passed through cleanly.\n\tif (\n\t\t(process.platform === \"win32\" || process.platform === \"darwin\") &&\n\t\t!process.execArgv.includes(\"--use-system-ca\") &&\n\t\t!(process.env.NODE_OPTIONS ?? \"\").includes(\"--use-system-ca\")\n\t) {\n\t\tconst { spawn } = await import(\"node:child_process\");\n\t\tconst child = spawn(\n\t\t\tprocess.execPath,\n\t\t\t[\"--use-system-ca\", ...process.argv.slice(1)],\n\t\t\t{ stdio: \"inherit\", env: process.env },\n\t\t);\n\t\tchild.on(\"exit\", (code) => process.exit(code ?? 1));\n\t\tchild.on(\"error\", () => process.exit(1));\n\t\t// Block parent — child handles all I/O from here\n\t\tawait new Promise(() => {});\n\t\treturn;\n\t}\n\n\tconst buildTime = new Date().toISOString();\n\tlog.info(`[LIOP-Agent] 🚀 Version 1.2.0-alpha.9 | Build: ${buildTime}`);\n\n\tconst liopDir = path.join(os.homedir(), \".liop\");\n\tconst identityPath = path.join(liopDir, \"identity.json\");\n\n\tif (!fs.existsSync(liopDir)) {\n\t\tfs.mkdirSync(liopDir, { recursive: true });\n\t}\n\n\t// 1. Determine Bootstrap Nodes (Zero-Config Discovery)\n\tlet bootstrapNodes: string[] = [];\n\n\t// Command line arguments take precedence\n\tconst args = process.argv.slice(2);\n\tif (args.length > 0) {\n\t\tbootstrapNodes = args.filter((a) => a.startsWith(\"/\"));\n\t}\n\n\t// Priority 1: Physical Beacons (Industrial Pattern) - DETERMINISTIC & INSTANT\n\tif (bootstrapNodes.length === 0) {\n\t\tconst searchDirs = [];\n\n\t\t// Priority 1.1: Explicit file from environment variable\n\t\tif (process.env.LIOP_BOOTSTRAP_FILE) {\n\t\t\tlog.warn(\n\t\t\t\t\"LIOP_BOOTSTRAP_FILE is deprecated and will be removed in the next major version. \" +\n\t\t\t\t\t\"Use LIOP_NEXUS_URL for Auto-Discovery instead.\",\n\t\t\t);\n\t\t\tconst filePath = path.resolve(process.env.LIOP_BOOTSTRAP_FILE);\n\t\t\tif (fs.existsSync(filePath)) {\n\t\t\t\tconst addr = fs.readFileSync(filePath, \"utf8\").trim();\n\t\t\t\tif (addr) bootstrapNodes.push(normalizeBootstrap(addr));\n\t\t\t}\n\t\t}\n\n\t\t// Priority 1.2: Traditional locations (Scan for all *.multiaddr)\n\t\tsearchDirs.push(\n\t\t\tprocess.cwd(),\n\t\t\tpath.join(process.cwd(), \"tests/infra/nexus-data\"),\n\t\t\tliopDir,\n\t\t\tpath.join(\n\t\t\t\tpath\n\t\t\t\t\t.dirname(new URL(import.meta.url).pathname)\n\t\t\t\t\t.replace(/^\\/([A-Z]:)/, \"$1\"),\n\t\t\t\t\"../../tests/infra/nexus-data\",\n\t\t\t),\n\t\t);\n\n\t\tfor (const dir of searchDirs) {\n\t\t\ttry {\n\t\t\t\tif (fs.existsSync(dir)) {\n\t\t\t\t\tconst files = fs.readdirSync(dir);\n\t\t\t\t\tconst multiaddrFiles = files.filter((f) => f.endsWith(\".multiaddr\"));\n\n\t\t\t\t\tfor (const file of multiaddrFiles) {\n\t\t\t\t\t\tconst filePath = path.join(dir, file);\n\t\t\t\t\t\tconst addr = fs.readFileSync(filePath, \"utf8\").trim();\n\t\t\t\t\t\tif (addr) {\n\t\t\t\t\t\t\tconst normalized = normalizeBootstrap(addr);\n\t\t\t\t\t\t\tif (!bootstrapNodes.includes(normalized)) {\n\t\t\t\t\t\t\t\tbootstrapNodes.push(normalized);\n\t\t\t\t\t\t\t\tlog.info(`[LIOP-Agent] ✅ Loaded beacon: ${file} from ${dir}`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// If we found any beacons in this directory, we consider discovery successful for this layer\n\t\t\t\t\tif (bootstrapNodes.length > 0) break;\n\t\t\t\t}\n\t\t\t} catch (_e) {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t}\n\t}\n\n\t// Priority 2: Auto-Discovery via NEXUS URL (Aggressive Parallel Discovery)\n\tif (process.env.LIOP_NEXUS_URL) {\n\t\tconst nexusUrl = process.env.LIOP_NEXUS_URL;\n\t\tlog.info(\n\t\t\t`[LIOP-Agent] 🌐 Running parallel discovery from: ${nexusUrl} (Sources Found: ${bootstrapNodes.length})`,\n\t\t);\n\n\t\tconst resolved = await resolveBootstrapFromUrl(nexusUrl);\n\t\tif (resolved) {\n\t\t\tconst normalized = normalizeBootstrap(resolved);\n\t\t\tif (!bootstrapNodes.includes(normalized)) {\n\t\t\t\tbootstrapNodes.push(normalized);\n\t\t\t\tlog.info(\n\t\t\t\t\t`[LIOP-Agent] ✅ Added bootstrap from URL discovery: ${normalized}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Priority 3: Environment variable (direct multiaddr)\n\tif (bootstrapNodes.length === 0 && process.env.LIOP_BOOTSTRAP) {\n\t\tbootstrapNodes.push(process.env.LIOP_BOOTSTRAP.trim());\n\t}\n\n\t// Final fallback: local Nexus bootstrap for demo environments.\n\t// Avoid injecting stale static peer IDs when discovery already found valid peers.\n\tif (bootstrapNodes.length === 0) {\n\t\tbootstrapNodes.push(\n\t\t\t\"/ip4/127.0.0.1/tcp/13001/p2p/12D3KooWD8FUFdnLQzzLFNdicsaTknM5cpD7os9sK9NWVSVABJMD\",\n\t\t);\n\t}\n\n\t// Sanitize/validate all candidate multiaddrs so malformed PeerIDs don't crash startup.\n\tbootstrapNodes = bootstrapNodes.filter((addr) => {\n\t\ttry {\n\t\t\tmultiaddr(addr);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\tlog.warn(`[LIOP-Agent] Ignoring invalid bootstrap multiaddr: ${addr}`);\n\t\t\treturn false;\n\t\t}\n\t});\n\n\t// If no bootstrap nodes found, the agent operates in standalone mode.\n\t// It will only serve local tools until peers are discovered.\n\tif (bootstrapNodes.length === 0) {\n\t\tlog.info(\n\t\t\t\"[LIOP-Agent] No bootstrap nodes configured. Operating in standalone mode.\",\n\t\t);\n\t\tlog.info(\n\t\t\t\"[LIOP-Agent] Pass a multiaddr as argument or create 'nexus.multiaddr' file.\",\n\t\t);\n\t}\n\n\t// Initialize local server node (lightweight, no tools registered locally)\n\tconst liopServer = new LiopServer({\n\t\tname: \"@nekzus/liop\",\n\t\tversion: \"1.0.0\",\n\t});\n\n\t// Enable Zero-Shot Autonomy (Industrial Prompt Injection)\n\tliopServer.enableZeroShotAutonomy();\n\n\t// 2. Mesh Node Configuration\n\tconst meshNode = new MeshNode({\n\t\tidentityPath: identityPath,\n\t\tbootstrapNodes: bootstrapNodes,\n\t\taddressMapper: shouldEnableDockerMap()\n\t\t\t? industrialAddressMapper\n\t\t\t: undefined,\n\t});\n\n\t// Start P2P Mesh\n\tawait meshNode.start();\n\n\t// 3. Initialize the Dynamic Router\n\t// No hardcoded tools — all discovery happens via liop:manifest protocol\n\tconst router = new LiopMcpRouter(liopServer, meshNode);\n\n\t// Proactive Notification to Claude Desktop when tools/resources are discovered dynamically\n\trouter.onToolsChanged = () => {\n\t\tprocess.stdout.write(\n\t\t\t`{\"jsonrpc\":\"2.0\",\"method\":\"notifications/tools/list_changed\"}\\n`,\n\t\t);\n\t\tprocess.stdout.write(\n\t\t\t`{\"jsonrpc\":\"2.0\",\"method\":\"notifications/resources/list_changed\"}\\n`,\n\t\t);\n\t};\n\n\t// Initial warming period (2s) then Adaptive Background Discovery\n\t// Polls DHT for new nodes and triggers onToolsChanged when topology shifts.\n\t// Uses exponential backoff to reduce polling load on stable meshes.\n\tsetTimeout(() => {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: access internal for telemetry\n\t\tconst rtSize = (meshNode as any).getRoutingTableSize?.() || 0;\n\t\tlog.info(`[LIOP-Agent] Warm-up complete. Routing Table size: ${rtSize}`);\n\t\trouter.refreshManifestCache(true).catch(() => {});\n\t}, 2000);\n\n\tconst POLL_BASE_MS = 10_000;\n\tconst POLL_MAX_MS = 120_000;\n\tlet pollIntervalMs = POLL_BASE_MS;\n\n\tconst scheduleAdaptivePoll = () => {\n\t\tsetTimeout(async () => {\n\t\t\tconst prevSize = router.getCacheSize();\n\t\t\tawait router.refreshManifestCache(true).catch(() => {});\n\t\t\tconst newSize = router.getCacheSize();\n\n\t\t\tif (newSize !== prevSize) {\n\t\t\t\t// Topology changed — reset to aggressive polling\n\t\t\t\tpollIntervalMs = POLL_BASE_MS;\n\t\t\t\tlog.info(\n\t\t\t\t\t`[LIOP-Agent] Topology change detected (${prevSize} → ${newSize}). Resetting poll to ${POLL_BASE_MS / 1000}s.`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Stable — relax polling interval (factor 1.5)\n\t\t\t\tpollIntervalMs = Math.min(\n\t\t\t\t\tMath.round(pollIntervalMs * 1.5),\n\t\t\t\t\tPOLL_MAX_MS,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tscheduleAdaptivePoll();\n\t\t}, pollIntervalMs);\n\t};\n\n\tscheduleAdaptivePoll();\n\n\t// 4. STDIO Transport — Buffered Line Reader\n\t// Uses readline to guarantee complete JSON-RPC messages before parsing.\n\t// Raw stdin.on(\"data\") can fragment large payloads across multiple chunks.\n\tconst readline = await import(\"node:readline\");\n\tconst rl = readline.createInterface({\n\t\tinput: process.stdin,\n\t\tterminal: false,\n\t});\n\n\tprocess.stdout.on(\"error\", (err: Error & { code?: string }) => {\n\t\tif (err.code === \"EPIPE\") {\n\t\t\tprocess.exit(0); // Graceful exit when Claude Desktop disconnects\n\t\t}\n\t});\n\n\trl.on(\"line\", async (line) => {\n\t\tconst trimmed = line.trim();\n\t\tif (!trimmed) return;\n\n\t\ttry {\n\t\t\tconst request = JSON.parse(trimmed) as McpRequest;\n\t\t\tif (request.method) {\n\t\t\t\tconst response = await router.dispatch(request);\n\t\t\t\tif (response) {\n\t\t\t\t\tprocess.stdout.write(`${JSON.stringify(response)}\\n`);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (_err) {\n\t\t\t// Silent catch for binary noise or malformed lines\n\t\t}\n\t});\n\n\trl.on(\"close\", () => {\n\t\tprocess.exit(0);\n\t});\n\n\t// Status directed only to stderr\n\tlog.info(`[LIOP-Agent] Guarding Claude Desktop via STDIO.`);\n\tlog.info(\n\t\t`[LIOP-Agent] P2P Mesh: Joined (${bootstrapNodes.length} bootstraps)`,\n\t);\n\tlog.info(\"[LIOP-Agent] Tool discovery: Dynamic via /liop/manifest/1.0.0\");\n\n\tprocess.on(\"SIGINT\", async () => {\n\t\tawait meshNode.stop();\n\t\tprocess.exit(0);\n\t});\n}\n\nmain().catch((err) => {\n\tlog.error(`[LIOP-Agent] Fatal Error: ${err.message}`);\n\tprocess.exit(1);\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/bin/agent.ts"],"names":["resolveBootstrapFromUrl","url","healthUrl","response","data","tcpAddr","a","resolved","shouldEnableDockerMap","industrialAddressMapper","urlHost","normalizeBootstrap","addr","trimmed","dockerIpRegex","loopbackRegex","physicalIpRegex","targetIp","normalized","log","isDockerDemoHost","urlStr","u","main","spawn","child","code","buildTime","liopDir","identityPath","bootstrapNodes","args","searchDirs","filePath","dir","multiaddrFiles","f","file","nexusUrl","multiaddr","liopServer","LiopServer","meshNode","MeshNode","router","LiopMcpRouter","rtSize","POLL_BASE_MS","POLL_MAX_MS","pollIntervalMs","scheduleAdaptivePoll","prevSize","newSize","rl","err","line","request"],"mappings":"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","file":"agent.js","sourcesContent":["#!/usr/bin/env node\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { multiaddr } from \"@multiformats/multiaddr\";\nimport { LiopMcpRouter } from \"../gateway/router.js\";\nimport { MeshNode } from \"../mesh/index.js\";\nimport { LiopServer } from \"../server/index.js\";\nimport type { McpRequest } from \"../types.js\";\nimport { log } from \"../utils/logger.js\";\n\n/**\n * Resolves a full libp2p multiaddr (with PeerID) from a LIOP node's\n * HTTP health endpoint. This enables zero-config bootstrap — users\n * only need to provide a URL, not a cryptographic PeerID.\n *\n * @param url - HTTP URL of a LIOP node's health endpoint (e.g. \"http://host:3000\")\n * @returns Full multiaddr string with PeerID, or null if resolution fails\n */\nasync function resolveBootstrapFromUrl(url: string): Promise<string | null> {\n\ttry {\n\t\tconst healthUrl = url.endsWith(\"/health\") ? url : `${url}/health`;\n\t\tconst response = await fetch(healthUrl, {\n\t\t\theaders: { Accept: \"application/json\" },\n\t\t\tsignal: AbortSignal.timeout(10000), // Increased to 10s\n\t\t});\n\t\tif (!response.ok) return null;\n\n\t\tconst data = await response.json();\n\t\tif (!data.mesh?.multiaddrs?.length || !data.mesh?.peerId) return null;\n\n\t\t// Find TCP multiaddr (prefer non-websocket for stability)\n\t\tconst tcpAddr = data.mesh.multiaddrs.find(\n\t\t\t(a: string) =>\n\t\t\t\ta.includes(\"/tcp/\") &&\n\t\t\t\t!a.includes(\"/ws\") &&\n\t\t\t\t!a.includes(\"/ip4/127.0.0.1/\"),\n\t\t);\n\t\tif (!tcpAddr) return null;\n\n\t\t// Rewrite internal Docker IP using the address mapper if enabled\n\t\tlet resolved = shouldEnableDockerMap()\n\t\t\t? industrialAddressMapper(tcpAddr)\n\t\t\t: tcpAddr;\n\t\tif (!resolved || resolved === tcpAddr) {\n\t\t\tconst urlHost = new URL(url).hostname;\n\t\t\tresolved = tcpAddr.replace(/\\/ip4\\/[^/]+/, `/ip4/${urlHost}`);\n\t\t}\n\n\t\tif (!resolved) return null;\n\n\t\tresolved += resolved.includes(\"/p2p/\") ? \"\" : `/p2p/${data.mesh.peerId}`;\n\n\t\treturn resolved;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Normalizes a bootstrap multiaddr string.\n * If the address contains a Docker bridge IP (172.16-31.x.x) or Loopback (127.0.0.1),\n * rewrites it to the host accessible via LIOP_NEXUS_URL (e.g. WSL2 IP).\n * This is critical when WSL2 mirror-mode networking is broken.\n */\nfunction normalizeBootstrap(addr: string): string {\n\tconst trimmed = addr.trim();\n\t// Remap Docker bridge IPs and ANY external physical IPs to 127.0.0.1\n\t// because Test-NetConnection confirmed 127.0.0.1 is the only reliable path to Docker ports.\n\tconst dockerIpRegex =\n\t\t/\\/ip4\\/172\\.(1[6-9]|2[0-9]|3[0-1])\\.[0-9]{1,3}\\.[0-9]{1,3}/;\n\tconst loopbackRegex = /\\/ip4\\/127\\.0\\.0\\.1/;\n\tconst physicalIpRegex = /\\/ip4\\/192\\.168\\.[0-9]{1,3}\\.[0-9]{1,3}/;\n\n\tif (\n\t\tdockerIpRegex.test(trimmed) ||\n\t\tloopbackRegex.test(trimmed) ||\n\t\tphysicalIpRegex.test(trimmed)\n\t) {\n\t\tconst targetIp = \"127.0.0.1\";\n\t\tconst normalized = trimmed\n\t\t\t.replace(dockerIpRegex, `/ip4/${targetIp}`)\n\t\t\t.replace(loopbackRegex, `/ip4/${targetIp}`)\n\t\t\t.replace(physicalIpRegex, `/ip4/${targetIp}`);\n\n\t\tif (normalized !== trimmed) {\n\t\t\tlog.info(\n\t\t\t\t`[LIOP-Agent] 🔄 Local Routing Hack → Forced 127.0.0.1: ${normalized}`,\n\t\t\t);\n\t\t}\n\t\treturn normalized;\n\t}\n\n\treturn trimmed;\n}\n\n/**\n * industrialAddressMapper\n *\n * Maps Docker-internal IPs to host-published ports for local demo environments.\n * Activated when any of the following conditions are met:\n * - NODE_ENV is \"development\" or \"test\"\n * - LIOP_DOCKER_MAP=\"true\" or LIOP_DEV_MODE=\"true\" is set\n * - LIOP_NEXUS_URL points to a local Docker demo port (127.0.0.1:13000|13001)\n *\n * Nexus (172.20.0.10) -> 13001\n * Vault (172.20.0.11) -> 13003\n * Bank (172.20.0.12) -> 13004\n * Oracle(172.20.0.13) -> 13005\n */\nfunction industrialAddressMapper(addr: string): string | null {\n\tif (addr.includes(\"/ip4/172.20.0.10\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.10\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13001\",\n\t\t);\n\tif (addr.includes(\"/ip4/172.20.0.11\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.11\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13003\",\n\t\t);\n\tif (addr.includes(\"/ip4/172.20.0.12\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.12\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13004\",\n\t\t);\n\tif (addr.includes(\"/ip4/172.20.0.13\"))\n\t\treturn addr.replace(\n\t\t\t/\\/ip4\\/172\\.20\\.0\\.13\\/tcp\\/[0-9]+/,\n\t\t\t\"/ip4/127.0.0.1/tcp/13005\",\n\t\t);\n\n\t// Drop container-internal loopbacks to prevent the Host Agent from dialing itself or conflicting ports\n\tif (\n\t\taddr.includes(\"/ip4/127.0.0.1/tcp/4000\") ||\n\t\taddr.includes(\"/ip4/127.0.0.1/tcp/3000\")\n\t) {\n\t\treturn null;\n\t}\n\n\treturn addr;\n}\n\n/**\n * Checks if a URL points to the local Docker demo environment\n * (loopback address on known demo ports).\n */\nfunction isDockerDemoHost(urlStr: string): boolean {\n\ttry {\n\t\tconst u = new URL(urlStr);\n\t\treturn (\n\t\t\t(u.hostname === \"127.0.0.1\" || u.hostname === \"localhost\") &&\n\t\t\t(u.port === \"13000\" || u.port === \"13001\")\n\t\t);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Determines whether Docker address mapping should be enabled.\n * True when running in development/test mode, when explicitly requested\n * via LIOP_DOCKER_MAP/LIOP_DEV_MODE, or when the Nexus URL points to\n * a local Docker demo port.\n */\nfunction shouldEnableDockerMap(): boolean {\n\treturn (\n\t\tprocess.env.NODE_ENV === \"development\" ||\n\t\tprocess.env.NODE_ENV === \"test\" ||\n\t\tprocess.env.LIOP_DOCKER_MAP === \"true\" ||\n\t\tprocess.env.LIOP_DEV_MODE === \"true\" ||\n\t\t(!!process.env.LIOP_NEXUS_URL &&\n\t\t\tisDockerDemoHost(process.env.LIOP_NEXUS_URL))\n\t);\n}\n\n/**\n * LIOP Agent (Zero-Config CLI)\n *\n * Secure Logic-on-Origin gateway for Claude Desktop.\n * Communicates via STDIO / JSON-RPC.\n *\n * All tool discovery is DYNAMIC via the /liop/manifest/1.0.0 protocol.\n * No hardcoded tools, PeerIDs, or port mappings.\n */\nasync function main() {\n\t// Auto-Relaunch: Ensure system CA certificates are loaded for TLS compatibility.\n\t// Corporate proxies (Cloudflare WARP, Zscaler) inject custom root CAs into the\n\t// OS certificate store. Node.js ignores these by default, causing UNABLE_TO_VERIFY_LEAF_SIGNATURE.\n\t// Pattern: if --use-system-ca is not active, re-spawn with the flag transparently.\n\t// stdio: \"inherit\" ensures Claude Desktop's JSON-RPC pipe is passed through cleanly.\n\tif (\n\t\t(process.platform === \"win32\" || process.platform === \"darwin\") &&\n\t\t!process.execArgv.includes(\"--use-system-ca\") &&\n\t\t!(process.env.NODE_OPTIONS ?? \"\").includes(\"--use-system-ca\")\n\t) {\n\t\tconst { spawn } = await import(\"node:child_process\");\n\t\tconst child = spawn(\n\t\t\tprocess.execPath,\n\t\t\t[\"--use-system-ca\", ...process.argv.slice(1)],\n\t\t\t{ stdio: \"inherit\", env: process.env },\n\t\t);\n\t\tchild.on(\"exit\", (code) => process.exit(code ?? 1));\n\t\tchild.on(\"error\", () => process.exit(1));\n\t\t// Block parent — child handles all I/O from here\n\t\tawait new Promise(() => {});\n\t\treturn;\n\t}\n\n\tconst buildTime = new Date().toISOString();\n\tlog.info(`[LIOP-Agent] 🚀 Version 1.2.0-alpha.9 | Build: ${buildTime}`);\n\n\tconst liopDir = path.join(os.homedir(), \".liop\");\n\tconst identityPath = path.join(liopDir, \"identity.json\");\n\n\tif (!fs.existsSync(liopDir)) {\n\t\tfs.mkdirSync(liopDir, { recursive: true });\n\t}\n\n\t// 1. Determine Bootstrap Nodes (Zero-Config Discovery)\n\tlet bootstrapNodes: string[] = [];\n\n\t// Command line arguments take precedence\n\tconst args = process.argv.slice(2);\n\tif (args.length > 0) {\n\t\tbootstrapNodes = args.filter((a) => a.startsWith(\"/\"));\n\t}\n\n\t// Priority 1: Physical Beacons (Industrial Pattern) - DETERMINISTIC & INSTANT\n\tif (bootstrapNodes.length === 0) {\n\t\tconst searchDirs = [];\n\n\t\t// Priority 1.1: Explicit file from environment variable\n\t\tif (process.env.LIOP_BOOTSTRAP_FILE) {\n\t\t\tlog.warn(\n\t\t\t\t\"LIOP_BOOTSTRAP_FILE is deprecated and will be removed in the next major version. \" +\n\t\t\t\t\t\"Use LIOP_NEXUS_URL for Auto-Discovery instead.\",\n\t\t\t);\n\t\t\tconst filePath = path.resolve(process.env.LIOP_BOOTSTRAP_FILE);\n\t\t\tif (fs.existsSync(filePath)) {\n\t\t\t\tconst addr = fs.readFileSync(filePath, \"utf8\").trim();\n\t\t\t\tif (addr) bootstrapNodes.push(normalizeBootstrap(addr));\n\t\t\t}\n\t\t}\n\n\t\t// Priority 1.2: Traditional locations (Scan for all *.multiaddr)\n\t\tsearchDirs.push(\n\t\t\tprocess.cwd(),\n\t\t\tpath.join(process.cwd(), \"tests/infra/nexus-data\"),\n\t\t\tliopDir,\n\t\t\tpath.join(\n\t\t\t\tpath\n\t\t\t\t\t.dirname(new URL(import.meta.url).pathname)\n\t\t\t\t\t.replace(/^\\/([A-Z]:)/, \"$1\"),\n\t\t\t\t\"../../tests/infra/nexus-data\",\n\t\t\t),\n\t\t);\n\n\t\tfor (const dir of searchDirs) {\n\t\t\ttry {\n\t\t\t\tif (fs.existsSync(dir)) {\n\t\t\t\t\tconst files = fs.readdirSync(dir);\n\t\t\t\t\tconst multiaddrFiles = files.filter((f) => f.endsWith(\".multiaddr\"));\n\n\t\t\t\t\tfor (const file of multiaddrFiles) {\n\t\t\t\t\t\tconst filePath = path.join(dir, file);\n\t\t\t\t\t\tconst addr = fs.readFileSync(filePath, \"utf8\").trim();\n\t\t\t\t\t\tif (addr) {\n\t\t\t\t\t\t\tconst normalized = normalizeBootstrap(addr);\n\t\t\t\t\t\t\tif (!bootstrapNodes.includes(normalized)) {\n\t\t\t\t\t\t\t\tbootstrapNodes.push(normalized);\n\t\t\t\t\t\t\t\tlog.info(`[LIOP-Agent] ✅ Loaded beacon: ${file} from ${dir}`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// If we found any beacons in this directory, we consider discovery successful for this layer\n\t\t\t\t\tif (bootstrapNodes.length > 0) break;\n\t\t\t\t}\n\t\t\t} catch (_e) {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t}\n\t}\n\n\t// Priority 2: Auto-Discovery via NEXUS URL (Aggressive Parallel Discovery)\n\tif (process.env.LIOP_NEXUS_URL) {\n\t\tconst nexusUrl = process.env.LIOP_NEXUS_URL;\n\t\tlog.info(\n\t\t\t`[LIOP-Agent] 🌐 Running parallel discovery from: ${nexusUrl} (Sources Found: ${bootstrapNodes.length})`,\n\t\t);\n\n\t\tconst resolved = await resolveBootstrapFromUrl(nexusUrl);\n\t\tif (resolved) {\n\t\t\tconst normalized = normalizeBootstrap(resolved);\n\t\t\tif (!bootstrapNodes.includes(normalized)) {\n\t\t\t\tbootstrapNodes.push(normalized);\n\t\t\t\tlog.info(\n\t\t\t\t\t`[LIOP-Agent] ✅ Added bootstrap from URL discovery: ${normalized}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Priority 3: Environment variable (direct multiaddr)\n\tif (bootstrapNodes.length === 0 && process.env.LIOP_BOOTSTRAP) {\n\t\tbootstrapNodes.push(process.env.LIOP_BOOTSTRAP.trim());\n\t}\n\n\t// Final fallback: local Nexus bootstrap for demo environments.\n\t// Avoid injecting stale static peer IDs when discovery already found valid peers.\n\tif (bootstrapNodes.length === 0) {\n\t\tbootstrapNodes.push(\n\t\t\t\"/ip4/127.0.0.1/tcp/13001/p2p/12D3KooWD8FUFdnLQzzLFNdicsaTknM5cpD7os9sK9NWVSVABJMD\",\n\t\t);\n\t}\n\n\t// Sanitize/validate all candidate multiaddrs so malformed PeerIDs don't crash startup.\n\tbootstrapNodes = bootstrapNodes.filter((addr) => {\n\t\ttry {\n\t\t\tmultiaddr(addr);\n\t\t\treturn true;\n\t\t} catch {\n\t\t\tlog.warn(`[LIOP-Agent] Ignoring invalid bootstrap multiaddr: ${addr}`);\n\t\t\treturn false;\n\t\t}\n\t});\n\n\t// If no bootstrap nodes found, the agent operates in standalone mode.\n\t// It will only serve local tools until peers are discovered.\n\tif (bootstrapNodes.length === 0) {\n\t\tlog.info(\n\t\t\t\"[LIOP-Agent] No bootstrap nodes configured. Operating in standalone mode.\",\n\t\t);\n\t\tlog.info(\n\t\t\t\"[LIOP-Agent] Pass a multiaddr as argument or create 'nexus.multiaddr' file.\",\n\t\t);\n\t}\n\n\t// Initialize local server node (lightweight, no tools registered locally)\n\tconst liopServer = new LiopServer({\n\t\tname: \"@nekzus/liop\",\n\t\tversion: \"1.0.0\",\n\t});\n\n\t// Enable Zero-Shot Autonomy (Industrial Prompt Injection)\n\tliopServer.enableZeroShotAutonomy();\n\n\t// 2. Mesh Node Configuration\n\tconst meshNode = new MeshNode({\n\t\tidentityPath: identityPath,\n\t\tbootstrapNodes: bootstrapNodes,\n\t\taddressMapper: shouldEnableDockerMap()\n\t\t\t? industrialAddressMapper\n\t\t\t: undefined,\n\t});\n\n\t// Start P2P Mesh\n\tawait meshNode.start();\n\n\t// 3. Initialize the Dynamic Router\n\t// No hardcoded tools — all discovery happens via liop:manifest protocol\n\tconst router = new LiopMcpRouter(liopServer, meshNode);\n\n\t// Proactive Notification to Claude Desktop when tools/resources are discovered dynamically\n\trouter.onToolsChanged = () => {\n\t\tprocess.stdout.write(\n\t\t\t`{\"jsonrpc\":\"2.0\",\"method\":\"notifications/tools/list_changed\"}\\n`,\n\t\t);\n\t\tprocess.stdout.write(\n\t\t\t`{\"jsonrpc\":\"2.0\",\"method\":\"notifications/resources/list_changed\"}\\n`,\n\t\t);\n\t};\n\n\t// Initial warming period (2s) then Adaptive Background Discovery\n\t// Polls DHT for new nodes and triggers onToolsChanged when topology shifts.\n\t// Uses exponential backoff to reduce polling load on stable meshes.\n\tsetTimeout(() => {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: access internal for telemetry\n\t\tconst rtSize = (meshNode as any).getRoutingTableSize?.() || 0;\n\t\tlog.info(`[LIOP-Agent] Warm-up complete. Routing Table size: ${rtSize}`);\n\t\trouter.refreshManifestCache(true).catch(() => {});\n\t}, 2000);\n\n\tconst POLL_BASE_MS = 10_000;\n\tconst POLL_MAX_MS = 120_000;\n\tlet pollIntervalMs = POLL_BASE_MS;\n\n\tconst scheduleAdaptivePoll = () => {\n\t\tsetTimeout(async () => {\n\t\t\tconst prevSize = router.getCacheSize();\n\t\t\tawait router.refreshManifestCache(true).catch(() => {});\n\t\t\tconst newSize = router.getCacheSize();\n\n\t\t\tif (newSize !== prevSize) {\n\t\t\t\t// Topology changed — reset to aggressive polling\n\t\t\t\tpollIntervalMs = POLL_BASE_MS;\n\t\t\t\tlog.info(\n\t\t\t\t\t`[LIOP-Agent] Topology change detected (${prevSize} → ${newSize}). Resetting poll to ${POLL_BASE_MS / 1000}s.`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// Stable — relax polling interval (factor 1.5)\n\t\t\t\tpollIntervalMs = Math.min(\n\t\t\t\t\tMath.round(pollIntervalMs * 1.5),\n\t\t\t\t\tPOLL_MAX_MS,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tscheduleAdaptivePoll();\n\t\t}, pollIntervalMs);\n\t};\n\n\tscheduleAdaptivePoll();\n\n\t// 4. STDIO Transport — Buffered Line Reader\n\t// Uses readline to guarantee complete JSON-RPC messages before parsing.\n\t// Raw stdin.on(\"data\") can fragment large payloads across multiple chunks.\n\tconst readline = await import(\"node:readline\");\n\tconst rl = readline.createInterface({\n\t\tinput: process.stdin,\n\t\tterminal: false,\n\t});\n\n\tprocess.stdout.on(\"error\", (err: Error & { code?: string }) => {\n\t\tif (err.code === \"EPIPE\") {\n\t\t\tprocess.exit(0); // Graceful exit when Claude Desktop disconnects\n\t\t}\n\t});\n\n\trl.on(\"line\", async (line) => {\n\t\tconst trimmed = line.trim();\n\t\tif (!trimmed) return;\n\n\t\ttry {\n\t\t\tconst request = JSON.parse(trimmed) as McpRequest;\n\t\t\tif (request.method) {\n\t\t\t\tconst response = await router.dispatch(request);\n\t\t\t\tif (response) {\n\t\t\t\t\tprocess.stdout.write(`${JSON.stringify(response)}\\n`);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (_err) {\n\t\t\t// Silent catch for binary noise or malformed lines\n\t\t}\n\t});\n\n\trl.on(\"close\", () => {\n\t\tprocess.exit(0);\n\t});\n\n\t// Status directed only to stderr\n\tlog.info(`[LIOP-Agent] Guarding Claude Desktop via STDIO.`);\n\tlog.info(\n\t\t`[LIOP-Agent] P2P Mesh: Joined (${bootstrapNodes.length} bootstraps)`,\n\t);\n\tlog.info(\"[LIOP-Agent] Tool discovery: Dynamic via /liop/manifest/1.0.0\");\n\n\tprocess.on(\"SIGINT\", async () => {\n\t\tawait meshNode.stop();\n\t\tprocess.exit(0);\n\t});\n}\n\nmain().catch((err) => {\n\tlog.error(`[LIOP-Agent] Fatal Error: ${err.message}`);\n\tprocess.exit(1);\n});\n"]}
|
package/dist/bridge.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{b as LiopMcpBridge,a as LiopStreamBridge}from'./chunk-
|
|
1
|
+
export{b as LiopMcpBridge,a as LiopStreamBridge}from'./chunk-VDNV2I4I.js';import'./chunk-S6RJHZV2.js';//# sourceMappingURL=bridge.js.map
|
|
2
2
|
//# sourceMappingURL=bridge.js.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {b as b$1,a as a$3}from'./chunk-SB5XJXKV.js';import {a,b}from'./chunk-V5MKJT6S.js';import {a as a$2}from'./chunk-DQ6UW6L7.js';import {a as a$1}from'./chunk-S6RJHZV2.js';import {Buffer}from'buffer';import L from'crypto';import*as v from'fs';import {createRequire}from'module';import k from'path';import {fileURLToPath,pathToFileURL}from'url';import*as P from'@grpc/grpc-js';import {createMlKem768}from'mlkem';import {Piscina,FixedQueue}from'piscina';import {z as z$1}from'zod';import {zodToJsonSchema}from'zod-to-json-schema';import*as D from'jose';import oe from'oidc-provider';import*as q from'acorn';import {simple}from'acorn-walk';var ne={"grpc.keepalive_time_ms":3e4,"grpc.keepalive_timeout_ms":1e4,"grpc.keepalive_permit_without_calls":1,"grpc.max_send_message_length":-1,"grpc.max_receive_message_length":-1,"grpc.enable_retries":1},$=class{server;constructor(){this.server=new P.Server(ne);}addService(e){this.server.addService(a.LogicMesh.service,{NegotiateIntent:e.negotiateIntent,ExecuteLogic:e.executeLogic});}async listen(e=50051,r){let t=b(r);return new Promise((i,n)=>{this.server.bindAsync(`0.0.0.0:${e}`,t,(s,o)=>{if(s){n(s);return}a$1.info(`[LIOP-RPC] Server listening on port ${o}`),i(o);});})}async stop(){return new Promise(e=>{this.server.tryShutdown(()=>{a$1.info("[LIOP-RPC] Server shut down"),e();});})}};var N={audience:"urn:liop:mesh:api",tokenTtlSeconds:3600,jwksCacheTtlMs:6e5,jwksCooldownMs:3e4,clockToleranceSec:5,signingAlgorithm:"EdDSA"};var F=class{jwksResolver;issuer;audience;constructor(e,r,t){this.issuer=e,this.audience=r,t instanceof URL?this.jwksResolver=D.createRemoteJWKSet(t,{cacheMaxAge:N.jwksCacheTtlMs,cooldownDuration:N.jwksCooldownMs}):this.jwksResolver=D.createLocalJWKSet(t);}async validate(e){let r=this.buildIssuerAliases(),{payload:t}=await D.jwtVerify(e,this.jwksResolver,{issuer:r.length>1?r:this.issuer,audience:this.audience,algorithms:[N.signingAlgorithm,"ES256"],clockTolerance:N.clockToleranceSec,requiredClaims:["sub","scope"]});return {token:e,clientId:t.sub??"unknown",scopes:typeof t.scope=="string"?t.scope.split(" "):[],expiresAt:t.exp}}buildIssuerAliases(){let e=[this.issuer],r=this.issuer.endsWith("/")?this.issuer.slice(0,-1):this.issuer,t=["nexus:3000","liop-nexus:3000","127.0.0.1:3000","localhost:3000","127.0.0.1:13000","localhost:13000","127.0.0.1:13001","localhost:13001"],i="";try{let o=new URL(r);i=`${o.hostname}:${o.port||"3000"}`;}catch{return e}if(!t.some(o=>i===o))return e;let s=r.replace(/^https?:\/\/[^/]+/,"");for(let o of t){let a=`http://${o}${s}`;e.includes(a)||e.push(a);}if(s)for(let o of t){let a=`http://${o}`;e.includes(a)||e.push(a);}else for(let o of t){let a=`http://${o}/oidc`;e.includes(a)||e.push(a);}return e}getIssuer(){return this.issuer}getAudience(){return this.audience}};function ee(g){let{privateKey:e,publicKey:r}=L.generateKeyPairSync("ed25519"),t=e.export({format:"jwk"}),i=r.export({format:"jwk"}),n=L.createHash("sha256").update(i.x||"").digest("hex").slice(0,16),s={...t,kid:n,use:"sig",alg:"EdDSA"},o={...i,kid:n,use:"sig",alg:"EdDSA"},a={keys:[s]},c={keys:[o]},l={scopes:["openid","offline_access",...b$1],clients:g.clients.map(h=>({client_id:h.client_id,client_secret:h.client_secret,grant_types:["client_credentials"],response_types:[],redirect_uris:[],scope:h.scope,token_endpoint_auth_method:"client_secret_post",id_token_signed_response_alg:"EdDSA"})),features:{clientCredentials:{enabled:true},devInteractions:{enabled:false},resourceIndicators:{enabled:true,useGrantedResource:()=>true,getResourceServerInfo:(h,u,f)=>({scope:f.scope||"",accessTokenFormat:"jwt",jwt:{sign:{alg:"EdDSA"}}})}},formats:{AccessToken:"jwt"},interactions:{url:()=>{throw new Error("InteractionsNotSupportedException: This Authorization Server is strictly configured for Machine-to-Machine flows.")}},jwks:a,ttl:{ClientCredentials:3600},cookies:{keys:[L.randomBytes(32).toString("hex")]},extraTokenClaims:(h,u)=>u.kind==="AccessToken"?{scope:u.scope}:{}},m=g.issuer.endsWith("/")?g.issuer.slice(0,-1):g.issuer,p=new oe(m,l);return p.proxy=true,{provider:p,jwks:c}}var U=class g{piiFields;sensitiveKeys;static TAINT_PROPAGATING_METHODS=new Set(["charCodeAt","codePointAt","charAt","at","indexOf","lastIndexOf","search","localeCompare","startsWith","endsWith","includes","substring","slice","substr","split","match","matchAll","replace","replaceAll","normalize","toLowerCase","toUpperCase","trim","trimStart","trimEnd","padStart","padEnd","repeat"]);static ARRAY_CALLBACK_METHODS=new Set(["map","forEach","filter","find","some","every","flatMap","findIndex"]);static REDUCE_METHODS=new Set(["reduce","reduceRight"]);constructor(e,r=[]){this.piiFields=new Set(e.map(t=>t.toLowerCase())),this.sensitiveKeys=new Set(r.map(t=>t.toLowerCase()));}classifyField(e,r=[]){let t=e.toLowerCase();if(this.piiFields.has(t))return "forbidden";let i=new Set(r.map(n=>n.toLowerCase()));return this.sensitiveKeys.has(t)||i.has(t)?"sensitive":"public"}analyze(e,r,t=50){let i;try{let a=`function liop_analysis_wrapper(env) {
|
|
2
|
+
${e}
|
|
3
|
+
}`;i=q.parse(a,{ecmaVersion:2022,sourceType:"script",locations:!0});}catch{return null}let n=new Set,s=new Set;this.identifyRecordBoundVars(i,n),this.propagateTaint(i,n,s);let o=this.checkReturnStatements(i,n,s);if(o)return o;if(r!==void 0&&r>0&&r<t){let a=this.detectCorrelatedAggregations(i);if(a)return a.reason=a.reason.replace("50 records",`${t} records`),a}if(r!==void 0&&r>0&&r<t){let a=this.detectMinMaxExtraction(i);if(a)return a.reason=a.reason.replace("50 records",`${t} records`),a}return null}extractQueriedFields(e){let r;try{r=q.parse(`function w(env) {
|
|
4
|
+
${e}
|
|
5
|
+
}`,{ecmaVersion:2022,sourceType:"script"});}catch{return []}let t=new Set;this.identifyRecordBoundVars(r,t);let i=new Set;return simple(r,{MemberExpression:s=>{let o=this.getPropertyName(s);if(!(!o||o==="length")&&(s.object.type==="Identifier"&&t.has(s.object.name)&&i.add(o),s.object.type==="MemberExpression")){let a=s.object;a.computed&&this.isEnvRecordsAccess(a.object)&&i.add(o);}}}),Array.from(i)}detectCorrelatedAggregations(e){let r=new Map;simple(e,{CallExpression:i=>{if(i.callee.type!=="MemberExpression")return;let n=i.callee,s=this.getPropertyName(n);if(!s||!g.REDUCE_METHODS.has(s)||!this.isEnvRecordsChain(n.object))return;let o=i.arguments[0];if(!o||o.type!=="ArrowFunctionExpression"&&o.type!=="FunctionExpression")return;let a=o,c=a.params.length>1?a.params[1]:a.params[0];if(!c||c.type!=="Identifier")return;let l=c.name,m=this.extractFieldsFromBody(a.body,l);for(let p of m){let h=r.get(p)??0;r.set(p,h+1);}}});for(let[i,n]of r)if(n>=2)return {reason:`Correlation guard: ${n} aggregations detected on field '${i}'. Multiple correlated aggregations on the same field can enable differencing attacks. Use a single aggregation per numeric field, or increase dataset size above 50 records.`};return null}isEnvRecordsChain(e){if(this.isEnvRecordsAccess(e))return true;if(e.type==="CallExpression"){let r=e;if(r.callee.type==="MemberExpression"){let t=r.callee,i=this.getPropertyName(t);if(i&&(i==="slice"||i==="filter"||i==="toSorted"))return this.isEnvRecordsChain(t.object)}}return false}extractFieldsFromBody(e,r){let t=[];return simple(e,{MemberExpression:n=>{if(n.object.type==="Identifier"&&n.object.name===r){let s=this.getPropertyName(n);s&&s!=="length"&&t.push(s);}}}),t}detectMinMaxExtraction(e){let r=null;return simple(e,{CallExpression:i=>{if(!r&&i.callee.type==="MemberExpression"){let n=i.callee;if(n.object.type==="Identifier"&&n.object.name==="Math"){let s=this.getPropertyName(n);(s==="min"||s==="max")&&i.arguments.some(o=>o.type==="SpreadElement"&&this.isRecordsMapCall(o.argument))&&(r={reason:`Min/Max gate: Math.${s}() on individual records blocked for small datasets (n < 50). Use avg/stddev/count for privacy-safe aggregations.`});}}},MemberExpression:i=>{if(!r&&i.computed&&i.object.type==="CallExpression"){let n=i.object;if(n.callee.type==="MemberExpression"){let s=this.getPropertyName(n.callee);if(s==="sort"||s==="toSorted"){let o=n.callee.object;this.isEnvRecordsChain(o)&&(r={reason:"Min/Max gate: .sort()[index] on individual records blocked for small datasets (n < 50). Use avg/stddev/count for privacy-safe aggregations."});}}}}}),r}isRecordsMapCall(e){if(e.type!=="CallExpression")return false;let r=e;if(r.callee.type!=="MemberExpression")return false;let t=r.callee;return this.getPropertyName(t)==="map"&&this.isEnvRecordsChain(t.object)}identifyRecordBoundVars(e,r){simple(e,{CallExpression:n=>{if(n.callee.type!=="MemberExpression")return;let s=n.callee,o=this.getPropertyName(s);if(!o||!this.isEnvRecordsAccess(s.object))return;let a=n.arguments[0];if(a&&(a.type==="ArrowFunctionExpression"||a.type==="FunctionExpression")){let c=a;if(g.ARRAY_CALLBACK_METHODS.has(o)&&c.params.length>0){let l=c.params[0];l.type==="Identifier"&&r.add(l.name);}if(g.REDUCE_METHODS.has(o)&&c.params.length>1){let l=c.params[1];l.type==="Identifier"&&r.add(l.name);}}},ForOfStatement:n=>{if(this.isEnvRecordsAccess(n.right)&&n.left.type==="VariableDeclaration")for(let s of n.left.declarations)s.id.type==="Identifier"&&r.add(s.id.name);}}),simple(e,{VariableDeclarator:n=>{if(!(!n.init||n.id.type!=="Identifier")&&n.init.type==="MemberExpression"&&n.init.computed){let s=n.init;this.isEnvRecordsAccess(s.object)&&r.add(n.id.name);}}});}propagateTaint(e,r,t){for(let i=0;i<3;i++){let n=t.size;if(simple(e,{VariableDeclarator:o=>{!o.init||o.id.type!=="Identifier"||this.isExpressionTainted(o.init,r,t)&&t.add(o.id.name);},AssignmentExpression:o=>{o.left.type==="Identifier"&&this.isExpressionTainted(o.right,r,t)&&t.add(o.left.name);},FunctionDeclaration:o=>{o.id&&o.id.type==="Identifier"&&this.doesCallbackProduceTaint(o,null,r,t)&&t.add(o.id.name);},CallExpression:o=>{if(o.callee.type!=="MemberExpression")return;let a=o.callee;this.getPropertyName(a)==="push"&&a.object.type==="Identifier"&&o.arguments.some(l=>this.isExpressionTainted(l,r,t))&&t.add(a.object.name);}}),t.size===n)break}}checkReturnStatements(e,r,t){let i=null;return simple(e,{ReturnStatement:s=>{if(!i&&s.argument&&this.isExpressionTainted(s.argument,r,t)){let o=s.loc?.start.line?s.loc.start.line-1:void 0,a=this.describeTaintSource(s.argument,r,t);i={reason:`PII side-channel detected: output contains values derived from restricted fields. ${a?`Operation: ${a}. `:""}Use only non-PII fields (e.g., numeric/date columns) for aggregations.`,line:o,operation:a};}}}),i}isExpressionTainted(e,r,t){switch(e.type){case "Identifier":return t.has(e.name);case "MemberExpression":return this.isMemberExprTainted(e,r,t);case "CallExpression":return this.isCallExprTainted(e,r,t);case "YieldExpression":{let i=e;return i.argument?this.isExpressionTainted(i.argument,r,t):false}case "FunctionExpression":case "ArrowFunctionExpression":{let i=e;return this.doesCallbackProduceTaint(i,null,r,t)}case "BinaryExpression":case "LogicalExpression":{let i=e;return this.isExpressionTainted(i.left,r,t)||this.isExpressionTainted(i.right,r,t)}case "UnaryExpression":{let i=e;return this.isExpressionTainted(i.argument,r,t)}case "ConditionalExpression":{let i=e;return this.isExpressionTainted(i.test,r,t)||this.isExpressionTainted(i.consequent,r,t)||this.isExpressionTainted(i.alternate,r,t)}case "ObjectExpression":return e.properties.some(n=>n.type==="Property"&&this.isExpressionTainted(n.value,r,t));case "ArrayExpression":return e.elements.some(n=>n!==null&&this.isExpressionTainted(n,r,t));case "TemplateLiteral":return e.expressions.some(n=>this.isExpressionTainted(n,r,t));case "SpreadElement":{let i=e;return this.isExpressionTainted(i.argument,r,t)}default:return false}}isMemberExprTainted(e,r,t){let i=this.getPropertyName(e);if(e.object.type==="Identifier"&&r.has(e.object.name)&&i&&this.piiFields.has(i.toLowerCase()))return true;if(e.object.type==="MemberExpression"&&i&&this.piiFields.has(i.toLowerCase())){let n=e.object;if(n.computed&&this.isEnvRecordsAccess(n.object))return true}if(this.isExpressionTainted(e.object,r,t))return true;if(e.computed&&e.object.type==="Identifier"&&r.has(e.object.name)&&e.property.type==="Literal"){let n=e.property.value;if(typeof n=="string"&&this.piiFields.has(n.toLowerCase()))return true}return false}isCallExprTainted(e,r,t){if(e.callee.type==="MemberExpression"){let i=e.callee,n=this.getPropertyName(i);if(n&&g.TAINT_PROPAGATING_METHODS.has(n)&&this.isExpressionTainted(i.object,r,t))return true;if(this.isEnvRecordsAccess(i.object)&&e.arguments[0]){let s=e.arguments[0];if(s.type==="ArrowFunctionExpression"||s.type==="FunctionExpression")return this.doesCallbackProduceTaint(s,n,r,t)}if(this.isExpressionTainted(i.object,r,t)||e.arguments.some(s=>this.isExpressionTainted(s,r,t)))return true}if(e.callee.type==="MemberExpression"){let i=e.callee;this.getPropertyName(i)==="push"&&i.object.type==="Identifier"&&e.arguments.some(s=>this.isExpressionTainted(s,r,t))&&t.add(i.object.name);}if(e.callee.type==="Identifier"){let i=e.callee.name;if(t.has(i))return true;if(!new Set(["Math","Number","parseInt","parseFloat","isNaN","isFinite"]).has(i))return e.arguments.some(s=>this.isExpressionTainted(s,r,t))}return false}doesCallbackProduceTaint(e,r,t,i){let n=new Set(t),s=new Set(i);if(e.params.length>0){let l=r!==null&&g.REDUCE_METHODS.has(r)?1:0;e.params.length>l&&e.params[l].type==="Identifier"&&n.add(e.params[l].name);}if(e.type==="ArrowFunctionExpression"&&e.body.type!=="BlockStatement")return this.isExpressionTainted(e.body,n,s);let o=false,a={ReturnStatement:c=>{c.argument&&this.isExpressionTainted(c.argument,n,s)&&(o=true);},YieldExpression:c=>{let l=c;l.argument&&this.isExpressionTainted(l.argument,n,s)&&(o=true);}};return simple(e.body,a),o}getPropertyName(e){if(!e.computed&&e.property.type==="Identifier")return e.property.name;if(e.computed&&e.property.type==="Literal"){let r=e.property.value;if(typeof r=="string")return r}return null}isEnvRecordsAccess(e){if(e.type==="MemberExpression"){let r=e;if(this.getPropertyName(r)==="records"&&r.object.type==="Identifier"&&r.object.name==="env")return true}return e.type==="Identifier"&&e.name==="records"}describeTaintSource(e,r,t){if(e.type==="Identifier"){let i=e.name;if(t.has(i))return `variable '${i}' is PII-derived`}if(e.type==="ObjectExpression"){let i=e;for(let n of i.properties)if(n.type==="Property"&&this.isExpressionTainted(n.value,r,t))return `property '${n.key.type==="Identifier"?n.key.name:"unknown"}' contains PII-derived value`}if(e.type==="CallExpression"){let i=e;if(i.callee.type==="MemberExpression"){let n=this.getPropertyName(i.callee);if(n)return `result of .${n}() on PII data`}}}};var ae={aspirin:"Medication",lisinopril:"Medication",metformin:"Medication",amlodipine:"Medication",atorvastatin:"Medication",omeprazole:"Medication",losartan:"Medication",simvastatin:"Medication",levothyroxine:"Medication",ibuprofen:"Medication",acetaminophen:"Medication",amoxicillin:"Medication",ciprofloxacin:"Medication",prednisone:"Medication",warfarin:"Medication",insulin:"Medication",hydrochlorothiazide:"Medication",gabapentin:"Medication",albuterol:"Medication",pantoprazole:"Medication",hypertension:"Condition",diabetes:"Condition",bronchitis:"Condition",pneumonia:"Condition",asthma:"Condition"},z=4,ce=/^[\d\s.,:;!?()[\]{}<>@#$%^&*+=|\\/"'`~_-]+$/,W=class g{static nlp=null;async getNlp(){if(!g.nlp){let e=await import('compromise/three');g.nlp=e.default||e,g.nlp.addWords(ae);}return g.nlp}async scan(e){if(e.length<z||ce.test(e))return {detected:false,entities:[]};let t=(await this.getNlp())(e),i=[],n=t.people().out("array");for(let a of n){let c=a.trim();c.length>=z&&i.push({type:"person",text:c});}let s=t.places().out("array");for(let a of s){let c=a.trim();c.length>=z&&i.push({type:"place",text:c});}let o=t.organizations().out("array");for(let a of o){let c=a.trim();c.length>=z&&i.push({type:"organization",text:c});}return {detected:i.length>0,entities:i}}async scanDeep(e,r=new WeakSet){if(e==null)return {detected:false,entities:[]};if(typeof e=="string")return this.scan(e);if(typeof e=="object"){if(r.has(e))return {detected:false,entities:[]};r.add(e);let t=Array.isArray(e)?e:Object.values(e),i=[];for(let n of t){let s=await this.scanDeep(n,r);if(s.detected&&(i.push(...s.entities),s.entities.some(o=>o.type==="person")))return {detected:true,entities:i}}return {detected:i.length>0,entities:i}}return {detected:false,entities:[]}}};var le={maxDecimalPlaces:4,clampNonNegative:true};function H(g,e){let r={...le,...e},t=new WeakSet;function i(n){if(n==null)return n;if(typeof n=="number"){if(!Number.isFinite(n))return n;let s=n;r.clampNonNegative&&s<0&&(s=0);let o=10**r.maxDecimalPlaces;return s=Math.round(s*o)/o,s}if(typeof n=="string"||typeof n=="boolean")return n;if(typeof n=="object"){if(t.has(n))return n;if(t.add(n),Array.isArray(n))return n.map(o=>i(o));let s={};for(let[o,a]of Object.entries(n))s[o]=i(a);return s}return n}return i(g)}function ue(g){let e=g.replace(/\D/g,"");if(e.length<13||e.length>19)return false;let r=0,t=false;for(let i=e.length-1;i>=0;i--){let n=parseInt(e.charAt(i),10);t&&(n*=2,n>9&&(n-=9)),r+=n,t=!t;}return r%10===0}function de(g){let e=g.replace(/\s+/g,"").toUpperCase();if(!/^[A-Z]{2}[0-9]{2}[A-Z0-9]{1,30}$/.test(e))return false;let r=e.substring(4)+e.substring(0,4),t="";for(let i=0;i<r.length;i++){let n=r.charCodeAt(i);if(n>=65&&n<=90)t+=(n-55).toString();else if(n>=48&&n<=57)t+=r.charAt(i);else return false}try{return BigInt(t)%97n===1n}catch{return false}}var T={EMAIL:{name:"EMAIL",pattern:/\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\b/gi,validator:g=>!g.endsWith("@example.com")&&!g.endsWith("@test.com")},CREDIT_CARD:{name:"CREDIT_CARD",pattern:/\b(?:\d[ -]*?){13,16}\b/g,validator:ue},IP_ADDRESS:{name:"IP_ADDRESS",pattern:/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/g,validator:g=>["127.0.0.1","0.0.0.0","255.255.255.255"].includes(g)?false:g.split(".").map(Number).every(t=>t>=0&&t<=255)},PHONE:{name:"PHONE",pattern:/(?:(?:\+?\d{1,3}[-. ]?)?\(?\d{3}\)?[-. ]?\d{3}[-. ]?\d{4})\b/g,validator:g=>{let e=g.replace(/\D/g,"");return !(e.length<7||e.length>15||/^(\d)\1+$/.test(e)||e==="1234567890")}},SSN:{name:"SSN",pattern:/\b\d{3}[- ]?\d{2}[- ]?\d{4}\b/g,validator:g=>{let e=g.replace(/\D/g,"");if(e.length!==9)return false;let r=parseInt(e.substring(0,3),10);return !(r===0||r===666||r>=900||parseInt(e.substring(3,5),10)===0||parseInt(e.substring(5,9),10)===0||/^(\d)\1+$/.test(e)||e==="123456789")}},IBAN:{name:"IBAN",pattern:/\b[A-Z]{2}[0-9]{2}[A-Z0-9]{1,30}\b/gi,validator:de},PASSPORT_MRZ:{name:"PASSPORT_MRZ",pattern:/\bP[A-Z<][A-Z<]{3}[A-Z0-9<]{39}(?:\b|\s|$)/g}},te={GLOBAL_STRICT:[T.EMAIL,T.CREDIT_CARD,T.IP_ADDRESS,T.PHONE,T.PASSPORT_MRZ,T.IBAN],US_COMPLIANT:[T.EMAIL,T.CREDIT_CARD,T.IP_ADDRESS,T.PHONE,T.SSN,T.PASSPORT_MRZ],EU_GDPR:[T.EMAIL,T.CREDIT_CARD,T.IP_ADDRESS,T.PHONE,T.IBAN,T.PASSPORT_MRZ]},K=class g{patterns;forbiddenKeysSet;nerScanner;static KEY_SAFELIST=new Set(["grid","video","android","identity","provide","override","validate","hidden","widget","guidelines","beside","guideline","outside","inside","collide","decide","divide","aside","ride","side","wide","hide","tide","pride","bride","slide","guide","stride","oxide","dioxide","suicide","homicide","pesticide","valid","invalid","void","avoid","diagnosis","medication","namespace","namesake","rename","filename","hostname","typename","unnamed","renamed","phonetic","phoneme","microphone","headphone","telephone","saxophone","smartphone","streetview","addressable","addressing","cityscape","electricity","capacity","velocity","opacity","timestamp","timezone","image_id","computation_result","zk_receipt","testid","toolid","sessionid","peerid","nodeid","requestid","correlationid","traceid","spanid"]);shortTokenBoundaryPatterns;longForbiddenTokens;constructor(e=[],r=[],t){this.patterns=e,this.forbiddenKeysSet=new Set(r.map(i=>i.toLowerCase())),this.nerScanner=t??null,this.shortTokenBoundaryPatterns=new Map,this.longForbiddenTokens=[];for(let i of this.forbiddenKeysSet)i.length<4?this.shortTokenBoundaryPatterns.set(i,new RegExp((()=>{let n=i.split("").map(o=>`[${o.toLowerCase()}${o.toUpperCase()}]`).join(""),s=`[a-z]${i.charAt(0).toUpperCase()}${i.slice(1)}`;return `(?:^|[_-])${n}(?:$|[_-])|${s}(?:$|[A-Z_-])|^${n}$`})())):this.longForbiddenTokens.push(i);}async scan(e,r=new WeakSet){if(e==null)return null;if(typeof e=="string"){let t=e.trim();if(t.startsWith("{")&&t.endsWith("}")||t.startsWith("[")&&t.endsWith("]"))try{let n=JSON.parse(t),s=await this.scan(n,r);if(s)return s}catch{}let i=this.checkString(e);if(i)return i;if(this.nerScanner){let n=await this.nerScanner.scan(e);if(n.detected){let s=n.entities.find(o=>o.type==="person");if(s)return `PII Entity Detected: person name "${s.text}"`}}return null}if(typeof e=="object"){if(r.has(e))return null;if(r.add(e),Array.isArray(e))for(let t of e){let i=await this.scan(t,r);if(i)return i}else for(let[t,i]of Object.entries(e)){if(this.forbiddenKeysSet.has(t.toLowerCase()))return `Forbidden Key: ${t}`;let n=this.checkKeyFuzzy(t);if(n)return n;let s=await this.scan(i,r);if(s)return s}}return null}checkKeyFuzzy(e){let r=e.toLowerCase();if(g.KEY_SAFELIST.has(r))return null;for(let[t,i]of this.shortTokenBoundaryPatterns)if(i.test(e))return `Forbidden Key (fuzzy): ${e} matches boundary pattern "${t}"`;for(let t of this.longForbiddenTokens)if(r.includes(t))return `Forbidden Key (fuzzy): ${e} contains restricted token "${t}"`;return null}checkString(e){for(let r of this.patterns)if(typeof r=="string"){if(e.toLowerCase().includes(r.toLowerCase()))return r}else if(r instanceof RegExp){if(r.global&&(r.lastIndex=0),r.test(e))return r.source}else if(typeof r=="object"&&r!==null){let t=r;if(typeof t.pattern=="string"){if(e.toLowerCase().includes(t.pattern.toLowerCase())&&(!t.validator||t.validator(t.pattern)))return t.name}else if(t.pattern instanceof RegExp){t.pattern.global&&(t.pattern.lastIndex=0);let i=t.pattern.exec(e);for(;i!==null;){let n=i[0];if(!t.validator||t.validator(n))return t.name;if(!t.pattern.global)break;i=t.pattern.exec(e);}}}return null}};var re=k.dirname(fileURLToPath(import.meta.url)),ie=class g{constructor(e,r){this.serverInfo=e;this.config=r;let t=this.config?.security?.enableNerScanning?new W:null;this.piiScanner=new K(this.config?.security?.piiPatterns??te.GLOBAL_STRICT,this.config?.security?.forbiddenKeys??["id","name","fullName","firstName","lastName","address","street","city","postalCode","zipCode","phone","email","ssn","accountHolder","accountNumber","account_number","password","token","secret","privateKey"],t);let i=this.config?.security?.rateLimit;this.toolCallWindowMs=i?.windowMs??Number.parseInt(process.env.LIOP_RATE_LIMIT_WINDOW_MS??"60000",10),this.toolCallMaxPerWindow=i?.maxPerWindow??Number.parseInt(process.env.LIOP_RATE_LIMIT_MAX??"15",10),this.globalCallMaxPerWindow=i?.globalMaxPerWindow??Number.parseInt(process.env.LIOP_RATE_LIMIT_GLOBAL_MAX??"40",10);let n=this.config?.security?.forbiddenKeys??["id","name","fullName","firstName","lastName","address","street","city","postalCode","zipCode","phone","email","ssn","accountHolder","accountNumber","account_number","password","token","secret","privateKey"],s=this.config?.security?.sensitiveKeys??[];this.taintAnalyzer=new U(n,s);let o=import.meta.url.endsWith(".ts"),a=o?".ts":".js",c=[];if(o)try{let f=createRequire(import.meta.url).resolve("tsx/package.json");c=["--import",pathToFileURL(k.join(k.dirname(f),"dist","loader.mjs")).href];}catch{c=["--import","tsx"];}let l=process.env.NODE_ENV==="test"||process.env.VITEST;this.config?.capabilities&&!this.serverInfo.capabilities&&(this.serverInfo.capabilities=this.config.capabilities);let m=[k.resolve(re,`./workers/logic-execution${a}`),k.resolve(re,`../workers/logic-execution${a}`)],p=m.find(u=>v.existsSync(u))||m[1];this.workerPool=new Piscina({filename:p,minThreads:this.config?.workerPool?.minThreads??(l?0:2),maxThreads:this.config?.workerPool?.maxThreads??(l?1:8),idleTimeout:this.config?.workerPool?.idleTimeout??(l?500:5e3),maxQueue:this.config?.workerPool?.maxQueue??"auto",taskQueue:new FixedQueue,execArgv:c,resourceLimits:{maxOldGenerationSizeMb:this.config?.workerPool?.maxHeapMb??Number.parseInt(process.env.LIOP_WORKER_MAX_HEAP_MB??"64",10)}});let h=this.config?.workerPool?.minThreads??(l?0:2);if(this.workerPool&&h>0)for(let u=0;u<h;u++)this.workerPool.run({isWarmup:true}).catch(f=>{a$1.debug(`[LiopServer] Worker pool warm-up ping failed: ${f.message}`);});if(this.config?.auth?.role==="nexus"){let u=this.config.auth.issuer||"http://localhost:3000",f=this.config.auth.audience||N.audience,d=this.config.auth.clients||[{client_id:process.env.LIOP_OAUTH_CLIENT_ID||"liop-mesh-agent",client_secret:process.env.LIOP_OAUTH_CLIENT_SECRET||"dev-secret-change-me",grant_types:["client_credentials"],scope:"liop:tools:call liop:tools:list liop:resources:read liop:schema:read liop:mesh:query"}],{provider:b,jwks:S}=ee({issuer:u,clients:d});this.oauthProvider=b,this.jwtValidator=new F(u,f,S);}else if(this.config?.auth?.role==="node"){let u=this.config.auth.nexusUrl||process.env.LIOP_NEXUS_URL||"http://localhost:3000",f=this.config.auth.audience||N.audience,d=u.endsWith("/oidc")?u:`${u}/oidc`,b=new URL(`${d}/jwks`);this.jwtValidator=new F(u,f,b);}this.resource("LIOP Envelope Specification","liop://protocol/envelope-spec","Complete Logic-on-Origin envelope format, execution rules, and security constraints","text/plain",()=>Promise.resolve(this.buildEnvelopeSpec())),this.config?.auth?.revocationPath&&this.loadRevocationList();}logicCache=new Map;connectionStats=new Map;CACHE_TTL_MS=1440*60*1e3;THROTTLE_THRESHOLD=5;THROTTLE_COOLDOWN_MS=60*1e3;toolCallWindows=new Map;toolCallMaxPerWindow;toolCallWindowMs;globalCallWindow=[];globalCallMaxPerWindow;fieldQueryBudget=new Map;taintAnalyzer;tools=new Map;resources=new Map;prompts=new Map;activeSchema=null;sandboxRecords=[];piiScanner;workerPool;meshNode=null;rpcServer=null;boundPort=null;jwtValidator;oauthProvider;sessions=new Map;revokedTokenHashes=new Set;lastRevocationLoadTime=0;static LIOP_COMPACT_REGEX=/@LIOP\{(?<target>[^,}]+)(?:,(?<name>[^}]*))?\}\n(?<logic>[\s\S]*?)\n@END/m;extractLogic(e){let r=e.match(g.LIOP_COMPACT_REGEX);return r?.groups?.logic?r.groups.logic.trim():null}parseUnknownJson(e){if(typeof e!="string")return e;let r=e.trim();if(r.startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]"))try{return JSON.parse(r)}catch{return e}return e}runPreflightPolicy(e,r,t,i="local-client"){if(t){let a=r.replace(/\s+/g," ");if(t.enforceAggregationFirst&&[/return\s+env\.records(?!\s*\.\s*(?:reduce|length|filter|every|some|find)\b)/i,/return\s*\{[\s\S]*\b(accounts|patients|rows|records)\s*:\s*env\.records(?!\s*\.\s*(?:reduce|length|filter)\b)/i].some(l=>l.test(a)))return "Preflight policy rejected: potential row-level export pattern detected.";if(t.preflightDenyPatterns?.some(c=>c.test(a)))return "Preflight policy rejected: custom deny pattern matched."}let n=50;typeof t?.enforceAggregationFirst=="object"&&(n=t.enforceAggregationFirst.minMaxBlockThreshold??50);let s=this.taintAnalyzer.analyze(r,this.sandboxRecords.length,n);if(s)return `Preflight policy rejected: ${s.reason}`;let o=this.taintAnalyzer.extractQueriedFields(r);if(o.length>0){let a=t?.budgetStorePath||this.config?.budgetStorePath;if(a)try{let c=this.executeWithBudgetLock(a,l=>{let m=l[i]||{},p=m[e]||{};for(let d of o){let b=this.taintAnalyzer.classifyField(d,t?.sensitiveKeys),S=25,E="public";if(t?.queryBudgetPerField!==void 0?(S=t.queryBudgetPerField,E="override"):b==="forbidden"?(S=3,E="forbidden"):b==="sensitive"&&(S=8,E="sensitive"),(p[d]??0)>=S)return {result:`Preflight policy rejected: Query budget exceeded for field '${d}' (max ${S} per session for ${E} fields). Rotate PQC session to reset budget.`}}let h={...p};for(let d of o)h[d]=(h[d]??0)+1;let u={...m};u[e]=h;let f={...l};return f[i]=u,{result:null,updatedBudget:f}});if(c)return c}catch(c){let l=c instanceof Error?c.message:String(c);a$1.error(`[LIOP-Server] Error applying persistent query budget: ${l}. Falling back to in-memory.`);let m=this.applyInMemoryBudget(i,e,o,t);if(m)return m}else {let c=this.applyInMemoryBudget(i,e,o,t);if(c)return c}}return null}validateOutputPolicy(e,r,t){if(!t)return null;let i=this.parseUnknownJson(r);if(i&&typeof i=="object"&&i.isError===true)return null;if(t.outputSchema){let s=(()=>{if(!(t.outputSchema instanceof z$1.ZodObject))return t.outputSchema;let o=t.outputSchema;return o._def.catchall instanceof z$1.ZodNever?o.strict():o})().safeParse(i);if(!s.success)return `[LIOP] Output schema violation for ${e}: ${s.error.issues.map(o=>`${o.path.join(".")||"<root>"} ${o.message}`).join("; ")}. HINT: Your output must conform to the declared schema. Use 'env.records' to access the dataset and return only allowed fields.`}return t.enforceAggregationFirst&&this.violatesAggregationFirstPolicy(this.unwrapForAggregationPolicyScan(i),t.enforceAggregationFirst,this.sandboxRecords.length)?process.env.NODE_ENV==="development"||process.env.NODE_ENV==="test"||process.env.LIOP_SEC_VERBOSE==="1"?"Aggregation-First Policy Violation: row-level export or K-Anonymity violation blocked. HINT: Use .reduce() to produce a flat {key:value} object. Do NOT use .map() to create arrays of objects. Ensure dataset size > 10 for detailed results.":"Aggregation-First Policy Violation: Output blocked due to privacy constraints.":null}unwrapForAggregationPolicyScan(e){if(typeof e=="string"){let n=e.trim();if(n.startsWith("{")&&n.endsWith("}")||n.startsWith("[")&&n.endsWith("]"))try{return this.unwrapForAggregationPolicyScan(JSON.parse(n))}catch{return e}return e}if(!e||typeof e!="object")return e;let r=e;if(r.computation_result!==void 0)return this.unwrapForAggregationPolicyScan(r.computation_result);if(!Array.isArray(r.content)||r.content.length===0)return e;let t=[];for(let n of r.content)if(n&&typeof n=="object"&&"text"in n){let s=n.text;typeof s=="string"&&t.push(s);}if(t.length===0)return e;let i=t.length===1?t[0]:t.join(`
|
|
6
|
+
`);return this.unwrapForAggregationPolicyScan(i)}violatesAggregationFirstPolicy(e,r,t){if(!r)return false;let i=typeof r=="object"&&typeof r.maxOutputRows=="number"?r.maxOutputRows:10,n=typeof r=="object"&&typeof r.allowPrimitiveArrays=="boolean"?r.allowPrimitiveArrays:true;if(typeof e=="string"){let s=e.trim();if(s.startsWith("{")&&s.endsWith("}")||s.startsWith("[")&&s.endsWith("]"))try{return this.violatesAggregationFirstPolicy(JSON.parse(s),r,t)}catch{return false}return false}if(Array.isArray(e))return e.length>0&&e.every(s=>typeof s=="object"&&s!==null)?e.length>i?true:e.some(s=>this.violatesAggregationFirstPolicy(s,r,t)):e.length>0&&e.every(s=>typeof s!="object"||s===null)?!n:e.some(s=>this.violatesAggregationFirstPolicy(s,r,t));if(e&&typeof e=="object"){let s=Object.keys(e);return t!==void 0&&t>0&&t<10&&(s.length>3||Object.values(e).some(a=>Array.isArray(a)||typeof a=="object"&&a!==null))||s.length>i?true:Object.values(e).some(o=>this.violatesAggregationFirstPolicy(o,r,t))}return false}buildEnvelopeSpec(){let e=["LIOP v1 Envelope Specification","================================","","FORMAT:","","Compact Envelope:"," @LIOP{wasi_v1,TaskName}"," <JavaScript code>"," @END","","RUNTIME ENVIRONMENT:","- env.records: Array of data objects from the origin","- Must use 'return' to output results","- Zero-Trust WASI Sandbox (Node.js Worker Pool)","- Return aggregated objects, NOT raw row-level arrays","","SANDBOX RUNTIME RESTRICTIONS & WORKAROUNDS:","- Date is poisoned: The 'Date' class/constructor is undefined (Date.now(), Date.parse(), etc. will throw)."," Workaround: Use lexicographical string comparison on ISO 8601 date strings (e.g., record.date >= '2024-01-01').","- Poisoned globals: eval, Function, setTimeout, setInterval, Buffer, ArrayBuffer, and TypedArrays are undefined.","- Frozen prototypes: Any modifications to Object.prototype, Array.prototype, etc., are blocked.","","SECURITY CONSTRAINTS:","- PII Egress Shield blocks raw identifiers in output","- Aggregation-First policy: prefer counts, averages, summaries","- AST Guardian: static analysis before execution","","DIFFERENTIAL PRIVACY (DP) MECHANISM (Laplace Mechanism):","- Default field noise scale is derived from node global sensitivity.","- COUNT / LENGTH Optimization: To obtain EXACT counts without noise (sensitivity=1),"," the return keys MUST contain 'count', 'length', 'size', 'num', 'positive', 'negative',"," or start with 'total_' or 'num_' (e.g. 'total_tx', 'credits_count').","- AVERAGE Optimization: Keys containing 'avg', 'mean' or 'average' scale noise"," down automatically by dividing sensitivity by dataset size (sensitivity / n).","- SUM / OTHER queries: Receive full Laplace noise based on global node sensitivity"," (e.g., Sensitivity=100,000 in Bank to protect balances)."];return this.config?.security?.forbiddenKeys?.length&&e.push(`- Restricted fields: ${this.config.security.forbiddenKeys.join(", ")}`),e.push("","TAINT TRACKING (Phase 108):","- AST-level analysis blocks PII-derived scalars (charCodeAt, charAt, etc.)","- Operations on restricted fields are tracked through variable assignments","- Boolean inference (field.charCodeAt(0) < N ? 1 : 0) is blocked","- Allowed: aggregations on non-PII fields (balance, amount, date)","","K-ANONYMITY THRESHOLDS:","- Small Datasets (< 10 records): Maximum of 3 scalar output fields. Nesting or arrays in output are strictly forbidden.","- Large Datasets (>= 10 records): Maximum of 10 output fields.","","RATE LIMITS (OWASP A01):","- Per-tool: 15 calls/min (configurable via LIOP_RATE_LIMIT_MAX)","- Global: 40 calls/min across all tools (LIOP_RATE_LIMIT_GLOBAL_MAX)","","OPTIONAL PARAMETERS:","- __liop_bypass_ast_cache: boolean (force AST re-evaluation)","","AUTHENTICATION (tokenSlug Convention):","- Restricted nodes declare authRequired: true in their manifest.","- Token resolution: LIOP_TOKEN_<tokenSlug> (deterministic) > LIOP_TOKEN_<PeerID> > LIOP_TOKEN_<ProviderName>","- Format: tokenSlug must match SCREAMING_SNAKE_CASE /^[A-Z][A-Z0-9_]*$/ (e.g., BANK, VAULT, HFT_ORACLE)."),e.join(`
|
|
7
|
+
`)}extractSchemaFieldSummary(e,r=0){if(r>3)return "{...}";let t=e.type,i=e.properties,n=e.items;return i?`{${Object.entries(i).map(([o,a])=>{let c=a.type;if(c==="array"&&a.items){let l=this.extractSchemaFieldSummary(a.items,r+1);return `${o}(array of ${l})`}if(c==="object"&&a.properties){let l=this.extractSchemaFieldSummary(a,r+1);return `${o}(${l})`}return `${o}(${c||"unknown"})`}).join(", ")}}`:t==="array"&&n?`Array of ${this.extractSchemaFieldSummary(n,r+1)}`:t||Object.keys(e).join(", ")}async connect(e={}){return this.connectToMesh(e)}tool(e,r,t,i,n){if(this.tools.has(e))throw new Error(`Tool already registered: ${e}`);let s=z$1.object(t),o=zodToJsonSchema(s),a=r,c=i;if(t.payload&&t.payload instanceof z$1.ZodString){let m=this.config?.security?.forbiddenKeys||[];if(a+=`
|
|
8
|
+
|
|
9
|
+
Payload: LIOP v1 envelope (WASI sandbox). Format: @LIOP{wasi_v1,TaskName}\\n<JS code>\\n@END | Access data: env.records. Return aggregated object. Note: If dataset size < 10 (synthetic demo), Egress K-Anonymity blocks output if it has >3 keys or any array/nested object. | Full spec: resource liop://protocol/envelope-spec`,m.length>0&&(a+=`
|
|
10
|
+
Restricted fields: ${m.join(", ")}.`),this.activeSchema){let p=this.extractSchemaFieldSummary(this.activeSchema);a+=`
|
|
11
|
+
Data structure: ${p}. Full schema: resource liop://schema/global`;}c=async(p,h)=>{let u="global_connection",f=Date.now(),d=this.connectionStats.get(u)||{failures:0,lastAttempt:0};if(d.failures>=this.THROTTLE_THRESHOLD&&f-d.lastAttempt<this.THROTTLE_COOLDOWN_MS)return {content:[{type:"text",text:"LIOP_THROTTLED: Too many violations. Cooling down for 60 seconds."}],isError:true};let b=p.payload,S=p.__liop_bypass_ast_cache===true,E=L.createHash("sha256").update(b).digest("hex"),R=this.extractLogic(b),C=this.logicCache.get(E);if(!S&&C&&f-C.timestamp<this.CACHE_TTL_MS&&R){p.payload=R;let x=this.runPreflightPolicy(e,R,n,"mcp-client");return x?{content:[{type:"text",text:x}],isError:true}:await this.executeInWorkerPool(p,R,e)}if(!R)return d.failures++,d.lastAttempt=f,this.connectionStats.set(u,d),{content:[{type:"text",text:"Error: Malformed payload. Missing @LIOP boundary.\\nYou MUST wrap your logic exactly like this:\\n\\n@LIOP{wasi_v1,DynamicAudit}\\n// Your JS code here\\n@END"}],isError:true};try{let x=this.extractLogic(p.payload);p.payload=x;let A=this.runPreflightPolicy(e,x,n,"mcp-client");if(A)return d.failures++,d.lastAttempt=f,this.connectionStats.set(u,d),{content:[{type:"text",text:A}],isError:!0};let I=await this.executeInWorkerPool(p,x,e);return I.isError?(d.failures++,d.lastAttempt=f,this.connectionStats.set(u,d)):(this.connectionStats.set(u,{failures:0,lastAttempt:f}),this.logicCache.set(E,{hash:E,timestamp:f})),I}catch(x){let A=x;return d.failures++,d.lastAttempt=f,this.connectionStats.set(u,d),{content:[{type:"text",text:`ExecutionRuntimeException: ${A.message}`}],isError:true}}};}let l={type:"object",properties:o.properties||{},required:o.required};this.tools.set(e,{tool:{name:e,description:a,inputSchema:l},handler:c,schema:s,policy:n}),this.meshNode&&this.meshNode.announceCapability(e).catch(m=>{a$1.info(`[LIOP-Mesh] Failed to auto-announce tool ${e}: ${m.message}`);});}prompt(e,r,t,i){if(this.prompts.has(e))throw new Error(`Prompt already registered: ${e}`);this.prompts.set(e,{prompt:{name:e,description:r,arguments:t},handler:i});}enableZeroShotAutonomy(){this.prompt("liop_blind_analyst","The official Logic-Injection-on-Origin Protocol system prompt. Instructs the LLM on how to securely inject Logic-on-Origin without violating PII or safety constraints.",[],e=>({description:"LIOP Blind Analyst Instructions",messages:[{role:"user",content:{type:"text",text:`You are the "Blind Analyst" operating within the Logic-Injection-on-Origin Protocol (LIOP) ecosystem.
|
|
12
|
+
Your objective is to perform secure Logic-on-Origin injections. You must process remote data without ever requesting its extraction.
|
|
13
|
+
|
|
14
|
+
INDUSTRIAL CONSTRAINTS & PROTOCOL RULES:
|
|
15
|
+
1. DATA PRIVACY: NEVER attempt to export Personally Identifiable Information (PII). The LIOP Egress Shield will block any response containing raw IDs, names, or addresses.
|
|
16
|
+
2. AGGREGATION FIRST & K-ANONYMITY THRESHOLDS: Always prefer returning counts, averages, or anonymized summaries.
|
|
17
|
+
- Dataset < 10 records: Maximum of 3 scalar output fields. Nesting or arrays in output are strictly forbidden.
|
|
18
|
+
- Dataset >= 10 records: Maximum of 10 output fields.
|
|
19
|
+
3. LAPLACE DIFFERENTIAL PRIVACY (DP) COMPLIANCE:
|
|
20
|
+
- Legitimate COUNT queries: To obtain EXACT, un-noised counts, you MUST name your return keys containing 'count', 'length', 'size', 'num', 'positive', 'negative', or starting with 'total_' or 'num_' (e.g. 'total_tx', 'credits_count'). This forces sensitivity=1.0, rounds values, and clamps to non-negative values.
|
|
21
|
+
- Legitimate AVERAGE queries: Use 'avg_', '_average' or 'mean_' keys to automatically scale down Laplace noise by dividing sensitivity by the dataset size (sensitivity / n).
|
|
22
|
+
- Legitimate SUM queries: Return keys without count/average suffixes will receive full Laplacian noise scaled by the node's global sensitivity (which can be up to 100,000 in Bank nodes to protect raw balances). Do NOT attempt to bypass this by renaming sum fields to count fields, as it violates protocol integrity.
|
|
23
|
+
4. PAYLOAD ENCAPSULATION: Your JavaScript payloads MUST strictly adhere to the Compact Envelope. DO NOT include markdown backticks or leading text inside the 'payload' argument.
|
|
24
|
+
Structure:
|
|
25
|
+
@LIOP{wasi_v1,AnalysisTask}
|
|
26
|
+
// Your JS Code Here
|
|
27
|
+
@END
|
|
28
|
+
5. RUNTIME SCOPE: The execution environment provides a global 'env' object. Use 'env.records' to access the target dataset.
|
|
29
|
+
6. LOCALIZATION: Format all JSON response keys in the language used by the user in their query (e.g., use Spanish keys if the query is in Spanish).
|
|
30
|
+
7. SCHEMA RIGIDITY: Only use fields defined in the 'Data Dictionary'. Usage of non-existent fields will trigger a sandbox runtime exception.
|
|
31
|
+
8. SANDBOX RUNTIME: The 'Date' class/constructor is poisoned and set to undefined. Calling 'new Date()', 'Date.now()', or 'Date.parse()' will throw exceptions.
|
|
32
|
+
Workaround: Perform chronological operations and filtering using lexicographical string comparisons on ISO 8601 date strings (e.g., 'record.date >= "2024-01-01"').
|
|
33
|
+
Additionally, standard globals like 'eval', 'Function', 'setTimeout', 'setInterval', 'Buffer', ArrayBuffer, and TypedArrays are also undefined.${this.activeSchema?`
|
|
34
|
+
|
|
35
|
+
CURRENT DATA DICTIONARY (STRICT):
|
|
36
|
+
${JSON.stringify(this.activeSchema,null,2)}`:""}
|
|
37
|
+
|
|
38
|
+
Protocol Adherence is mandatory for successful execution.`}}]}));}resource(e,r,t,i,n){if(this.resources.has(r))throw new Error(`Resource URI already registered: ${r}`);this.resources.set(r,{name:e,uri:r,description:t,mimeType:i,content:n});}buildExecutionGuidelines(){return ["LIOP Sandbox Execution Guidelines","=================================","","1. DATE POISONING & FILTERING WORKAROUND:"," The global 'Date' class is set to undefined inside the sandbox. Calling 'new Date()', 'Date.now()', or 'Date.parse()' will throw a ReferenceError."," - Workaround: Perform chronological filtering using lexicographical string comparisons on ISO 8601 strings."," Example: const filtered = env.records.filter(r => r.date >= '2024-01-01' && r.date <= '2024-12-31');","","2. K-ANONYMITY CONSTRAINTS:"," - Datasets with LESS than 10 records: The returned object must contain at most 3 scalar fields, and must NOT contain any arrays or nested objects."," - Datasets with 10 or MORE records: The returned object can contain up to 10 fields.","","3. DIFFERENTIAL PRIVACY SUFFIXES:"," To avoid Laplacian noise adding random perturbations to your counts or averages, you must name your object keys using specific terms:"," - Counts (Exact, no noise): Key names must contain 'count', 'length', 'size', 'num', 'positive', 'negative', or start with 'total_' or 'num_'."," - Averages (Reduced noise): Key names must contain 'avg', 'mean', or 'average'."," - Sums/Other: Will receive full Laplace noise.","","4. GENERAL RESTRICTIONS:"," - Do not use 'eval', 'Function', 'setTimeout', 'setInterval', 'Buffer', 'ArrayBuffer', or TypedArrays."," - Do not attempt to modify prototypes (Object.prototype, Array.prototype)."].join(`
|
|
39
|
+
`)}dataDictionary(e,r="Global Medical Data Dictionary",t="liop://schema/global",i="Exposes the internal database schema for Zero-Shot Autonomy planning"){e.$comment="LIOP DIRECTIVES: 1. Date is undefined (Date.now(), new Date() throw). Workaround: use lexicographical string comparison on ISO 8601 string dates (e.g. record.date >= '2024-01-01'). 2. Small datasets (<10 records) limit outputs to max 3 scalar keys with NO nesting. 3. DP counts must contain count/length/size/num/total_ prefix/suffix.",this.activeSchema=e;let n=this.extractSchemaFieldSummary(e);for(let[s,o]of this.tools.entries())o.schema.shape.payload&&o.schema.shape.payload instanceof z$1.ZodString&&o.tool.description&&!o.tool.description.includes("Data structure:")&&(o.tool.description+=`
|
|
40
|
+
Data structure: ${n}. Full schema: resource ${t}. Guidelines: resource liop://schema/guidelines`,this.tools.set(s,o));this.resources.has("liop://schema/guidelines")||this.resource("LIOP Execution Guidelines","liop://schema/guidelines","Directives for generating compliant JavaScript code for the LIOP Sandbox runtime","text/plain",()=>Promise.resolve(this.buildExecutionGuidelines())),this.resource(r,t,i,"application/json",JSON.stringify(e,null,2));}clearAstCache(){this.logicCache.clear(),a$1.info("[LIOP-SDK] AST Security Cache cleared by Admin.");}checkToolCallRateLimit(e){let r=Date.now(),t=this.toolCallWindowMs,i=this.toolCallMaxPerWindow,s=(this.toolCallWindows.get(e)||[]).filter(o=>r-o<t);if(s.length>=i){let o=Math.ceil((s[0]+t-r)/1e3);return {content:[{type:"text",text:`LIOP_RATE_LIMITED: Too many calls to ${e}. Max ${i} per ${t/1e3}s window. Retry after ${o}s.`}],isError:true}}return s.push(r),this.toolCallWindows.set(e,s),null}checkGlobalRateLimit(){let e=Date.now(),r=this.toolCallWindowMs,t=this.globalCallMaxPerWindow;if(this.globalCallWindow=this.globalCallWindow.filter(i=>e-i<r),this.globalCallWindow.length>=t){let i=Math.ceil((this.globalCallWindow[0]+r-e)/1e3);return {content:[{type:"text",text:`LIOP_RATE_LIMITED: Global call limit exceeded. Max ${t} total calls per ${r/1e3}s window. Retry after ${i}s.`}],isError:true}}return this.globalCallWindow.push(e),null}async callTool(e,r="local-client"){let t=this.tools.get(e.name);if(!t)throw new Error(`Tool not found: ${e.name}`);let i=this.checkGlobalRateLimit();if(i)return i;let n=this.checkToolCallRateLimit(e.name);if(n)return n;try{let s=t.schema.parse(e.arguments||{});if(e.arguments?.__liop_bypass_ast_cache===!0&&(s.__liop_bypass_ast_cache=!0),s&&typeof s.payload=="string"){let a=s.payload,c=this.extractLogic(a);if(c){let l=this.runPreflightPolicy(e.name,c,t.policy,r);return l?{content:[{type:"text",text:l}],isError:!0}:(s.payload=c,await this.executeInWorkerPool(s,c,e.name))}}return await t.handler(s,{})}catch(s){let o=s;return o instanceof z$1.ZodError?{content:[{type:"text",text:`Validation Error: ${o.message}`}],isError:true}:{content:[{type:"text",text:`Internal Execution Error: ${o.message}`}],isError:true}}}listTools(){return Array.from(this.tools.values()).map(e=>e.tool)}listPrompts(){return Array.from(this.prompts.values()).map(e=>e.prompt)}async getPrompt(e){let r=this.prompts.get(e.name);if(!r)throw new Error(`Prompt not found: ${e.name}`);return await r.handler(e)}listResources(){return Array.from(this.resources.values())}async readResource(e){let r=this.resources.get(e);if(!r)throw new Error(`Resource not found: ${e}`);let t="No description provided";return typeof r.content=="function"?t=await r.content():typeof r.content=="string"?t=r.content:r.description&&(t=r.description),{contents:[{uri:r.uri,mimeType:r.mimeType||"text/plain",text:t}]}}getServerInfo(){return this.serverInfo}getMeshNode(){return this.meshNode}setSandboxData(e){this.sandboxRecords=e;}getBoundPort(){return this.boundPort}async connectToMesh(e={}){let r=process.env.LIOP_GRPC_PORT?Number.parseInt(process.env.LIOP_GRPC_PORT,10):void 0,t=e.port??r??50051,i=/^[A-Z][A-Z0-9_]*$/;if(this.config?.tokenSlug&&!i.test(this.config.tokenSlug))throw new Error(`Invalid tokenSlug "${this.config.tokenSlug}". Must match SCREAMING_SNAKE_CASE: /^[A-Z][A-Z0-9_]*$/ (e.g., "BANK", "VAULT", "HFT_ORACLE").`);this.meshNode=new a$2(e.meshConfig),await this.meshNode.start();let n=this.meshNode;this.meshNode.registerManifestHandler(()=>{let s=this.listTools().map(a=>({name:a.name,description:a.description,inputSchema:a.inputSchema})),o=Array.from(this.resources.values()).map(a=>({name:a.name,uri:a.uri,description:a.description,mimeType:a.mimeType,text:typeof a.content=="string"?a.content:a.description}));return {peerId:n.getPeerId(),grpcPort:t,tools:s,resources:o,serverInfo:this.serverInfo,authRequired:this.jwtValidator!==void 0,tokenSlug:this.config?.tokenSlug,taxonomy:this.config?.taxonomy?{domain:this.config.taxonomy.domain||"Unknown Domain",clearanceTier:this.config.taxonomy.clearanceTier??0,executionTypes:this.config.taxonomy.executionTypes||[]}:void 0}});for(let s of this.listTools())await this.meshNode.announceCapability(s.name).catch(a$1.info);await this.meshNode.announceManifest().catch(a$1.info),this.rpcServer=new $,this.rpcServer.addService({negotiateIntent:(s,o)=>{let a=s.request;if(a$1.info(`[LIOP-RPC] Negotiating intent for capability: ${a.capability_hash}`),this.jwtValidator){let c=s.metadata.get("authorization")[0];if(!c){o({code:P.status.UNAUTHENTICATED,details:"Missing Authorization header in gRPC metadata"});return}let l=c.startsWith("Bearer ")?c.slice(7):c,m=L.createHash("sha256").update(l).digest("hex").toLowerCase();if(this.loadRevocationList(),this.revokedTokenHashes.has(m)){o({code:P.status.UNAUTHENTICATED,details:"Token has been revoked by the resource owner"});return}let p=this.config?.auth?.localTestToken,h=/^[a-zA-Z0-9_-]+-local-test-token$/;if(p){if(l===p){a$1.info(`[LIOP-RPC] Bypass authentication for matching localTestToken: ${p}`),import('./kyber-2WDOTUQX.js').then(async({Kyber768Wrapper:u})=>{let{publicKey:f,secretKey:d}=await u.generateKeyPair(),b=L.randomUUID();this.sessions.set(b,{capability_hash:a.capability_hash,kyber_sk:d,agent_did:a.agent_did,tokenHash:m}),o(null,{accepted:true,session_token:b,error_message:"",kyber_public_key:f});});return}o({code:P.status.PERMISSION_DENIED,details:l&&h.test(l)?"Pre-shared local test token is invalid for this resource domain (segregation violation).":"Access Denied: This restricted node requires its specific static access token."});return}this.jwtValidator.validate(l).then(u=>{let f=a$3("tools/call",u);if(!f.allowed){o({code:P.status.PERMISSION_DENIED,details:f.reason||"Access Denied"});return}import('./kyber-2WDOTUQX.js').then(async({Kyber768Wrapper:d})=>{let{publicKey:b,secretKey:S}=await d.generateKeyPair(),E=L.randomUUID();this.sessions.set(E,{capability_hash:a.capability_hash,kyber_sk:S,agent_did:a.agent_did,tokenHash:m}),o(null,{accepted:true,session_token:E,error_message:"",kyber_public_key:b});});}).catch(u=>{o({code:P.status.UNAUTHENTICATED,details:`Invalid JWT token: ${u.message}`});});}else import('./kyber-2WDOTUQX.js').then(async({Kyber768Wrapper:c})=>{let{publicKey:l,secretKey:m}=await c.generateKeyPair(),p=L.randomUUID();this.sessions.set(p,{capability_hash:a.capability_hash,kyber_sk:m,agent_did:a.agent_did}),o(null,{accepted:true,session_token:p,error_message:"",kyber_public_key:l});});},executeLogic:async s=>{let o=s.request;a$1.info(`[LIOP-RPC] Executing Logic-on-Origin for session: ${o.session_token}`);let a=async()=>{let c=this.sessions.get(o.session_token);if(!c){s.emit("error",{code:P.status.UNAUTHENTICATED,details:"Invalid session token"});return}if(c.tokenHash&&(this.loadRevocationList(),this.revokedTokenHashes.has(c.tokenHash))){s.emit("error",{code:P.status.UNAUTHENTICATED,details:"Token has been revoked by the resource owner"});return}let l=c.capability_hash,p=(l?this.tools.get(l):void 0)?.policy;try{let u=(await createMlKem768()).decap(new Uint8Array(o.pqc_ciphertext),c.kyber_sk),f=Buffer.from(u),d=Buffer.from(o.wasm_binary),b=d.subarray(-16),S=d.subarray(0,-16),E=L.createDecipheriv("aes-256-gcm",f,Buffer.from(o.aes_nonce||new Uint8Array(12)));E.setAuthTag(b);let R=E.update(S);R=Buffer.concat([R,E.final()]);let C=R.toString("utf-8"),x=this.extractLogic(C)||C.trim(),A=this.runPreflightPolicy(l||"unknown_tool",x,p,c.agent_did||o.session_token);if(A){a$1.info(`[LIOP-RPC] Preflight blocked: ${A}`);let I={semantic_evidence:A,cryptographic_proof:Buffer.from(""),zk_receipt:Buffer.from(""),is_error:!0};s.write(I,()=>{s.end();});return}}catch(h){let u=h instanceof Error?h.message:String(h);a$1.error(`[LIOP-RPC] Preflight decryption failed: ${u}`),s.emit("error",{code:P.status.INTERNAL,details:`Preflight logic analysis failed: ${u}`});return}try{let h=p?{epsilon:p.dpEpsilon??1,sensitivity:p.dpSensitivity??1,smallDatasetThreshold:p.dpSmallDatasetThreshold??50}:void 0,u=await this.workerPool.run({ciphertext:o.pqc_ciphertext,secretKeyObj:Array.from(c.kyber_sk),wasmBinary:o.wasm_binary,inputs:o.inputs,aesNonce:o.aes_nonce,records:this.sandboxRecords,sessionToken:o.session_token,isEncrypted:!0,dpConfig:h}),f=H(u.output),d,b=f;try{d=typeof f=="string"?f:JSON.stringify(f);let x=JSON.parse(d);if(x.__liop_proxy_tool){a$1.info(`[LIOP-RPC] Executing Proxied Tool: ${x.__liop_proxy_tool}`);let A=c.agent_did||"unknown-client",I=await this.callTool({name:x.__liop_proxy_tool,arguments:x.__liop_proxy_args||{}},A);if(I.isError){a$1.info(`[LIOP-RPC] Proxy tool execution failed: ${I.content[0].text}`);let se={semantic_evidence:I.content[0].text||"Unknown error",cryptographic_proof:Buffer.from(""),zk_receipt:Buffer.from(""),is_error:!0};s.write(se,()=>{s.end();});return}let Z=H(I);d=JSON.stringify(Z),b=this.unwrapForAggregationPolicyScan(Z);}}catch{d=String(f);}let S=this.validateOutputPolicy(l||"unknown_tool",b,p);if(S){a$1.info(`[LIOP-RPC] Output policy blocked for ${l||"unknown_tool"}: ${S}`);let I={semantic_evidence:process.env.NODE_ENV==="development"||process.env.NODE_ENV==="test"||process.env.LIOP_SEC_VERBOSE==="1"?S:"[LIOP] Egress Security Violation. Output blocked due to policy enforcement.",cryptographic_proof:Buffer.from(""),zk_receipt:Buffer.from(""),is_error:!0};s.write(I,()=>{s.end();});return}let E={semantic_evidence:d,cryptographic_proof:Buffer.from(u.image_id||"","hex"),zk_receipt:u.zk_receipt?Buffer.from(u.zk_receipt,"base64"):Buffer.from(""),is_error:!1},R=await this.piiScanner.scan(b),C=this.violatesAggregationFirstPolicy(this.unwrapForAggregationPolicyScan(b),p?.enforceAggregationFirst,this.sandboxRecords?.length);if(R||C){let x=R||"Aggregation-First Policy Violation";a$1.info(`[LIOP-RPC] Secure egress blocked in gRPC stream: ${x}`),E.semantic_evidence="[LIOP] Egress Security Violation. Output blocked due to policy enforcement.",E.is_error=!0;}s.write(E,()=>{s.end();});}catch(h){let u=h,f=process.env.NODE_ENV==="development"||process.env.NODE_ENV==="test",d=u.message||String(h);a$1.error(`[LIOP-RPC] Execution Error: ${d}`);let S={semantic_evidence:f?`Execution Error: ${d}`:"[LIOP] Execution Failed. The injected logic violated runtime constraints or encountered a fatal error.",cryptographic_proof:Buffer.from(""),zk_receipt:Buffer.from(""),is_error:true};try{s.write(S,()=>{s.end();});}catch{s.end();}}};if(this.jwtValidator){let c=s.metadata.get("authorization")[0];if(!c){s.emit("error",{code:P.status.UNAUTHENTICATED,details:"Missing Authorization header in gRPC metadata"});return}let l=c.startsWith("Bearer ")?c.slice(7):c,m=L.createHash("sha256").update(l).digest("hex").toLowerCase();if(this.loadRevocationList(),this.revokedTokenHashes.has(m)){s.emit("error",{code:P.status.UNAUTHENTICATED,details:"Token has been revoked by the resource owner"});return}let p=this.config?.auth?.localTestToken,h=/^[a-zA-Z0-9_-]+-local-test-token$/;if(p){if(l===p){a$1.info(`[LIOP-RPC] Bypass authentication in executeLogic for matching localTestToken: ${p}`),await a();return}s.emit("error",{code:P.status.PERMISSION_DENIED,details:l&&h.test(l)?"Pre-shared local test token is invalid for this resource domain (segregation violation).":"Access Denied: This restricted node requires its specific static access token."});return}try{let u=await this.jwtValidator.validate(l),f=a$3("tools/call",u);if(!f.allowed){s.emit("error",{code:P.status.PERMISSION_DENIED,details:f.reason||"Access Denied"});return}await a();}catch(u){s.emit("error",{code:P.status.UNAUTHENTICATED,details:`Invalid JWT token: ${u instanceof Error?u.message:String(u)}`});}}else await a();}}),this.boundPort=await this.rpcServer.listen(t),a$1.info(`[LIOP-SDK] Node successfully announced to Mesh. PeerID: ${this.meshNode.getPeerId()}`);}async executeInWorkerPool(e,r,t){try{let i=t?this.tools.get(t)?.policy:void 0,n=i?{epsilon:i.dpEpsilon??1,sensitivity:i.dpSensitivity??1,smallDatasetThreshold:i.dpSmallDatasetThreshold??50}:void 0,s=await this.workerPool.run({ciphertext:new Uint8Array(0),secretKeyObj:Array.from(new Uint8Array(0)),kyberPublicKey:new Uint8Array(0),wasmBinary:Buffer.from(r),inputs:{},records:this.sandboxRecords,sessionToken:"local-dev-token",isEncrypted:!1,dpConfig:n}),o=s.output,a=H(o),l=[{type:"text",text:JSON.stringify({computation_result:a,image_id:s.image_id,zk_receipt:s.zk_receipt,status:"Worker Pool Execution Success"})}],m=t?this.tools.get(t)?.policy:void 0,p=this.validateOutputPolicy(t||"unknown_tool",a,m);if(p)return a$1.info(`[LIOP-SDK] Output policy blocked for ${t||"unknown_tool"}: ${p}`),{content:[{type:"text",text:process.env.NODE_ENV==="development"||process.env.NODE_ENV==="test"||process.env.LIOP_SEC_VERBOSE==="1"?p:"[LIOP] Egress Security Violation. Output blocked due to policy enforcement. Ensure your logic uses strictly aggregated, non-PII patterns."}],isError:!0};let h=await this.piiScanner.scan(a),u=this.violatesAggregationFirstPolicy(a,m?.enforceAggregationFirst,this.sandboxRecords?.length);if(h||u){let f=h||"Aggregation-First Policy Violation: Output blocked due to dynamic flat-key policy enforcement.";return a$1.info(`[LIOP-SDK] Secure egress blocked in local execution: ${f}`),{content:[{type:"text",text:process.env.NODE_ENV==="development"||process.env.NODE_ENV==="test"||process.env.LIOP_SEC_VERBOSE==="1"?`[LIOP] Egress Security Violation: ${f}`:"[LIOP] Egress Security Violation. Output blocked due to policy enforcement. Ensure your logic uses strictly aggregated, non-PII patterns."}],isError:!0}}return {content:l}}catch(i){let n=i,s=process.env.NODE_ENV==="development"||process.env.NODE_ENV==="test"||process.env.LIOP_SEC_VERBOSE==="1",o=n.message||String(i);return a$1.error(`[LIOP-SDK] WorkerPool Execution Fault: ${o}`),{content:[{type:"text",text:o.includes("worker_thread_exited")||o.includes("ERR_WORKER_OUT_OF_MEMORY")||o.includes("terminated")||o.includes("heap limit")?"[LIOP] Execution terminated: memory limit exceeded (64MB heap). Reduce data processing volume.":s?`WorkerPoolError: ${o}`:"[LIOP] Execution Failed. The injected logic violated runtime constraints or encountered a fatal error."}],isError:true}}}async close(){this.workerPool&&await this.workerPool.close({force:true}),this.rpcServer&&await this.rpcServer.stop(),this.meshNode&&await this.meshNode.stop();}loadRevocationList(){let e=this.config?.auth?.revocationPath;if(e)try{if(v.existsSync(e)){let r=v.statSync(e);if(r.mtimeMs<=this.lastRevocationLoadTime)return;let t=v.readFileSync(e,"utf-8"),i=JSON.parse(t);if(Array.isArray(i)){this.revokedTokenHashes.clear();for(let n of i)typeof n=="string"&&this.revokedTokenHashes.add(n.trim().toLowerCase());this.lastRevocationLoadTime=r.mtimeMs,a$1.info(`[LiopServer] Loaded ${this.revokedTokenHashes.size} revoked token hashes from ${e}`);}}else {let r=k.dirname(e);v.existsSync(r)||v.mkdirSync(r,{recursive:!0}),v.writeFileSync(e,JSON.stringify([],null,2),"utf-8"),this.lastRevocationLoadTime=Date.now(),a$1.info(`[LiopServer] Created empty local revocation list at ${e}`);}}catch(r){a$1.error(`[LiopServer] Failed to load revocation list: ${r instanceof Error?r.message:String(r)}`);}}revokeToken(e){if(!e)return;let r=L.createHash("sha256").update(e).digest("hex").toLowerCase();this.revokeTokenHash(r);}revokeTokenHash(e){if(!e)return;let r=e.toLowerCase();this.loadRevocationList(),this.revokedTokenHashes.add(r);let t=this.config?.auth?.revocationPath;if(t)try{let i=k.dirname(t);v.existsSync(i)||v.mkdirSync(i,{recursive:!0});let n=Array.from(this.revokedTokenHashes);v.writeFileSync(t,JSON.stringify(n,null,2),"utf-8");let s=v.statSync(t);this.lastRevocationLoadTime=s.mtimeMs,a$1.info(`[LiopServer] Persisted revocation for hash ${r} to ${t}`);}catch(i){a$1.error(`[LiopServer] Failed to persist revocation: ${i instanceof Error?i.message:String(i)}`);}}getPersistentBudget(e){try{if(!v.existsSync(e))return {};let r=v.readFileSync(e,"utf-8");return JSON.parse(r||"{}")}catch{return {}}}savePersistentBudget(e,r){let t=`${e}.tmp`,i=k.dirname(e);v.existsSync(i)||v.mkdirSync(i,{recursive:true}),v.writeFileSync(t,JSON.stringify(r,null,2),"utf-8"),v.renameSync(t,e);}executeWithBudgetLock(e,r){let t=`${e}.lock`,i=100,s=0,o=k.dirname(e);if(!v.existsSync(o))try{v.mkdirSync(o,{recursive:!0});}catch{}for(;s<i;)try{v.writeFileSync(t,process.pid.toString(),{flag:"wx"});break}catch(a){if(a&&typeof a=="object"&&"code"in a&&a.code==="EEXIST"){s++;}else throw a}if(s>=i)throw new Error("Timeout acquiring lock for persistent query budget database");try{let a=this.getPersistentBudget(e),{result:c,updatedBudget:l}=r(a);return l&&this.savePersistentBudget(e,l),c}finally{try{v.existsSync(t)&&v.unlinkSync(t);}catch{}}}applyInMemoryBudget(e,r,t,i){let n=this.fieldQueryBudget.get(e);n||(n=new Map,this.fieldQueryBudget.set(e,n));let s=n.get(r);s||(s=new Map,n.set(r,s));for(let o of t){let a=this.taintAnalyzer.classifyField(o,i?.sensitiveKeys),c=25,l="public";if(i?.queryBudgetPerField!==void 0?(c=i.queryBudgetPerField,l="override"):a==="forbidden"?(c=3,l="forbidden"):a==="sensitive"&&(c=8,l="sensitive"),(s.get(o)??0)>=c)return `Preflight policy rejected: Query budget exceeded for field '${o}' (max ${c} per session for ${l} fields). Rotate PQC session to reset budget.`}for(let o of t){let a=s.get(o)??0;s.set(o,a+1);}return null}};
|
|
41
|
+
export{$ as a,N as b,F as c,ee as d,W as e,H as f,T as g,te as h,K as i,ie as j};//# sourceMappingURL=chunk-AEWYQWVZ.js.map
|
|
42
|
+
//# sourceMappingURL=chunk-AEWYQWVZ.js.map
|