@nekzus/liop 2.0.0-alpha.2 → 2.0.0-alpha.20
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 +58 -24
- package/dist/bin/agent.js +3 -3
- package/dist/bin/agent.js.map +1 -1
- package/dist/bridge.js +1 -1
- package/dist/chunk-2MGFSIXN.js +2 -0
- package/dist/chunk-2MGFSIXN.js.map +1 -0
- package/dist/chunk-4C666HHU.js +2 -0
- package/dist/chunk-4C666HHU.js.map +1 -0
- package/dist/{chunk-PPCOS2NU.js → chunk-7I6YJS3C.js} +2 -2
- package/dist/{chunk-PPCOS2NU.js.map → chunk-7I6YJS3C.js.map} +1 -1
- package/dist/{chunk-HNDVAKEK.js → chunk-C65RM2A3.js} +6 -6
- package/dist/chunk-C65RM2A3.js.map +1 -0
- package/dist/{chunk-P52IE4L6.js → chunk-ISKM7EAL.js} +2 -2
- package/dist/{chunk-P52IE4L6.js.map → chunk-ISKM7EAL.js.map} +1 -1
- package/dist/{chunk-XLVRRGOX.js → chunk-NWZ5KZDN.js} +3 -3
- package/dist/chunk-NWZ5KZDN.js.map +1 -0
- package/dist/{chunk-PIBCW4BD.js → chunk-SYMZRXI3.js} +3 -3
- package/dist/{chunk-PIBCW4BD.js.map → chunk-SYMZRXI3.js.map} +1 -1
- package/dist/chunk-TNMS53OP.js +2 -0
- package/dist/chunk-TNMS53OP.js.map +1 -0
- package/dist/chunk-UK7OBXGZ.js +33 -0
- package/dist/chunk-UK7OBXGZ.js.map +1 -0
- package/dist/chunk-V5MKJT6S.js +2 -0
- package/dist/chunk-V5MKJT6S.js.map +1 -0
- package/dist/chunk-WG353XMU.js +43 -0
- package/dist/chunk-WG353XMU.js.map +1 -0
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/gateway.js +1 -1
- package/dist/{index-CyxNLlz7.d.ts → index-BihN3W-K.d.ts} +9 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/kyber-NONMBQNH.js +2 -0
- package/dist/{kyber-2WDOTUQX.js.map → kyber-NONMBQNH.js.map} +1 -1
- package/dist/mesh.js +1 -1
- package/dist/server.d.ts +18 -0
- package/dist/server.js +1 -1
- package/dist/types.js +1 -1
- package/dist/verifier-6M7GY4TW.js +2 -0
- package/dist/{verifier-RQRYXA4C.js.map → verifier-6M7GY4TW.js.map} +1 -1
- package/dist/workers/logic-execution.d.ts +5 -0
- 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 +54 -49
- package/dist/chunk-4ABAFG44.js +0 -33
- package/dist/chunk-4ABAFG44.js.map +0 -1
- package/dist/chunk-HM77MWB6.js +0 -2
- package/dist/chunk-HM77MWB6.js.map +0 -1
- package/dist/chunk-HNDVAKEK.js.map +0 -1
- package/dist/chunk-HQZHZM6U.js +0 -2
- package/dist/chunk-HQZHZM6U.js.map +0 -1
- package/dist/chunk-X6FJATUE.js +0 -29
- package/dist/chunk-X6FJATUE.js.map +0 -1
- package/dist/chunk-XLVRRGOX.js.map +0 -1
- package/dist/kyber-2WDOTUQX.js +0 -2
- package/dist/verifier-RQRYXA4C.js +0 -2
package/dist/client.d.ts
CHANGED
package/dist/client.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{b as LiopClient}from'./chunk-
|
|
1
|
+
export{b as LiopClient}from'./chunk-ISKM7EAL.js';import'./chunk-UVTEJYHN.js';import'./chunk-ANFXJGMP.js';import'./chunk-DBXGYHKY.js';import'./chunk-V5MKJT6S.js';import'./chunk-7I6YJS3C.js';import'./chunk-S6RJHZV2.js';import'./chunk-4C666HHU.js';//# sourceMappingURL=client.js.map
|
|
2
2
|
//# sourceMappingURL=client.js.map
|
package/dist/gateway.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{a as LiopHybridGateway}from'./chunk-
|
|
1
|
+
export{a as LiopHybridGateway}from'./chunk-SYMZRXI3.js';import'./chunk-UK7OBXGZ.js';import'./chunk-UVTEJYHN.js';import'./chunk-ANFXJGMP.js';import'./chunk-DBXGYHKY.js';import'./chunk-V5MKJT6S.js';import'./chunk-S6RJHZV2.js';import'./chunk-4C666HHU.js';//# sourceMappingURL=gateway.js.map
|
|
2
2
|
//# sourceMappingURL=gateway.js.map
|
|
@@ -8,6 +8,15 @@ import { CallToolRequest, CallToolResult } from './types.js';
|
|
|
8
8
|
* Provides conditional TLS credential factories for gRPC connections.
|
|
9
9
|
* When TLS options are provided, connections are secured with mutual TLS.
|
|
10
10
|
* Otherwise, falls back to insecure credentials (alpha/development mode).
|
|
11
|
+
*
|
|
12
|
+
* Production Hardening (Phase 128):
|
|
13
|
+
* - When NODE_ENV=production and TLS is configured but certificate loading
|
|
14
|
+
* fails, the system throws a fatal error instead of silently degrading
|
|
15
|
+
* to insecure credentials. This prevents MITM/eavesdropping attacks
|
|
16
|
+
* caused by misconfigured certificate paths going unnoticed.
|
|
17
|
+
* - Reference: gRPC-node official docs — "Using insecure credentials in
|
|
18
|
+
* production poses significant security risks including eavesdropping,
|
|
19
|
+
* MITM attacks, and lack of authentication."
|
|
11
20
|
*/
|
|
12
21
|
|
|
13
22
|
interface LiopTlsOptions {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { LiopBridgeOptions, LiopMcpBridge, LiopStreamBridge, LiopStreamBridgeOptions } from './bridge.js';
|
|
2
|
-
import { L as LiopTlsOptions } from './index-
|
|
3
|
-
export { a as LiopClient } from './index-
|
|
2
|
+
import { L as LiopTlsOptions } from './index-BihN3W-K.js';
|
|
3
|
+
export { a as LiopClient } from './index-BihN3W-K.js';
|
|
4
4
|
export { LiopHybridGateway } from './gateway.js';
|
|
5
5
|
export { LiopManifest, MeshNode, MeshNodeConfig } from './mesh.js';
|
|
6
6
|
import * as grpc from '@grpc/grpc-js';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export{b as WasiSandbox}from'./chunk-
|
|
1
|
+
export{b as WasiSandbox}from'./chunk-C65RM2A3.js';export{b as LiopClient,a as LiopRpcClient}from'./chunk-ISKM7EAL.js';export{c as PromptSchema,b as ResourceSchema,a as ToolSchema}from'./chunk-TNMS53OP.js';export{b as LiopMcpBridge,a as LiopStreamBridge}from'./chunk-NWZ5KZDN.js';export{a as LiopHybridGateway}from'./chunk-SYMZRXI3.js';export{a as LiopRpcServer,f as LiopServer,b as NerScanner,c as PII_PATTERNS,d as PII_PRESETS,e as PiiScanner}from'./chunk-WG353XMU.js';import'./chunk-2MGFSIXN.js';export{b as HeuristicTokenEstimator,e as LiopOTelBridge,a as RealTokenEstimator,f as TokenTelemetryEngine,d as createSyncTokenEstimator,c as createTokenEstimator}from'./chunk-UK7OBXGZ.js';import'./chunk-UVTEJYHN.js';import'./chunk-ANFXJGMP.js';import'./chunk-DBXGYHKY.js';import'./chunk-V5MKJT6S.js';export{a as MeshNode}from'./chunk-7I6YJS3C.js';import'./chunk-S6RJHZV2.js';import'./chunk-4C666HHU.js';var u=(e=>(e.CapabilityViolation="CapabilityViolation",e.SandboxEscape="SandboxEscape",e.PiiLeak="PiiLeak",e.InvalidIntent="InvalidIntent",e.Throttled="Throttled",e.ZkVerificationFailed="ZkVerificationFailed",e.MeshUnavailable="MeshUnavailable",e.ConnectionFailed="ConnectionFailed",e))(u||{}),n=class extends Error{code;constructor(t,o){super(o),this.name="LiopError",this.code=t;}};var f={claude:{xmlStandard:true,jsonSchemaPreferred:false},openai:{xmlStandard:false,jsonSchemaPreferred:true},gemini:{xmlStandard:false,jsonSchemaPreferred:true}};function D(a){let t=f[a],o=`[LIOP-PROTO-V1: LOGIC-ON-ORIGIN SPECIFICATION]
|
|
2
2
|
You are interacting with a Logic-Injection-on-Origin Protocol (LIOP) Mesh Network.
|
|
3
3
|
Unlike standard MCP where you pull context to evaluate it remotely, in LIOP you WRITE code that executes on the data's origin.
|
|
4
4
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/prompts/adapters.ts"],"names":["ErrorCode","LiopError","code","message","PROVIDER_CONFIGS","generateSystemInstructions","provider","config","instructions"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/prompts/adapters.ts"],"names":["ErrorCode","LiopError","code","message","PROVIDER_CONFIGS","generateSystemInstructions","provider","config","instructions"],"mappings":"q4BAAO,IAAKA,OACXA,CAAAA,CAAA,mBAAA,CAAsB,qBAAA,CACtBA,CAAAA,CAAA,cAAgB,eAAA,CAChBA,CAAAA,CAAA,OAAA,CAAU,SAAA,CACVA,EAAA,aAAA,CAAgB,eAAA,CAChBA,EAAA,SAAA,CAAY,WAAA,CACZA,EAAA,oBAAA,CAAuB,sBAAA,CACvBA,CAAAA,CAAA,eAAA,CAAkB,kBAClBA,CAAAA,CAAA,gBAAA,CAAmB,kBAAA,CARRA,CAAAA,CAAAA,EAAAA,CAAAA,EAAA,IAWCC,CAAAA,CAAN,cAAwB,KAAM,CACpB,KAEhB,WAAA,CAAYC,CAAAA,CAAiBC,EAAiB,CAC7C,KAAA,CAAMA,CAAO,CAAA,CACb,IAAA,CAAK,IAAA,CAAO,WAAA,CACZ,KAAK,IAAA,CAAOD,EACb,CACD,ECLA,IAAME,CAAAA,CAAqD,CAC1D,MAAA,CAAQ,CAAE,YAAa,IAAA,CAAM,mBAAA,CAAqB,KAAM,CAAA,CACxD,MAAA,CAAQ,CAAE,WAAA,CAAa,KAAA,CAAO,mBAAA,CAAqB,IAAK,EACxD,MAAA,CAAQ,CAAE,YAAa,KAAA,CAAO,mBAAA,CAAqB,IAAK,CACzD,CAAA,CAMO,SAASC,CAAAA,CAA2BC,EAA8B,CACxE,IAAMC,EAASH,CAAAA,CAAiBE,CAAQ,EAEpCE,CAAAA,CAAe,CAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAcnB,OAAID,CAAAA,CAAO,WAAA,CACVC,CAAAA,EAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAUND,CAAAA,CAAO,sBACjBC,CAAAA,EAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAAA,CAWVA,CACR","file":"index.js","sourcesContent":["export enum ErrorCode {\n\tCapabilityViolation = \"CapabilityViolation\",\n\tSandboxEscape = \"SandboxEscape\",\n\tPiiLeak = \"PiiLeak\",\n\tInvalidIntent = \"InvalidIntent\",\n\tThrottled = \"Throttled\",\n\tZkVerificationFailed = \"ZkVerificationFailed\",\n\tMeshUnavailable = \"MeshUnavailable\",\n\tConnectionFailed = \"ConnectionFailed\",\n}\n\nexport class LiopError extends Error {\n\tpublic readonly code: ErrorCode;\n\n\tconstructor(code: ErrorCode, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"LiopError\";\n\t\tthis.code = code;\n\t}\n}\n","/**\n * LIOP Cross-AI Prompt Adapters (Fase 92)\n *\n * Normalizes system instructions for different LLM providers (Claude, OpenAI, Gemini)\n * to ensure they understand how to generate \"Logic-on-Origin\" WASM-compatible payload structures.\n */\n\nexport type AIProvider = \"claude\" | \"openai\" | \"gemini\";\n\nexport interface PromptConfig {\n\txmlStandard: boolean;\n\tjsonSchemaPreferred: boolean;\n}\n\nconst PROVIDER_CONFIGS: Record<AIProvider, PromptConfig> = {\n\tclaude: { xmlStandard: true, jsonSchemaPreferred: false },\n\topenai: { xmlStandard: false, jsonSchemaPreferred: true },\n\tgemini: { xmlStandard: false, jsonSchemaPreferred: true },\n};\n\n/**\n * Generates specific System Prompts optimized for the provided AI.\n * This instructs the LLM on how to bypass Context-Pulling and use Logic-Injection (Zero-Shot).\n */\nexport function generateSystemInstructions(provider: AIProvider): string {\n\tconst config = PROVIDER_CONFIGS[provider];\n\n\tlet instructions = `[LIOP-PROTO-V1: LOGIC-ON-ORIGIN SPECIFICATION]\nYou are interacting with a Logic-Injection-on-Origin Protocol (LIOP) Mesh Network.\nUnlike standard MCP where you pull context to evaluate it remotely, in LIOP you WRITE code that executes on the data's origin.\n\n### CORE PARADIGM\nWhen you call a tool or resource, you MUST provide a payload that represents secure sandboxed logic to be executed on the remote Node.\nThe node will execute your logic securely on the raw secure data, and return only the RESULT, avoiding PII data egress.\n\n### EXECUTION RULES\n1. Provide a self-contained JavaScript syntax block that we will compile to WASM-Sandboxed logic.\n2. Rely only on standard ECMA script features (No Node.js polyfills).\n3. The logic must end by returning the calculated insights, not the raw data.\n`;\n\n\tif (config.xmlStandard) {\n\t\tinstructions += `\n### PAYLOAD FORMATTING (CLAUDE-XML PREFERRED)\nYou must wrap your logic precisely within <liop_logic> tags.\nExample:\n<liop_logic>\nconst records = await liop.readResource(\"liop://vault/patients\");\nconst filtered = records.filter(r => r.disease === \"Hypertension\");\nreturn { alert: \"High risk demographic\", targetCount: filtered.length };\n</liop_logic>\n`;\n\t} else if (config.jsonSchemaPreferred) {\n\t\tinstructions += `\n### PAYLOAD FORMATTING (JSON PARSING PREFERRED)\nYou must provide your logic strictly within a JSON string key called \\`\"logic_blob\"\\` inside your tool call parameters.\nExample:\n{\n \"target\": \"liop://vault/patients\",\n \"logic_blob\": \"const records = await liop.readResource(args.target); return { targetCount: records.filter(r => r.disease === 'Hypertension').length };\"\n}\n`;\n\t}\n\n\treturn instructions;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"kyber-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"kyber-NONMBQNH.js"}
|
package/dist/mesh.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import'./chunk-RWRRBYG4.js';export{a as MeshNode}from'./chunk-
|
|
1
|
+
import'./chunk-RWRRBYG4.js';export{a as MeshNode}from'./chunk-7I6YJS3C.js';import'./chunk-S6RJHZV2.js';import'./chunk-4C666HHU.js';//# sourceMappingURL=mesh.js.map
|
|
2
2
|
//# sourceMappingURL=mesh.js.map
|
package/dist/server.d.ts
CHANGED
|
@@ -143,6 +143,8 @@ interface AggregationPolicy {
|
|
|
143
143
|
maxOutputRows?: number;
|
|
144
144
|
/** Allow arrays containing only primitive values (default: true) */
|
|
145
145
|
allowPrimitiveArrays?: boolean;
|
|
146
|
+
/** Block min/max extraction when dataset size < this value (default: 50) */
|
|
147
|
+
minMaxBlockThreshold?: number;
|
|
146
148
|
}
|
|
147
149
|
interface LogicExecutionPolicy {
|
|
148
150
|
/**
|
|
@@ -158,6 +160,21 @@ interface LogicExecutionPolicy {
|
|
|
158
160
|
* Optional additional deny patterns checked against extracted logic source.
|
|
159
161
|
*/
|
|
160
162
|
preflightDenyPatterns?: RegExp[];
|
|
163
|
+
/**
|
|
164
|
+
* Differential Privacy epsilon per query (default: 1.0).
|
|
165
|
+
* Lower = stronger privacy + more noise. Standard: Apple iOS uses 1.0.
|
|
166
|
+
*/
|
|
167
|
+
dpEpsilon?: number;
|
|
168
|
+
/**
|
|
169
|
+
* DP sensitivity: max change when one record added/removed (default: 1.0).
|
|
170
|
+
* For SUM queries on a field with range [0, X], set sensitivity = X.
|
|
171
|
+
*/
|
|
172
|
+
dpSensitivity?: number;
|
|
173
|
+
/**
|
|
174
|
+
* Max queries per numeric field per PQC session (default: 5).
|
|
175
|
+
* Prevents multi-query differencing attacks.
|
|
176
|
+
*/
|
|
177
|
+
queryBudgetPerField?: number;
|
|
161
178
|
}
|
|
162
179
|
declare class LiopServer {
|
|
163
180
|
private serverInfo;
|
|
@@ -172,6 +189,7 @@ declare class LiopServer {
|
|
|
172
189
|
private readonly toolCallWindowMs;
|
|
173
190
|
private globalCallWindow;
|
|
174
191
|
private readonly globalCallMaxPerWindow;
|
|
192
|
+
private fieldQueryBudget;
|
|
175
193
|
private readonly taintAnalyzer;
|
|
176
194
|
private tools;
|
|
177
195
|
private resources;
|
package/dist/server.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{f as LiopServer,b as NerScanner,c as PII_PATTERNS,d as PII_PRESETS,e as PiiScanner}from'./chunk-
|
|
1
|
+
export{f as LiopServer,b as NerScanner,c as PII_PATTERNS,d as PII_PRESETS,e as PiiScanner}from'./chunk-WG353XMU.js';import'./chunk-2MGFSIXN.js';import'./chunk-V5MKJT6S.js';import'./chunk-7I6YJS3C.js';import'./chunk-S6RJHZV2.js';import'./chunk-4C666HHU.js';//# sourceMappingURL=server.js.map
|
|
2
2
|
//# sourceMappingURL=server.js.map
|
package/dist/types.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{c as PromptSchema,b as ResourceSchema,a as ToolSchema}from'./chunk-
|
|
1
|
+
export{c as PromptSchema,b as ResourceSchema,a as ToolSchema}from'./chunk-TNMS53OP.js';import'./chunk-2MGFSIXN.js';import'./chunk-4C666HHU.js';//# sourceMappingURL=types.js.map
|
|
2
2
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"verifier-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"verifier-6M7GY4TW.js"}
|
|
@@ -8,6 +8,11 @@ interface WorkerData {
|
|
|
8
8
|
sessionToken: string;
|
|
9
9
|
isEncrypted?: boolean;
|
|
10
10
|
aesNonce?: Uint8Array;
|
|
11
|
+
dpConfig?: {
|
|
12
|
+
epsilon: number;
|
|
13
|
+
sensitivity: number;
|
|
14
|
+
smallDatasetThreshold: number;
|
|
15
|
+
};
|
|
11
16
|
}
|
|
12
17
|
declare function processLogicExecution(data: WorkerData): Promise<{
|
|
13
18
|
image_id: string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {a,b}from'../chunk-
|
|
1
|
+
import {a,b}from'../chunk-C65RM2A3.js';import {a as a$1,b as b$1}from'../chunk-ANFXJGMP.js';import'../chunk-4C666HHU.js';import {Buffer}from'buffer';import g from'crypto';import {createMlKem768}from'mlkem';var C={epsilon:1,sensitivity:1,smallDatasetThreshold:50},I=1,K=10;function V(t,r){let n;do r?n=g.createHash("sha256").update(`${r.seed}:${r.counter++}`).digest().readUInt32BE(0)/4294967296-.5:n=g.randomBytes(4).readUInt32BE(0)/4294967296-.5;while(n===0||n===-0.5);return -t*Math.sign(n)*Math.log(1-2*Math.abs(n))}function G(t,r={},n){let e={...C,...r},a=e.sensitivity/e.epsilon,o=t+V(a,n);return Math.round(o*1e4)/1e4}function R(t,r,n){if(!t)return r;let e=t.toLowerCase(),a=/count|length|size|num|gainer|loser|positive|negative|nan_|null_|empty_|finite_|non_finite_/i.test(e),o=e==="total"||e==="n"||e==="total_records"||e.startsWith("total_")||e.startsWith("num_")||/total.*(count|items|entries|rows|records|tickers)/i.test(e);return a||o?1:/avg|mean|average/.test(e)&&n>0?r/n:r}function M(t,r={},n){let e={...C,...r};if(n>=e.smallDatasetThreshold)return t;n<K&&e.epsilon<I&&(e.epsilon=I);let a;return e.seed&&(a={seed:e.seed,counter:0}),A(t,e,n,void 0,a)}function A(t,r,n,e,a){if(typeof t=="number"&&Number.isFinite(t)){let o=R(e,r.sensitivity,n),u=G(t,{...r,sensitivity:o},a),p=e!=null&&R(e,r.sensitivity,n)===1;return (Number.isInteger(t)||p)&&(u=Math.round(u)),t>=0&&(u=Math.max(0,u)),u}if(Array.isArray(t))return t.map(o=>A(o,r,n,e,a));if(t!==null&&typeof t=="object"){let o={};for(let[u,p]of Object.entries(t))o[u]=A(p,r,n,u,a);return o}return t}async function Q(t){let{ciphertext:r,secretKeyObj:n,wasmBinary:e,inputs:a$2,aesNonce:o,records:u,isEncrypted:p=true,dpConfig:S}=t,s,O={},T=Buffer.alloc(32);if(p){let l=new Uint8Array(n),c=new Uint8Array(r),d=(await createMlKem768()).decap(c,l),f=Buffer.from(d);T=f;let m=Buffer.from(e),k=m.subarray(-16),b=m.subarray(0,-16),w=g.createDecipheriv("aes-256-gcm",f,Buffer.from(o||new Uint8Array(12)));w.setAuthTag(k);let y=w.update(b);y=Buffer.concat([y,w.final()]),s=y;for(let[W,j]of Object.entries(a$2||{})){let D=Buffer.from(j),H=D.subarray(0,12),z=D.subarray(-16),F=D.subarray(12,-16),_=g.createDecipheriv("aes-256-gcm",f,H);_.setAuthTag(z);let v=_.update(F);v=Buffer.concat([v,_.final()]),O[W]=JSON.parse(v.toString("utf-8"));}}else e[0]===0&&e[1]===97&&e[2]===115&&e[3]===109?s=Buffer.from(e):s=Buffer.from(e).toString("utf-8");let U=s[0]===0&&s[1]===97&&s[2]===115&&s[3]===109;if(s instanceof Buffer&&U){let l=new Uint8Array(s),c=await WebAssembly.compile(l);a.analyze(c);}else s instanceof Buffer&&!U&&(s=s.toString("utf-8"));typeof s=="string"&&(s=a$1(s));let x=new b;await x.init();try{let l=await x.execute(s,u,O),c=l.output,h;typeof s=="string"?h=Buffer.from(s,"utf-8"):h=new Uint8Array(s);let d=b$1(h).toString("hex"),f=g.createHash("sha256").update(JSON.stringify(u||[])).digest("hex");S&&(c=M(c,{...S,seed:`${f}:${d}`},u?.length||0));let m=Buffer.from(JSON.stringify({image_id:d,dataset_hash:f,output_hash:g.createHash("sha256").update(typeof c=="string"?c:JSON.stringify(c)).digest("hex"),fuel:l.fuelConsumed,ts:Date.now()})),k=g.createHmac("sha256",T).update(m).digest(),b=Buffer.alloc(2);b.writeUInt16BE(m.length);let y=Buffer.concat([Buffer.from([1]),b,m,k]).toString("base64");return {image_id:d,zk_receipt:y,output:c,fuel_consumed:l.fuelConsumed}}finally{await x.teardown();}}export{Q as default};//# sourceMappingURL=logic-execution.js.map
|
|
2
2
|
//# sourceMappingURL=logic-execution.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/workers/logic-execution.ts"],"names":["processLogicExecution","data","ciphertext","secretKeyObj","wasmBinary","inputs","aesNonce","records","isEncrypted","decryptedPayload","decryptedInputs","sessionSecret","Buffer","sk","ct","sharedSecret","createMlKem768","aesKey","wasmBuffer","authTag","encryptedData","decipher","crypto","decrypted","key","encValue","valBuffer","inputNonce","valTag","valData","valDecipher","valDecrypted","isWasm","wasmBytes","compiledModule","ASTGuardian","normalizeLogicSource","sandbox","WasiSandbox","result","logicBytes","imageId","deriveLogicImageDigest","journal","seal","journalLen","zkReceipt"],"mappings":"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","file":"logic-execution.js","sourcesContent":["import { Buffer } from \"node:buffer\";\nimport crypto from \"node:crypto\";\nimport { createMlKem768 } from \"mlkem\";\nimport {\n\tderiveLogicImageDigest,\n\tnormalizeLogicSource,\n} from \"../crypto/logic-image-id.js\";\nimport { ASTGuardian } from \"../sandbox/guardian.js\";\nimport { WasiSandbox } from \"../sandbox/wasi.js\";\n\nexport interface WorkerData {\n\tciphertext: Uint8Array;\n\tsecretKeyObj: ArrayLike<number>;\n\tkyberPublicKey: Uint8Array;\n\twasmBinary: Uint8Array; // Can also be JS code in non-encrypted mode\n\tinputs: Record<string, Uint8Array>;\n\trecords?: Record<string, unknown>[];\n\tsessionToken: string;\n\tisEncrypted?: boolean;\n\taesNonce?: Uint8Array;\n}\n\nexport default async function processLogicExecution(data: WorkerData): Promise<{\n\timage_id: string;\n\toutput: unknown;\n\tfuel_consumed: number;\n\tzk_receipt?: string;\n}> {\n\tconst {\n\t\tciphertext,\n\t\tsecretKeyObj,\n\t\twasmBinary,\n\t\tinputs,\n\t\taesNonce,\n\t\trecords,\n\t\tisEncrypted = true,\n\t} = data;\n\n\tlet decryptedPayload: Buffer | string;\n\tconst decryptedInputs: Record<string, unknown> = {};\n\tlet sessionSecret = Buffer.alloc(32); // Fallback if plain text (no PQC)\n\n\tif (isEncrypted) {\n\t\t// 1. Decapsulate Kyber secret\n\t\tconst sk = new Uint8Array(secretKeyObj);\n\t\tconst ct = new Uint8Array(ciphertext);\n\t\tconst kem = await createMlKem768();\n\t\tconst sharedSecret = kem.decap(ct, sk);\n\t\tconst aesKey = Buffer.from(sharedSecret);\n\t\tsessionSecret = aesKey;\n\n\t\t// 2. Decrypt Main Payload (WASM/JS Code)\n\t\t// LIOP Serialization: Ciphertext = EncryptedData + 16-byte AuthTag\n\t\tconst wasmBuffer = Buffer.from(wasmBinary);\n\t\tconst authTag = wasmBuffer.subarray(-16);\n\t\tconst encryptedData = wasmBuffer.subarray(0, -16);\n\n\t\tconst decipher = crypto.createDecipheriv(\n\t\t\t\"aes-256-gcm\",\n\t\t\taesKey,\n\t\t\tBuffer.from(aesNonce || new Uint8Array(12)),\n\t\t);\n\t\tdecipher.setAuthTag(authTag);\n\t\tlet decrypted = decipher.update(encryptedData);\n\t\tdecrypted = Buffer.concat([decrypted, decipher.final()]);\n\t\tdecryptedPayload = decrypted;\n\n\t\t// 3. Decrypt Inputs\n\t\tfor (const [key, encValue] of Object.entries(inputs || {})) {\n\t\t\tconst valBuffer = Buffer.from(encValue);\n\t\t\t// Extract 12-byte prepended nonce, ciphertext, and 16-byte AuthTag\n\t\t\tconst inputNonce = valBuffer.subarray(0, 12);\n\t\t\tconst valTag = valBuffer.subarray(-16);\n\t\t\tconst valData = valBuffer.subarray(12, -16);\n\n\t\t\tconst valDecipher = crypto.createDecipheriv(\n\t\t\t\t\"aes-256-gcm\",\n\t\t\t\taesKey,\n\t\t\t\tinputNonce,\n\t\t\t);\n\t\t\tvalDecipher.setAuthTag(valTag);\n\t\t\tlet valDecrypted = valDecipher.update(valData);\n\t\t\tvalDecrypted = Buffer.concat([valDecrypted, valDecipher.final()]);\n\t\t\tdecryptedInputs[key] = JSON.parse(valDecrypted.toString(\"utf-8\"));\n\t\t}\n\t} else {\n\t\t// Transparent mode: payload is provided directly\n\t\t// If it's WASM (Magic bytes: \\0asm), keep as Buffer\n\t\tif (\n\t\t\twasmBinary[0] === 0x00 &&\n\t\t\twasmBinary[1] === 0x61 &&\n\t\t\twasmBinary[2] === 0x73 &&\n\t\t\twasmBinary[3] === 0x6d\n\t\t) {\n\t\t\tdecryptedPayload = Buffer.from(wasmBinary);\n\t\t} else {\n\t\t\tdecryptedPayload = Buffer.from(wasmBinary).toString(\"utf-8\");\n\t\t}\n\t}\n\n\t// 3. Inspect AST with Guardian-TS (if WASM)\n\tconst isWasm =\n\t\tdecryptedPayload[0] === 0x00 &&\n\t\tdecryptedPayload[1] === 0x61 &&\n\t\tdecryptedPayload[2] === 0x73 &&\n\t\tdecryptedPayload[3] === 0x6d;\n\n\tif (decryptedPayload instanceof Buffer && isWasm) {\n\t\t// Ensure we pass a compatible BufferSource\n\t\tconst wasmBytes = new Uint8Array(decryptedPayload);\n\t\tconst compiledModule = await WebAssembly.compile(wasmBytes);\n\t\tASTGuardian.analyze(compiledModule);\n\t} else if (decryptedPayload instanceof Buffer && !isWasm) {\n\t\tdecryptedPayload = decryptedPayload.toString(\"utf-8\");\n\t}\n\n\t// Strip only a whole-document LIOP envelope (see logic-image-id.ts).\n\tif (typeof decryptedPayload === \"string\") {\n\t\tdecryptedPayload = normalizeLogicSource(decryptedPayload);\n\t}\n\n\t// 4. Instantiate and Execute WASI Sandbox (or V8 Fallback)\n\tconst sandbox = new WasiSandbox();\n\tawait sandbox.init();\n\n\ttry {\n\t\tconst result = await sandbox.execute(\n\t\t\tdecryptedPayload,\n\t\t\trecords,\n\t\t\tdecryptedInputs,\n\t\t);\n\n\t\t// 5. Generate Cryptographic Proof of Execution (HMAC-SHA256 Commitment)\n\t\tlet logicBytes: Uint8Array;\n\t\tif (typeof decryptedPayload === \"string\") {\n\t\t\tlogicBytes = Buffer.from(decryptedPayload, \"utf-8\");\n\t\t} else {\n\t\t\tlogicBytes = new Uint8Array(decryptedPayload);\n\t\t}\n\t\tconst imageId = deriveLogicImageDigest(logicBytes).toString(\"hex\");\n\n\t\tconst journal = Buffer.from(\n\t\t\tJSON.stringify({\n\t\t\t\timage_id: imageId,\n\t\t\t\toutput_hash: crypto\n\t\t\t\t\t.createHash(\"sha256\")\n\t\t\t\t\t.update(\n\t\t\t\t\t\ttypeof result.output === \"string\"\n\t\t\t\t\t\t\t? result.output\n\t\t\t\t\t\t\t: JSON.stringify(result.output),\n\t\t\t\t\t)\n\t\t\t\t\t.digest(\"hex\"),\n\t\t\t\tfuel: result.fuelConsumed,\n\t\t\t\tts: Date.now(),\n\t\t\t}),\n\t\t);\n\n\t\tconst seal = crypto\n\t\t\t.createHmac(\"sha256\", sessionSecret)\n\t\t\t.update(journal)\n\t\t\t.digest();\n\t\tconst journalLen = Buffer.alloc(2);\n\t\tjournalLen.writeUInt16BE(journal.length);\n\t\tconst receiptBuf = Buffer.concat([\n\t\t\tBuffer.from([0x01]), // Receipt format v1\n\t\t\tjournalLen,\n\t\t\tjournal,\n\t\t\tseal, // 32 bytes HMAC\n\t\t]);\n\t\tconst zkReceipt = receiptBuf.toString(\"base64\");\n\n\t\treturn {\n\t\t\timage_id: imageId,\n\t\t\tzk_receipt: zkReceipt,\n\t\t\toutput: result.output,\n\t\t\tfuel_consumed: result.fuelConsumed,\n\t\t};\n\t} finally {\n\t\tawait sandbox.teardown();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/security/dp-engine.ts","../../src/workers/logic-execution.ts"],"names":["DEFAULT_DP_CONFIG","EPSILON_FLOOR","EPSILON_FLOOR_THRESHOLD","laplaceSample","scale","prngState","u","crypto","addLaplaceNoise","value","config","merged","noisyValue","deriveFieldSensitivity","key","globalSensitivity","recordCount","lk","isCountWord","isTotalCount","applyDpToOutput","output","walkAndNoise","node","currentKey","fieldSensitivity","isCountKey","item","result","processLogicExecution","data","ciphertext","secretKeyObj","wasmBinary","inputs","aesNonce","records","isEncrypted","dpConfig","decryptedPayload","decryptedInputs","sessionSecret","Buffer","sk","ct","sharedSecret","createMlKem768","aesKey","wasmBuffer","authTag","encryptedData","decipher","decrypted","encValue","valBuffer","inputNonce","valTag","valData","valDecipher","valDecrypted","isWasm","wasmBytes","compiledModule","ASTGuardian","normalizeLogicSource","sandbox","WasiSandbox","finalOutput","logicBytes","imageId","deriveLogicImageDigest","datasetHash","journal","seal","journalLen","zkReceipt"],"mappings":"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","file":"logic-execution.js","sourcesContent":["/**\n * LIOP Differential Privacy Engine — Laplace Mechanism (NIST SP 800-226)\n *\n * Applies calibrated Laplace noise to numeric query outputs,\n * providing ε-differential privacy guarantees against differencing\n * and binary search attacks (F-01, F-02 from security audit).\n *\n * Key design decisions (Phase 110 — Industrial Recalibration):\n * 1. CSPRNG: Uses crypto.randomBytes() instead of Math.random()\n * to prevent state-reconstruction attacks on the noise generator.\n * 2. Query-Aware Sensitivity: COUNT keys get sensitivity=1,\n * AVG keys get sensitivity/n, SUM keys use global config.\n * 3. Epsilon Floor: Auto-enforce ε≥1.0 for datasets with n<10\n * to prevent catastrophic utility destruction.\n *\n * Reference: Dwork & Roth 2014, \"The Algorithmic Foundations of Differential Privacy\"\n * Standards: NIST SP 800-226, Google DP Library, US Census TopDown, Apple iOS DP\n * Industry precedent: Apple (ε=2.0 Health, ε=8.0 Keyboard), US Census (ε=1.0–4.0)\n */\n\nimport crypto from \"node:crypto\";\n\n// ── Public Configuration ─────────────────────────────────────────────\n\nexport interface DpConfig {\n\t/**\n\t * Privacy budget per query (default: 1.0).\n\t * Lower = stronger privacy + more noise. Higher = weaker privacy + less noise.\n\t * Industry standard: Apple iOS Health uses ε=2.0, US Census uses ε=1.0–4.0.\n\t */\n\tepsilon: number;\n\t/**\n\t * Max change in output when one record is added/removed.\n\t * For SUM queries: set to the max plausible value of the field.\n\t * For COUNT queries: the engine automatically overrides to 1.\n\t * For AVG queries: the engine automatically divides by recordCount.\n\t * Default: 1.0 (appropriate for counts and ratios).\n\t */\n\tsensitivity: number;\n\t/**\n\t * Only apply DP noise when dataset size is below this threshold.\n\t * Large datasets have natural statistical privacy (k-anonymity).\n\t * Default: 50 (aligned with HIPAA Safe Harbor minimum).\n\t */\n\tsmallDatasetThreshold: number;\n\t/**\n\t * Optional deterministic seed (e.g., datasetHash + imageId).\n\t * Enables Deterministic Differential Privacy (DDP) for audit modes,\n\t * ensuring perfectly reproducible ZK-Receipts while preserving DP.\n\t */\n\tseed?: string;\n}\n\nconst DEFAULT_DP_CONFIG: DpConfig = {\n\tepsilon: 1.0,\n\tsensitivity: 1.0,\n\tsmallDatasetThreshold: 50,\n};\n\n/**\n * Minimum epsilon enforced for very small datasets (n < 10).\n * Apple's most sensitive category (Health Data) uses ε=2.0 on millions of records.\n * Using ε<1.0 on datasets with <10 records destroys utility completely.\n */\nconst EPSILON_FLOOR = 1.0;\nconst EPSILON_FLOOR_THRESHOLD = 10;\n\n// ── Core Laplace Mechanism ───────────────────────────────────────────\n\nexport interface PrngState {\n\tseed: string;\n\tcounter: number;\n}\n\n/**\n * Generates a sample from the Laplace(0, scale) distribution\n * using inverse CDF sampling with a CSPRNG source.\n *\n * SECURITY: Uses crypto.randomBytes() (OS-level entropy pool) instead of\n * Math.random() (Xorshift128+ PRNG). This prevents state-reconstruction\n * attacks where an adversary observing 3-5 noisy outputs could predict\n * all future noise values and strip the DP protection entirely.\n *\n * Deterministic Audit Mode: If prngState is provided, derives cryptographic\n * entropy using SHA-256 over the seed and an auto-incrementing counter,\n * guaranteeing ZK-Receipt determinism while retaining mathematical privacy.\n *\n * Reference: NIST SP 800-226 §3.2 — \"Implementations must use a CSPRNG\n * for noise generation to maintain the mathematical privacy guarantee.\"\n */\nfunction laplaceSample(scale: number, prngState?: PrngState): number {\n\tlet u: number;\n\tdo {\n\t\tif (prngState) {\n\t\t\tconst hash = crypto\n\t\t\t\t.createHash(\"sha256\")\n\t\t\t\t.update(`${prngState.seed}:${prngState.counter++}`)\n\t\t\t\t.digest();\n\t\t\t// 4 bytes → Uint32 → uniform float in (-0.5, 0.5)\n\t\t\tu = hash.readUInt32BE(0) / 0x100000000 - 0.5;\n\t\t} else {\n\t\t\tconst buf = crypto.randomBytes(4);\n\t\t\tu = buf.readUInt32BE(0) / 0x100000000 - 0.5;\n\t\t}\n\t} while (u === 0 || u === -0.5); // Ensure no exactly 0 or -0.5 for log domain\n\treturn -scale * Math.sign(u) * Math.log(1 - 2 * Math.abs(u));\n}\n\n/**\n * Applies Laplace noise to a single numeric value.\n *\n * @param value - The true computed result\n * @param config - DP configuration (epsilon, sensitivity, seed)\n * @param prngState - Optional state tracking for deterministic sampling\n * @returns Noisy value with ε-differential privacy guarantee\n */\nexport function addLaplaceNoise(\n\tvalue: number,\n\tconfig: Partial<DpConfig> = {},\n\tprngState?: PrngState,\n): number {\n\tconst merged = { ...DEFAULT_DP_CONFIG, ...config };\n\tconst scale = merged.sensitivity / merged.epsilon;\n\tconst noisyValue = value + laplaceSample(scale, prngState);\n\t// Round to 4 decimal places to prevent long random digit strings\n\t// from triggering regex-based PII egress filters (e.g. phone numbers)\n\treturn Math.round(noisyValue * 10000) / 10000;\n}\n\n// ── Query-Aware Sensitivity ─────────────────────────────────────────\n\n/**\n * Derives field-level sensitivity based on key name semantics.\n *\n * This follows Google DP's architectural separation of CountParams,\n * SumParams, and MeanParams — each with independent sensitivity.\n *\n * Axioms (Dwork & Roth 2014):\n * - COUNT: Adding/removing one record changes count by at most 1.\n * - SUM: Adding/removing one record changes sum by at most max_value.\n * - AVG: Sensitivity = max_value / n (bounded contribution).\n *\n * @param key - Output field name (e.g., \"count\", \"avg_balance\", \"totalRevenue\")\n * @param globalSensitivity - Operator-configured max change per record\n * @param recordCount - Dataset size for average normalization\n */\nfunction deriveFieldSensitivity(\n\tkey: string | undefined,\n\tglobalSensitivity: number,\n\trecordCount: number,\n): number {\n\tif (!key) return globalSensitivity;\n\n\tconst lk = key.toLowerCase();\n\n\t// COUNT queries: sensitivity is ALWAYS 1 (fundamental DP axiom)\n\t// Match unambiguous count words: count, length, size, num (anywhere in key),\n\t// as well as common filter prefixes used in audits (nan_, negative_, positive_, null_, empty_, finite_, non_finite_).\n\t// \"total\" is ambiguous (\"totalRevenue\" = SUM, \"total\" or \"total_records\" = COUNT).\n\t// Only treat \"total\" as count when it IS the key or ends with a count suffix.\n\tconst isCountWord =\n\t\t/count|length|size|num|gainer|loser|positive|negative|nan_|null_|empty_|finite_|non_finite_/i.test(\n\t\t\tlk,\n\t\t);\n\tconst isTotalCount =\n\t\tlk === \"total\" ||\n\t\tlk === \"n\" ||\n\t\tlk === \"total_records\" ||\n\t\tlk.startsWith(\"total_\") || // Catch total_tickers, total_users\n\t\tlk.startsWith(\"num_\") || // Catch num_records, num_ticks\n\t\t/total.*(count|items|entries|rows|records|tickers)/i.test(lk);\n\tif (isCountWord || isTotalCount) return 1;\n\n\t// AVERAGE queries: sensitivity = globalSensitivity / n\n\tif (/avg|mean|average/.test(lk) && recordCount > 0) {\n\t\treturn globalSensitivity / recordCount;\n\t}\n\n\t// SUM / unknown: use operator-configured sensitivity\n\treturn globalSensitivity;\n}\n\n// ── Output Walker ────────────────────────────────────────────────────\n\n/**\n * Recursively walks a JSON output object and applies Laplace noise\n * to all finite numeric leaf values. Non-numeric values (strings,\n * booleans, null) are preserved unchanged.\n *\n * IMPORTANT: This function NEVER mutates the input object.\n * It always returns a new object tree, preserving data integrity\n * of the original sandbox output for ZK-Receipt verification.\n *\n * @param output - The sandbox computation result\n * @param config - DP configuration (epsilon, sensitivity, threshold)\n * @param recordCount - Source dataset size (noise only if < threshold)\n * @returns New object with noisy numeric values (never mutates input)\n */\nexport function applyDpToOutput(\n\toutput: unknown,\n\tconfig: Partial<DpConfig> = {},\n\trecordCount: number,\n): unknown {\n\tconst merged = { ...DEFAULT_DP_CONFIG, ...config };\n\n\t// Large datasets have natural statistical privacy — skip noise\n\tif (recordCount >= merged.smallDatasetThreshold) {\n\t\treturn output;\n\t}\n\n\t// NIST SP 800-226: For very small datasets, enforce minimum epsilon\n\t// to prevent catastrophic utility destruction. Apple uses ε≥2.0 even\n\t// for health data on millions of records; using ε<1.0 on n<10 is\n\t// mathematically equivalent to random number generation.\n\tif (recordCount < EPSILON_FLOOR_THRESHOLD && merged.epsilon < EPSILON_FLOOR) {\n\t\tmerged.epsilon = EPSILON_FLOOR;\n\t}\n\n\tlet prngState: PrngState | undefined;\n\tif (merged.seed) {\n\t\tprngState = { seed: merged.seed, counter: 0 };\n\t}\n\n\treturn walkAndNoise(output, merged, recordCount, undefined, prngState);\n}\n\n/**\n * Internal recursive walker that applies noise to numeric leaves.\n * Handles: numbers, arrays, objects (arbitrary nesting depth).\n *\n * Uses query-aware sensitivity: COUNT keys → sensitivity=1,\n * AVG keys → sensitivity/n, SUM/unknown → global sensitivity.\n */\nfunction walkAndNoise(\n\tnode: unknown,\n\tconfig: DpConfig,\n\trecordCount: number,\n\tcurrentKey?: string,\n\tprngState?: PrngState,\n): unknown {\n\tif (typeof node === \"number\" && Number.isFinite(node)) {\n\t\t// Query-aware sensitivity per Google DP / NIST SP 800-226\n\t\tconst fieldSensitivity = deriveFieldSensitivity(\n\t\t\tcurrentKey,\n\t\t\tconfig.sensitivity,\n\t\t\trecordCount,\n\t\t);\n\t\tlet noisyValue = addLaplaceNoise(\n\t\t\tnode,\n\t\t\t{\n\t\t\t\t...config,\n\t\t\t\tsensitivity: fieldSensitivity,\n\t\t\t},\n\t\t\tprngState,\n\t\t);\n\n\t\t// Semantic heuristics to preserve structural invariants:\n\t\t// Reuse the same count-key detection logic as deriveFieldSensitivity\n\t\tconst isCountKey =\n\t\t\tcurrentKey != null &&\n\t\t\tderiveFieldSensitivity(currentKey, config.sensitivity, recordCount) === 1;\n\n\t\t// If original was an integer OR key suggests a count, force integer\n\t\t// (US Census TopDown: all counts must be non-negative integers)\n\t\tif (Number.isInteger(node) || isCountKey) {\n\t\t\tnoisyValue = Math.round(noisyValue);\n\t\t}\n\n\t\t// If original was non-negative, clamp to 0\n\t\t// (US Census TopDown: enforces non-negative constraint in post-processing)\n\t\tif (node >= 0) {\n\t\t\tnoisyValue = Math.max(0, noisyValue);\n\t\t}\n\n\t\treturn noisyValue;\n\t}\n\n\tif (Array.isArray(node)) {\n\t\t// Pass currentKey down for array items so they inherit semantics\n\t\treturn node.map((item) =>\n\t\t\twalkAndNoise(item, config, recordCount, currentKey, prngState),\n\t\t);\n\t}\n\n\tif (node !== null && typeof node === \"object\") {\n\t\tconst result: Record<string, unknown> = {};\n\t\tfor (const [key, value] of Object.entries(\n\t\t\tnode as Record<string, unknown>,\n\t\t)) {\n\t\t\tresult[key] = walkAndNoise(value, config, recordCount, key, prngState);\n\t\t}\n\t\treturn result;\n\t}\n\n\t// Strings, booleans, null — pass through unchanged\n\treturn node;\n}\n","import { Buffer } from \"node:buffer\";\nimport crypto from \"node:crypto\";\nimport { createMlKem768 } from \"mlkem\";\nimport {\n\tderiveLogicImageDigest,\n\tnormalizeLogicSource,\n} from \"../crypto/logic-image-id.js\";\nimport { ASTGuardian } from \"../sandbox/guardian.js\";\nimport { WasiSandbox } from \"../sandbox/wasi.js\";\nimport { applyDpToOutput } from \"../security/dp-engine.js\";\n\nexport interface WorkerData {\n\tciphertext: Uint8Array;\n\tsecretKeyObj: ArrayLike<number>;\n\tkyberPublicKey: Uint8Array;\n\twasmBinary: Uint8Array; // Can also be JS code in non-encrypted mode\n\tinputs: Record<string, Uint8Array>;\n\trecords?: Record<string, unknown>[];\n\tsessionToken: string;\n\tisEncrypted?: boolean;\n\taesNonce?: Uint8Array;\n\tdpConfig?: {\n\t\tepsilon: number;\n\t\tsensitivity: number;\n\t\tsmallDatasetThreshold: number;\n\t};\n}\n\nexport default async function processLogicExecution(data: WorkerData): Promise<{\n\timage_id: string;\n\toutput: unknown;\n\tfuel_consumed: number;\n\tzk_receipt?: string;\n}> {\n\tconst {\n\t\tciphertext,\n\t\tsecretKeyObj,\n\t\twasmBinary,\n\t\tinputs,\n\t\taesNonce,\n\t\trecords,\n\t\tisEncrypted = true,\n\t\tdpConfig,\n\t} = data;\n\n\tlet decryptedPayload: Buffer | string;\n\tconst decryptedInputs: Record<string, unknown> = {};\n\tlet sessionSecret = Buffer.alloc(32); // Fallback if plain text (no PQC)\n\n\tif (isEncrypted) {\n\t\t// 1. Decapsulate Kyber secret\n\t\tconst sk = new Uint8Array(secretKeyObj);\n\t\tconst ct = new Uint8Array(ciphertext);\n\t\tconst kem = await createMlKem768();\n\t\tconst sharedSecret = kem.decap(ct, sk);\n\t\tconst aesKey = Buffer.from(sharedSecret);\n\t\tsessionSecret = aesKey;\n\n\t\t// 2. Decrypt Main Payload (WASM/JS Code)\n\t\t// LIOP Serialization: Ciphertext = EncryptedData + 16-byte AuthTag\n\t\tconst wasmBuffer = Buffer.from(wasmBinary);\n\t\tconst authTag = wasmBuffer.subarray(-16);\n\t\tconst encryptedData = wasmBuffer.subarray(0, -16);\n\n\t\tconst decipher = crypto.createDecipheriv(\n\t\t\t\"aes-256-gcm\",\n\t\t\taesKey,\n\t\t\tBuffer.from(aesNonce || new Uint8Array(12)),\n\t\t);\n\t\tdecipher.setAuthTag(authTag);\n\t\tlet decrypted = decipher.update(encryptedData);\n\t\tdecrypted = Buffer.concat([decrypted, decipher.final()]);\n\t\tdecryptedPayload = decrypted;\n\n\t\t// 3. Decrypt Inputs\n\t\tfor (const [key, encValue] of Object.entries(inputs || {})) {\n\t\t\tconst valBuffer = Buffer.from(encValue);\n\t\t\t// Extract 12-byte prepended nonce, ciphertext, and 16-byte AuthTag\n\t\t\tconst inputNonce = valBuffer.subarray(0, 12);\n\t\t\tconst valTag = valBuffer.subarray(-16);\n\t\t\tconst valData = valBuffer.subarray(12, -16);\n\n\t\t\tconst valDecipher = crypto.createDecipheriv(\n\t\t\t\t\"aes-256-gcm\",\n\t\t\t\taesKey,\n\t\t\t\tinputNonce,\n\t\t\t);\n\t\t\tvalDecipher.setAuthTag(valTag);\n\t\t\tlet valDecrypted = valDecipher.update(valData);\n\t\t\tvalDecrypted = Buffer.concat([valDecrypted, valDecipher.final()]);\n\t\t\tdecryptedInputs[key] = JSON.parse(valDecrypted.toString(\"utf-8\"));\n\t\t}\n\t} else {\n\t\t// Transparent mode: payload is provided directly\n\t\t// If it's WASM (Magic bytes: \\0asm), keep as Buffer\n\t\tif (\n\t\t\twasmBinary[0] === 0x00 &&\n\t\t\twasmBinary[1] === 0x61 &&\n\t\t\twasmBinary[2] === 0x73 &&\n\t\t\twasmBinary[3] === 0x6d\n\t\t) {\n\t\t\tdecryptedPayload = Buffer.from(wasmBinary);\n\t\t} else {\n\t\t\tdecryptedPayload = Buffer.from(wasmBinary).toString(\"utf-8\");\n\t\t}\n\t}\n\n\t// 3. Inspect AST with Guardian-TS (if WASM)\n\tconst isWasm =\n\t\tdecryptedPayload[0] === 0x00 &&\n\t\tdecryptedPayload[1] === 0x61 &&\n\t\tdecryptedPayload[2] === 0x73 &&\n\t\tdecryptedPayload[3] === 0x6d;\n\n\tif (decryptedPayload instanceof Buffer && isWasm) {\n\t\t// Ensure we pass a compatible BufferSource\n\t\tconst wasmBytes = new Uint8Array(decryptedPayload);\n\t\tconst compiledModule = await WebAssembly.compile(wasmBytes);\n\t\tASTGuardian.analyze(compiledModule);\n\t} else if (decryptedPayload instanceof Buffer && !isWasm) {\n\t\tdecryptedPayload = decryptedPayload.toString(\"utf-8\");\n\t}\n\n\t// Strip only a whole-document LIOP envelope (see logic-image-id.ts).\n\tif (typeof decryptedPayload === \"string\") {\n\t\tdecryptedPayload = normalizeLogicSource(decryptedPayload);\n\t}\n\n\t// 4. Instantiate and Execute WASI Sandbox (or V8 Fallback)\n\tconst sandbox = new WasiSandbox();\n\tawait sandbox.init();\n\n\ttry {\n\t\tconst result = await sandbox.execute(\n\t\t\tdecryptedPayload,\n\t\t\trecords,\n\t\t\tdecryptedInputs,\n\t\t);\n\n\t\tlet finalOutput = result.output;\n\n\t\t// Pre-compute Image ID and Dataset Hash for Audit Trail & DP Seeding\n\t\tlet logicBytes: Uint8Array;\n\t\tif (typeof decryptedPayload === \"string\") {\n\t\t\tlogicBytes = Buffer.from(decryptedPayload, \"utf-8\");\n\t\t} else {\n\t\t\tlogicBytes = new Uint8Array(decryptedPayload);\n\t\t}\n\t\tconst imageId = deriveLogicImageDigest(logicBytes).toString(\"hex\");\n\n\t\t// Phase 110: Include dataset_hash for SOX audit trail compliance.\n\t\t// This SHA-256 anchor proves the underlying dataset was identical\n\t\t// across consecutive queries, separating DP noise from data mutation.\n\t\tconst datasetHash = crypto\n\t\t\t.createHash(\"sha256\")\n\t\t\t.update(JSON.stringify(records || []))\n\t\t\t.digest(\"hex\");\n\n\t\t// Apply Differential Privacy before committing to the ZK-Receipt\n\t\tif (dpConfig) {\n\t\t\tfinalOutput = applyDpToOutput(\n\t\t\t\tfinalOutput,\n\t\t\t\t{\n\t\t\t\t\t...dpConfig,\n\t\t\t\t\tseed: `${datasetHash}:${imageId}`,\n\t\t\t\t},\n\t\t\t\trecords?.length || 0,\n\t\t\t);\n\t\t}\n\n\t\t// 5. Generate Cryptographic Proof of Execution (HMAC-SHA256 Commitment)\n\n\t\tconst journal = Buffer.from(\n\t\t\tJSON.stringify({\n\t\t\t\timage_id: imageId,\n\t\t\t\tdataset_hash: datasetHash,\n\t\t\t\toutput_hash: crypto\n\t\t\t\t\t.createHash(\"sha256\")\n\t\t\t\t\t.update(\n\t\t\t\t\t\ttypeof finalOutput === \"string\"\n\t\t\t\t\t\t\t? finalOutput\n\t\t\t\t\t\t\t: JSON.stringify(finalOutput),\n\t\t\t\t\t)\n\t\t\t\t\t.digest(\"hex\"),\n\t\t\t\tfuel: result.fuelConsumed,\n\t\t\t\tts: Date.now(),\n\t\t\t}),\n\t\t);\n\n\t\tconst seal = crypto\n\t\t\t.createHmac(\"sha256\", sessionSecret)\n\t\t\t.update(journal)\n\t\t\t.digest();\n\t\tconst journalLen = Buffer.alloc(2);\n\t\tjournalLen.writeUInt16BE(journal.length);\n\t\tconst receiptBuf = Buffer.concat([\n\t\t\tBuffer.from([0x01]), // Receipt format v1\n\t\t\tjournalLen,\n\t\t\tjournal,\n\t\t\tseal, // 32 bytes HMAC\n\t\t]);\n\t\tconst zkReceipt = receiptBuf.toString(\"base64\");\n\n\t\treturn {\n\t\t\timage_id: imageId,\n\t\t\tzk_receipt: zkReceipt,\n\t\t\toutput: finalOutput,\n\t\t\tfuel_consumed: result.fuelConsumed,\n\t\t};\n\t} finally {\n\t\tawait sandbox.teardown();\n\t}\n}\n"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {b}from'../chunk-ANFXJGMP.js';import d from'crypto';import'worker_threads';function u(e){return b(e)}async function y(e){let{logicPayload:t,remoteImageIdHex:o,zkReceipt:g,sessionSecret:n}=e,a=u(t).toString("hex");if(a!==o)return {verified:false,message:`Integrity Violation: Local (${a.slice(0,8)}) != Remote (${o.slice(0,8)})`};let r=Buffer.from(g);if(r.length<35)return {verified:false,message:"Receipt too short for binary format."};let s=r[0];if(s!==1)return {verified:false,message:`Unknown receipt version: ${s}`};let c=r.readUInt16BE(1),f=r.subarray(3,3+c),l=r.subarray(3+c);if(l.length!==32)return {verified:false,message:"Invalid seal length (expected 32 bytes HMAC-SHA256)."};try{let i=JSON.parse(f.toString());if(i.image_id!==a)return {verified:!1,message:`Journal ImageID mismatch: ${i.image_id.slice(0,8)} != ${a.slice(0,8)}`}}catch{return {verified:false,message:"Failed to parse journal data."}}if(n&&n.length>0){let i=d.createHmac("sha256",n).update(f).digest();if(!d.timingSafeEqual(l,i))return {verified:false,message:"Invalid seal: HMAC verification failed."}}return {verified:true,message:"HMAC Commitment Verified: Integrity intact."}}async function v(e){try{if(e.action==="verify_receipt")return await y(e);throw new Error("Unknown action in ZkVerifier Worker.")}catch(t){return {verified:false,message:`Verification Error: ${t.message}`}}}export{v as default};//# sourceMappingURL=zk-verifier.js.map
|
|
1
|
+
import {b}from'../chunk-ANFXJGMP.js';import'../chunk-4C666HHU.js';import d from'crypto';import'worker_threads';function u(e){return b(e)}async function y(e){let{logicPayload:t,remoteImageIdHex:o,zkReceipt:g,sessionSecret:n}=e,a=u(t).toString("hex");if(a!==o)return {verified:false,message:`Integrity Violation: Local (${a.slice(0,8)}) != Remote (${o.slice(0,8)})`};let r=Buffer.from(g);if(r.length<35)return {verified:false,message:"Receipt too short for binary format."};let s=r[0];if(s!==1)return {verified:false,message:`Unknown receipt version: ${s}`};let c=r.readUInt16BE(1),f=r.subarray(3,3+c),l=r.subarray(3+c);if(l.length!==32)return {verified:false,message:"Invalid seal length (expected 32 bytes HMAC-SHA256)."};try{let i=JSON.parse(f.toString());if(i.image_id!==a)return {verified:!1,message:`Journal ImageID mismatch: ${i.image_id.slice(0,8)} != ${a.slice(0,8)}`}}catch{return {verified:false,message:"Failed to parse journal data."}}if(n&&n.length>0){let i=d.createHmac("sha256",n).update(f).digest();if(!d.timingSafeEqual(l,i))return {verified:false,message:"Invalid seal: HMAC verification failed."}}return {verified:true,message:"HMAC Commitment Verified: Integrity intact."}}async function v(e){try{if(e.action==="verify_receipt")return await y(e);throw new Error("Unknown action in ZkVerifier Worker.")}catch(t){return {verified:false,message:`Verification Error: ${t.message}`}}}export{v as default};//# sourceMappingURL=zk-verifier.js.map
|
|
2
2
|
//# sourceMappingURL=zk-verifier.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/workers/zk-verifier.ts"],"names":["deriveImageId","logicPayload","deriveLogicImageDigest","verifyZkReceipt","payload","remoteImageIdHex","zkReceipt","sessionSecret","localImageIdHex","receiptBuf","version","journalLen","journal","seal","journalData","expectedSeal","crypto","workerHandler","task","error"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/workers/zk-verifier.ts"],"names":["deriveImageId","logicPayload","deriveLogicImageDigest","verifyZkReceipt","payload","remoteImageIdHex","zkReceipt","sessionSecret","localImageIdHex","receiptBuf","version","journalLen","journal","seal","journalData","expectedSeal","crypto","workerHandler","task","error"],"mappings":"+GAyBA,SAASA,CAAAA,CAAcC,CAAAA,CAAkC,CACxD,OAAOC,CAAAA,CAAuBD,CAAY,CAC3C,CAMA,eAAeE,CAAAA,CACdC,CAAAA,CACkD,CAClD,GAAM,CAAE,YAAA,CAAAH,CAAAA,CAAc,gBAAA,CAAAI,CAAAA,CAAkB,SAAA,CAAAC,CAAAA,CAAW,aAAA,CAAAC,CAAc,CAAA,CAAIH,CAAAA,CAI/DI,CAAAA,CADeR,CAAAA,CAAcC,CAAY,CAAA,CACV,QAAA,CAAS,KAAK,CAAA,CAEnD,GAAIO,CAAAA,GAAoBH,CAAAA,CACvB,OAAO,CACN,QAAA,CAAU,KAAA,CACV,OAAA,CAAS,CAAA,4BAAA,EAA+BG,CAAAA,CAAgB,KAAA,CAAM,CAAA,CAAG,CAAC,CAAC,CAAA,aAAA,EAAgBH,CAAAA,CAAiB,KAAA,CAAM,CAAA,CAAG,CAAC,CAAC,CAAA,CAAA,CAChH,EAID,IAAMI,CAAAA,CAAa,MAAA,CAAO,IAAA,CAAKH,CAAS,CAAA,CACxC,GAAIG,CAAAA,CAAW,MAAA,CAAS,EAAA,CAEvB,OAAO,CACN,QAAA,CAAU,KAAA,CACV,OAAA,CAAS,sCACV,CAAA,CAGD,IAAMC,CAAAA,CAAUD,CAAAA,CAAW,CAAC,CAAA,CAC5B,GAAIC,CAAAA,GAAY,CAAA,CACf,OAAO,CACN,QAAA,CAAU,KAAA,CACV,OAAA,CAAS,4BAA4BA,CAAO,CAAA,CAC7C,CAAA,CAGD,IAAMC,CAAAA,CAAaF,CAAAA,CAAW,YAAA,CAAa,CAAC,CAAA,CACtCG,CAAAA,CAAUH,CAAAA,CAAW,QAAA,CAAS,CAAA,CAAG,CAAA,CAAIE,CAAU,CAAA,CAC/CE,CAAAA,CAAOJ,CAAAA,CAAW,QAAA,CAAS,CAAA,CAAIE,CAAU,CAAA,CAE/C,GAAIE,CAAAA,CAAK,MAAA,GAAW,EAAA,CACnB,OAAO,CACN,QAAA,CAAU,KAAA,CACV,QAAS,sDACV,CAAA,CAID,GAAI,CACH,IAAMC,CAAAA,CAAc,IAAA,CAAK,KAAA,CAAMF,CAAAA,CAAQ,QAAA,EAAU,CAAA,CACjD,GAAIE,CAAAA,CAAY,WAAaN,CAAAA,CAC5B,OAAO,CACN,QAAA,CAAU,CAAA,CAAA,CACV,OAAA,CAAS,CAAA,0BAAA,EAA6BM,CAAAA,CAAY,QAAA,CAAS,KAAA,CAAM,CAAA,CAAG,CAAC,CAAC,CAAA,IAAA,EAAON,EAAgB,KAAA,CAAM,CAAA,CAAG,CAAC,CAAC,CAAA,CACzG,CAEF,CAAA,KAAa,CACZ,OAAO,CAAE,QAAA,CAAU,KAAA,CAAO,OAAA,CAAS,+BAAgC,CACpE,CAGA,GAAID,CAAAA,EAAiBA,CAAAA,CAAc,MAAA,CAAS,CAAA,CAAG,CAC9C,IAAMQ,CAAAA,CAAeC,CAAAA,CACnB,UAAA,CAAW,QAAA,CAAUT,CAAa,CAAA,CAClC,MAAA,CAAOK,CAAO,CAAA,CACd,MAAA,EAAO,CACT,GAAI,CAACI,CAAAA,CAAO,eAAA,CAAgBH,CAAAA,CAAME,CAAY,CAAA,CAC7C,OAAO,CACN,QAAA,CAAU,KAAA,CACV,OAAA,CAAS,yCACV,CAEF,CAEA,OAAO,CACN,QAAA,CAAU,IAAA,CACV,OAAA,CAAS,6CACV,CACD,CAKA,eAAOE,CAAAA,CACNC,CAAAA,CACkD,CAClD,GAAI,CACH,GAAIA,CAAAA,CAAK,MAAA,GAAW,gBAAA,CACnB,OAAO,MAAMf,CAAAA,CAAgBe,CAAI,CAAA,CAElC,MAAM,IAAI,KAAA,CAAM,sCAAsC,CACvD,CAAA,MAASC,CAAAA,CAAO,CACf,OAAO,CACN,QAAA,CAAU,KAAA,CACV,OAAA,CAAS,CAAA,oBAAA,EAAwBA,CAAAA,CAAgB,OAAO,CAAA,CACzD,CACD,CACD","file":"zk-verifier.js","sourcesContent":["import crypto from \"node:crypto\";\nimport { parentPort } from \"node:worker_threads\";\nimport { deriveLogicImageDigest } from \"../crypto/logic-image-id.js\";\n\n// Ensure this worker is used via Piscina pool\nif (!parentPort) {\n\t// Not fatal in Piscina, but handled appropriately\n}\n\n/**\n * ZK Verification Payload Structure.\n * Modeled after RISC Zero & SP1 Receipt formats.\n */\nexport interface ZkVerificationPayload {\n\taction: \"verify_receipt\";\n\t/** Original logic payload (JS/WASM) sent by client */\n\tlogicPayload: Uint8Array;\n\t/** Expected ImageID (SHA-256) of the execution state */\n\tremoteImageIdHex: string;\n\t/** Cbor-encoded or raw buffer containing the execution Receipt (Journal + Seal) */\n\tzkReceipt: Uint8Array;\n\t/** Kyber-derived session secret to verify HMAC signature */\n\tsessionSecret?: Uint8Array;\n}\n\nfunction deriveImageId(logicPayload: Uint8Array): Buffer {\n\treturn deriveLogicImageDigest(logicPayload);\n}\n\n/**\n * Simulates heavy ZK-Proof cryptographic verification.\n * In a real environment, this delegates to @risc0/verifier or SP1 FFI bindings.\n */\nasync function verifyZkReceipt(\n\tpayload: ZkVerificationPayload,\n): Promise<{ verified: boolean; message: string }> {\n\tconst { logicPayload, remoteImageIdHex, zkReceipt, sessionSecret } = payload;\n\n\t// 1. Calculate local ImageID (Integrity Check)\n\tconst localImageId = deriveImageId(logicPayload);\n\tconst localImageIdHex = localImageId.toString(\"hex\");\n\n\tif (localImageIdHex !== remoteImageIdHex) {\n\t\treturn {\n\t\t\tverified: false,\n\t\t\tmessage: `Integrity Violation: Local (${localImageIdHex.slice(0, 8)}) != Remote (${remoteImageIdHex.slice(0, 8)})`,\n\t\t};\n\t}\n\n\t// 2. Structural Verification: Deserialize Binary Receipt\n\tconst receiptBuf = Buffer.from(zkReceipt);\n\tif (receiptBuf.length < 35) {\n\t\t// 1 version + 2 len + 32 seal minimum\n\t\treturn {\n\t\t\tverified: false,\n\t\t\tmessage: \"Receipt too short for binary format.\",\n\t\t};\n\t}\n\n\tconst version = receiptBuf[0];\n\tif (version !== 0x01) {\n\t\treturn {\n\t\t\tverified: false,\n\t\t\tmessage: `Unknown receipt version: ${version}`,\n\t\t};\n\t}\n\n\tconst journalLen = receiptBuf.readUInt16BE(1);\n\tconst journal = receiptBuf.subarray(3, 3 + journalLen);\n\tconst seal = receiptBuf.subarray(3 + journalLen);\n\n\tif (seal.length !== 32) {\n\t\treturn {\n\t\t\tverified: false,\n\t\t\tmessage: \"Invalid seal length (expected 32 bytes HMAC-SHA256).\",\n\t\t};\n\t}\n\n\t// 3. Parse journal and verify imageId\n\ttry {\n\t\tconst journalData = JSON.parse(journal.toString());\n\t\tif (journalData.image_id !== localImageIdHex) {\n\t\t\treturn {\n\t\t\t\tverified: false,\n\t\t\t\tmessage: `Journal ImageID mismatch: ${journalData.image_id.slice(0, 8)} != ${localImageIdHex.slice(0, 8)}`,\n\t\t\t};\n\t\t}\n\t} catch (_e) {\n\t\treturn { verified: false, message: \"Failed to parse journal data.\" };\n\t}\n\n\t// 4. Mathematical Verification (HMAC-SHA256)\n\tif (sessionSecret && sessionSecret.length > 0) {\n\t\tconst expectedSeal = crypto\n\t\t\t.createHmac(\"sha256\", sessionSecret)\n\t\t\t.update(journal)\n\t\t\t.digest();\n\t\tif (!crypto.timingSafeEqual(seal, expectedSeal)) {\n\t\t\treturn {\n\t\t\t\tverified: false,\n\t\t\t\tmessage: \"Invalid seal: HMAC verification failed.\",\n\t\t\t};\n\t\t}\n\t}\n\n\treturn {\n\t\tverified: true,\n\t\tmessage: \"HMAC Commitment Verified: Integrity intact.\",\n\t};\n}\n\n/**\n * Main worker entry point for Piscina.\n */\nexport default async function workerHandler(\n\ttask: ZkVerificationPayload,\n): Promise<{ verified: boolean; message: string }> {\n\ttry {\n\t\tif (task.action === \"verify_receipt\") {\n\t\t\treturn await verifyZkReceipt(task);\n\t\t}\n\t\tthrow new Error(\"Unknown action in ZkVerifier Worker.\");\n\t} catch (error) {\n\t\treturn {\n\t\t\tverified: false,\n\t\t\tmessage: `Verification Error: ${(error as Error).message}`,\n\t\t};\n\t}\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nekzus/liop",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.20",
|
|
4
4
|
"description": "Official SDK for Logic-Injection-on-Origin Protocol (LIOP). Deploy Logic-on-Origin with WebAssembly at gRPC speed and bidirectional MCP compatibility.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"bin": {
|
|
8
|
-
"liop
|
|
8
|
+
"liop": "./dist/bin/agent.js"
|
|
9
9
|
},
|
|
10
10
|
"sideEffects": false,
|
|
11
11
|
"files": [
|
|
@@ -43,31 +43,6 @@
|
|
|
43
43
|
"import": "./dist/mesh.js"
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
|
-
"scripts": {
|
|
47
|
-
"build": "tsup && npx tsx scripts/copy-protos.ts",
|
|
48
|
-
"test": "vitest run --fileParallelism=false",
|
|
49
|
-
"test:all": "vitest run --fileParallelism=false",
|
|
50
|
-
"test:integration": "vitest run tests/integration --fileParallelism=false",
|
|
51
|
-
"test:conformance": "vitest run tests/conformance --fileParallelism=false",
|
|
52
|
-
"test:watch": "vitest",
|
|
53
|
-
"test:coverage": "vitest run --coverage",
|
|
54
|
-
"lint": "biome lint .",
|
|
55
|
-
"format": "biome format --write .",
|
|
56
|
-
"check": "biome check .",
|
|
57
|
-
"demo:client-quickstart": "pnpm --filter @liop/example-client-quickstart start",
|
|
58
|
-
"demo:server-quickstart": "pnpm --filter @liop/example-server-quickstart start",
|
|
59
|
-
"demo:server": "pnpm --filter @liop/example-server start",
|
|
60
|
-
"demo:client": "pnpm --filter @liop/example-client start",
|
|
61
|
-
"test:crossnet": "tsx tests/infra/cli/crossnet.ts",
|
|
62
|
-
"test:crossnet:burn": "tsx tests/infra/cli/crossnet-burn.ts",
|
|
63
|
-
"demo:build": "tsx tests/infra/cli/demo-build.ts",
|
|
64
|
-
"demo:start": "tsx tests/infra/cli/demo-start.ts",
|
|
65
|
-
"demo:start:rebuild": "tsx tests/infra/cli/demo-start-rebuild.ts",
|
|
66
|
-
"demo:stop": "tsx tests/infra/cli/demo-stop.ts",
|
|
67
|
-
"demo:clean": "tsx tests/infra/cli/demo-clean.ts",
|
|
68
|
-
"demo:claude": "tsx tests/infra/cli/demo-claude.ts",
|
|
69
|
-
"demo:inspector": "tsx tests/infra/cli/demo-inspector.ts"
|
|
70
|
-
},
|
|
71
46
|
"keywords": [
|
|
72
47
|
"liop",
|
|
73
48
|
"logic-injection-on-origin",
|
|
@@ -105,13 +80,18 @@
|
|
|
105
80
|
},
|
|
106
81
|
"devDependencies": {
|
|
107
82
|
"@biomejs/biome": "^2.4.4",
|
|
83
|
+
"@opentelemetry/api": "^1.9.1",
|
|
108
84
|
"@opentelemetry/sdk-metrics": "^2.7.0",
|
|
109
85
|
"@types/node": "^25.3.1",
|
|
110
86
|
"@vitest/coverage-v8": "^4.0.18",
|
|
87
|
+
"acorn": "^8.16.0",
|
|
88
|
+
"acorn-walk": "^8.3.5",
|
|
111
89
|
"tsup": "^8.5.1",
|
|
112
90
|
"tsx": "^4.21.0",
|
|
113
91
|
"typescript": "^5.9.3",
|
|
114
|
-
"vitest": "^4.0.18"
|
|
92
|
+
"vitest": "^4.0.18",
|
|
93
|
+
"zod": "^3.23.11",
|
|
94
|
+
"zod-to-json-schema": "^3.24.1"
|
|
115
95
|
},
|
|
116
96
|
"dependencies": {
|
|
117
97
|
"@chainsafe/libp2p-noise": "^17.0.0",
|
|
@@ -119,31 +99,22 @@
|
|
|
119
99
|
"@grpc/grpc-js": "^1.14.3",
|
|
120
100
|
"@grpc/proto-loader": "^0.8.0",
|
|
121
101
|
"@hono/node-server": "^1.19.11",
|
|
122
|
-
"@libp2p/bootstrap": "^
|
|
123
|
-
"@libp2p/crypto": "^5.1.
|
|
124
|
-
"@libp2p/identify": "^4.
|
|
125
|
-
"@libp2p/kad-dht": "^16.
|
|
126
|
-
"@libp2p/
|
|
127
|
-
"@libp2p/
|
|
128
|
-
"@libp2p/
|
|
129
|
-
"@libp2p/
|
|
130
|
-
"@libp2p/tcp": "^11.0.14",
|
|
131
|
-
"@libp2p/websockets": "^10.1.7",
|
|
102
|
+
"@libp2p/bootstrap": "^12.0.22",
|
|
103
|
+
"@libp2p/crypto": "^5.1.18",
|
|
104
|
+
"@libp2p/identify": "^4.1.6",
|
|
105
|
+
"@libp2p/kad-dht": "^16.3.0",
|
|
106
|
+
"@libp2p/peer-id": "^6.0.9",
|
|
107
|
+
"@libp2p/ping": "^3.1.5",
|
|
108
|
+
"@libp2p/tcp": "^11.0.20",
|
|
109
|
+
"@libp2p/websockets": "^10.1.13",
|
|
132
110
|
"@multiformats/multiaddr": "^13.0.1",
|
|
133
|
-
"@opentelemetry/api": "^1.9.1",
|
|
134
|
-
"acorn": "^8.16.0",
|
|
135
|
-
"acorn-walk": "^8.3.5",
|
|
136
111
|
"hono": "^4.12.5",
|
|
137
112
|
"it-pipe": "^3.0.1",
|
|
138
|
-
"libp2p": "^3.1
|
|
113
|
+
"libp2p": "^3.3.1",
|
|
139
114
|
"mlkem": "^2.7.0",
|
|
140
115
|
"multiformats": "^13.4.2",
|
|
141
|
-
"p-event": "^7.1.0",
|
|
142
116
|
"piscina": "^5.1.4",
|
|
143
|
-
"
|
|
144
|
-
"uint8arrays": "^3.1.1",
|
|
145
|
-
"zod": "^3.23.11",
|
|
146
|
-
"zod-to-json-schema": "^3.24.1"
|
|
117
|
+
"uint8arrays": "^3.1.1"
|
|
147
118
|
},
|
|
148
119
|
"optionalDependencies": {
|
|
149
120
|
"@modelcontextprotocol/sdk": "^1.28.0",
|
|
@@ -151,11 +122,45 @@
|
|
|
151
122
|
"gpt-tokenizer": "^3.4.0"
|
|
152
123
|
},
|
|
153
124
|
"peerDependencies": {
|
|
154
|
-
"@modelcontextprotocol/sdk": "^1.28.0"
|
|
125
|
+
"@modelcontextprotocol/sdk": "^1.28.0",
|
|
126
|
+
"@opentelemetry/api": "^1.9.1"
|
|
155
127
|
},
|
|
156
128
|
"peerDependenciesMeta": {
|
|
157
129
|
"@modelcontextprotocol/sdk": {
|
|
158
130
|
"optional": true
|
|
131
|
+
},
|
|
132
|
+
"@opentelemetry/api": {
|
|
133
|
+
"optional": true
|
|
159
134
|
}
|
|
135
|
+
},
|
|
136
|
+
"overrides": {
|
|
137
|
+
"content-type": "1.0.5",
|
|
138
|
+
"protobufjs": "^7.5.8",
|
|
139
|
+
"type-is": "2.0.1"
|
|
140
|
+
},
|
|
141
|
+
"scripts": {
|
|
142
|
+
"build": "tsup && npx tsx scripts/copy-protos.ts",
|
|
143
|
+
"test": "vitest run --fileParallelism=false",
|
|
144
|
+
"test:all": "vitest run --fileParallelism=false",
|
|
145
|
+
"test:integration": "vitest run tests/integration --fileParallelism=false",
|
|
146
|
+
"test:conformance": "vitest run tests/conformance --fileParallelism=false",
|
|
147
|
+
"test:watch": "vitest",
|
|
148
|
+
"test:coverage": "vitest run --coverage",
|
|
149
|
+
"lint": "biome lint .",
|
|
150
|
+
"format": "biome format --write .",
|
|
151
|
+
"check": "biome check .",
|
|
152
|
+
"demo:client-quickstart": "pnpm --filter @liop/example-client-quickstart start",
|
|
153
|
+
"demo:server-quickstart": "pnpm --filter @liop/example-server-quickstart start",
|
|
154
|
+
"demo:server": "pnpm --filter @liop/example-server start",
|
|
155
|
+
"demo:client": "pnpm --filter @liop/example-client start",
|
|
156
|
+
"test:crossnet": "tsx tests/infra/cli/crossnet.ts",
|
|
157
|
+
"test:crossnet:burn": "tsx tests/infra/cli/crossnet-burn.ts",
|
|
158
|
+
"demo:build": "tsx tests/infra/cli/demo-build.ts",
|
|
159
|
+
"demo:start": "tsx tests/infra/cli/demo-start.ts",
|
|
160
|
+
"demo:start:rebuild": "tsx tests/infra/cli/demo-start-rebuild.ts",
|
|
161
|
+
"demo:stop": "tsx tests/infra/cli/demo-stop.ts",
|
|
162
|
+
"demo:clean": "tsx tests/infra/cli/demo-clean.ts",
|
|
163
|
+
"demo:claude": "tsx tests/infra/cli/demo-claude.ts",
|
|
164
|
+
"demo:inspector": "tsx tests/infra/cli/demo-inspector.ts"
|
|
160
165
|
}
|
|
161
|
-
}
|
|
166
|
+
}
|
package/dist/chunk-4ABAFG44.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import {a as a$1}from'./chunk-UVTEJYHN.js';import {a as a$3}from'./chunk-DBXGYHKY.js';import {a as a$2,c}from'./chunk-HM77MWB6.js';import {a}from'./chunk-S6RJHZV2.js';import {metrics}from'@opentelemetry/api';import*as N from'crypto';var C=class{name="o200k_base";countFn;constructor(e,r){this.countFn=e,r&&r(1e4);}countTokens(e){return e.length===0?0:this.countFn(e)}},R=class{name="heuristic (chars/4)";countTokens(e){return e.length===0?0:Math.ceil(e.length/4)}};async function B(){try{let y=await import('gpt-tokenizer'),e=new C(y.countTokens,y.setMergeCacheSize);return a.debug("[LIOP-Economy] Token estimator initialized: o200k_base"),e}catch{return a.info("[LIOP-Economy] gpt-tokenizer unavailable, falling back to heuristic estimator"),new R}}function U(){return new R}var V="@nekzus/liop",J="1.2.0-alpha.9",q=[1,4,16,64,256,1024,4096,16384,65536,262144,1048576,4194304,16777216,67108864],Q=[.01,.02,.04,.08,.16,.32,.64,1.28,2.56,5.12,10.24,20.48,40.96,81.92],E=class{tokenUsage;operationDuration;active=false;constructor(){try{let e=metrics.getMeter(V,J);this.tokenUsage=e.createHistogram("gen_ai.client.token.usage",{description:"Number of tokens used in LIOP Logic-on-Origin operations",unit:"{token}",advice:{explicitBucketBoundaries:q}}),this.operationDuration=e.createHistogram("gen_ai.client.operation.duration",{description:"Duration of LIOP operations",unit:"s",advice:{explicitBucketBoundaries:Q}}),this.active=!0,a.debug("[LIOP-OTel] gen_ai.* metrics bridge initialized");}catch(e){a.debug(`[LIOP-OTel] Bridge disabled: ${e instanceof Error?e.message:String(e)}`);let r={record:()=>{}};this.tokenUsage=r,this.operationDuration=r;}}recordTokens(e,r,s,n){this.tokenUsage.record(e,{"gen_ai.system":"liop","gen_ai.operation.name":s,"gen_ai.token.type":r,"gen_ai.request.model":"liop-mesh",...n?{"liop.tool.name":n}:{}});}recordDuration(e,r,s){this.operationDuration.record(e/1e3,{"gen_ai.system":"liop","gen_ai.operation.name":r,...s?{"error.type":s}:{}});}isActive(){return this.active}};var W={tools_list:"chat",tool_call:"execute_tool",resource_read:"chat",resource_list:"chat",prompt_get:"chat",prompt_list:"chat",diagnostic:"chat"},I=class y{static instance=null;operations=[];sessionId;startedAt;estimator;otelBridge;constructor(){this.sessionId=crypto.randomUUID(),this.startedAt=Date.now(),this.estimator=U(),this.otelBridge=new E,this.initRealEstimator();}initRealEstimator(){B().then(e=>{this.estimator=e;}).catch(()=>{});}static getInstance(){return y.instance||(y.instance=new y),y.instance}countTokens(e){try{return this.estimator.countTokens(e)}catch{return Math.ceil(e.length/4)}}record(e){let r={...e,timestamp:Date.now()};this.operations.push(r);try{let s=W[e.type]||"chat";e.estimatedInputTokens>0&&this.otelBridge.recordTokens(e.estimatedInputTokens,"input",s,e.toolName),e.estimatedOutputTokens>0&&this.otelBridge.recordTokens(e.estimatedOutputTokens,"output",s,e.toolName),e.durationMs!==void 0&&this.otelBridge.recordDuration(e.durationMs,s);}catch{}}estimateTokens(e){return this.countTokens(e)}getReport(){return {sessionId:this.sessionId,operations:[...this.operations],totalInputTokens:this.operations.reduce((e,r)=>e+r.estimatedInputTokens,0),totalOutputTokens:this.operations.reduce((e,r)=>e+r.estimatedOutputTokens,0),estimatorName:this.estimator.name,sessionUptimeMs:Date.now()-this.startedAt}}getPerToolReport(){let e=new Map;for(let r of this.operations){let s=r.toolName||r.method,n=e.get(s)||{input:0,output:0,calls:0,avgDurationMs:0},t=n.avgDurationMs*n.calls+(r.durationMs||0),o=n.calls+1;e.set(s,{input:n.input+r.estimatedInputTokens,output:n.output+r.estimatedOutputTokens,calls:o,avgDurationMs:o>0?t/o:0});}return e}formatStatusBlock(){let e=this.getReport();if(e.operations.length===0)return "";let r=this.formatUptime(e.sessionUptimeMs),s=e.totalInputTokens+e.totalOutputTokens,n=new Map;for(let l of e.operations){let d=l.type,g=n.get(d)||{count:0,input:0,output:0};n.set(d,{count:g.count+1,input:g.input+l.estimatedInputTokens,output:g.output+l.estimatedOutputTokens});}let t=Array.from(n.entries()),o=t.map(([l,d],g)=>{let P=g===t.length-1?"\u2502 \u2514\u2500":"\u2502 \u251C\u2500",S=d.output>0?` / ${d.output.toLocaleString()} out`:"";return `${P} ${l} \xD7${d.count} \u2192 ${d.input.toLocaleString()} in${S}`}),c=this.getPerToolReport(),a=Array.from(c.entries()).filter(([l])=>l!=="tools/list"&&l!=="LiopMeshStatus"),u=[];a.length>0&&(u.push("\u251C\u2500 By Tool:"),a.forEach(([l,d],g)=>{let P=g===a.length-1?"\u2502 \u2514\u2500":"\u2502 \u251C\u2500",S=d.output>0?` / ${d.output.toLocaleString()} out`:"",v=d.avgDurationMs>0?` ~${Math.round(d.avgDurationMs)}ms`:"";u.push(`${P} ${l}: ${d.input.toLocaleString()} in${S} (\xD7${d.calls})${v}`);}));let f=e.operations.filter(l=>l.durationMs!==void 0),m=f.length>0?Math.round(f.reduce((l,d)=>l+(d.durationMs||0),0)/f.length):0,i=this.otelBridge.isActive()?"gen_ai.client.token.usage \u2192 active":"disabled";return [`
|
|
2
|
-
Token Economy:`,`\u251C\u2500 Session: ${e.sessionId.slice(0,8)} (${r})`,`\u251C\u2500 Estimator: ${e.estimatorName}`,`\u251C\u2500 Operations: ${e.operations.length}`,...o,`\u251C\u2500 Total: ${e.totalInputTokens.toLocaleString()} in / ${e.totalOutputTokens.toLocaleString()} out (${s.toLocaleString()} combined)`,...u,...m>0?[`\u251C\u2500 Avg Latency: ${m}ms`]:[],`\u2514\u2500 OTel: ${i}`].join(`
|
|
3
|
-
`)}formatUptime(e){let r=Math.floor(e/1e3);if(r<60)return `${r}s`;let s=Math.floor(r/60),n=r%60;if(s<60)return `${s}m ${n}s`;let t=Math.floor(s/60),o=s%60;return `${t}h ${o}m`}reset(){this.operations=[];}static destroy(){y.instance=null;}};function M(){let y=process.env.LIOP_MCP_COMPACT_TOOL_DESCRIPTIONS?.toLowerCase().trim();return y==="1"||y==="true"||y==="yes"}function b(y){let e=y,r=[`
|
|
4
|
-
|
|
5
|
-
[LIOP-PROTO-V1:`,`\r
|
|
6
|
-
\r
|
|
7
|
-
[LIOP-PROTO-V1:`,`
|
|
8
|
-
[LIOP-PROTO-V1:`];for(let s of r){let n=e.indexOf(s);if(n!==-1){e=e.slice(0,n);break}}return e.trimEnd()}var z=300,$=5,F=class y{constructor(e,r=null,s=50051){this.liopServer=e;this.meshNode=r;this.defaultRpcPort=s;this.meshNode&&(this.meshNode.registerManifestHandler(()=>{let n=this.liopServer.listTools().map(o=>({name:o.name,description:o.description,inputSchema:o.inputSchema})),t=this.liopServer.listResources().map(o=>({name:o.name,uri:o.uri,description:o.description,mimeType:o.mimeType}));return {peerId:this.meshNode?.getPeerId()||"unknown",grpcPort:this.defaultRpcPort,tools:[...n],resources:t,serverInfo:this.liopServer.getServerInfo()}}),this.meshNode.announceManifest().catch(n=>{a.info(`[LIOP-Router] Failed to announce manifest: ${n instanceof Error?n.message:String(n)}`);})),process.env.LIOP_DIAGNOSTIC_LEVEL==="full"&&process.stderr.write(`\u26A0\uFE0F [LIOP-Security] Diagnostic level set to FULL \u2014 PeerIDs and network topology are exposed. Do NOT use in production.
|
|
9
|
-
`);}manifestCache=new Map;currentDiscovery=null;verifier=new a$1;onToolsChanged;manifestFailureState=new Map;static MANIFEST_FAILURE_BASE_COOLDOWN_MS=15e3;static MANIFEST_FAILURE_MAX_COOLDOWN_MS=5*6e4;static MANIFEST_SKIP_LOG_THROTTLE_MS=3e4;shouldSkipManifestQuery(e){let r=this.manifestFailureState.get(e);if(!r)return false;let s=Date.now();return s>=r.cooldownUntil?false:(s-r.lastSkipLogAt>y.MANIFEST_SKIP_LOG_THROTTLE_MS&&(a.info(`[LIOP-Router] Skipping manifest query for ${e} during cooldown (${Math.ceil((r.cooldownUntil-s)/1e3)}s remaining)`),r.lastSkipLogAt=s),true)}recordManifestQuerySuccess(e){this.manifestFailureState.delete(e);}recordManifestQueryFailure(e){let r=Date.now(),n=(this.manifestFailureState.get(e)?.failures||0)+1,t=Math.min(y.MANIFEST_FAILURE_BASE_COOLDOWN_MS*2**Math.max(0,n-1),y.MANIFEST_FAILURE_MAX_COOLDOWN_MS);this.manifestFailureState.set(e,{failures:n,cooldownUntil:r+t,lastSkipLogAt:0});}async dispatch(e){let{method:r,params:s,id:n}=e;switch(a.info(`[LIOP-Router] Processing: ${r}`),r){case "initialize":return {jsonrpc:"2.0",id:n,result:{protocolVersion:"2025-11-25",capabilities:{tools:{listChanged:true},resources:{listChanged:true},prompts:{listChanged:true}},serverInfo:this.liopServer.getServerInfo()}};case "notifications/initialized":return this.kickDiscoveryAfterInitialized().catch(()=>{}),null;case "notifications/cancelled":return null;case "ping":return {jsonrpc:"2.0",id:n,result:{}};case "tools/list":{let t=this.liopServer.listTools(),o=await this.getRemoteTools(),c=M()?t.map(p=>({...p,description:b(p.description??"")})):t;a.info(`[LIOP-Router] tools/list: ${t.length} local, ${o.length} remote tools found`);let u=[{name:"LiopMeshStatus",description:"LiopMeshStatus: Returns the current dynamic diagnostic status of the Zero-Trust Neural Mesh.",inputSchema:{type:"object",properties:{},additionalProperties:false}},...c,...o],f=I.getInstance(),m=JSON.stringify(u),i=JSON.stringify({tools:u});return f.record({type:"tools_list",method:"tools/list",estimatedInputTokens:f.countTokens(m),estimatedOutputTokens:f.countTokens(i)}),{jsonrpc:"2.0",id:n,result:{tools:u}}}case "tools/call":return this.transcodeMcpToLiop(n,s);case "resources/list":{let t=this.liopServer.listResources(),o=await this.getRemoteResources(),c=[...t,...o],a=I.getInstance(),u=JSON.stringify(c);return a.record({type:"resource_list",method:"resources/list",estimatedInputTokens:0,estimatedOutputTokens:a.countTokens(u)}),{jsonrpc:"2.0",id:n,result:{resources:c}}}case "resources/read":{let t=s;if(!t?.uri)return {jsonrpc:"2.0",id:n,error:{code:-32602,message:"Missing resource uri"}};try{let o=Date.now(),c=await this.liopServer.readResource(t.uri),a=I.getInstance(),u=JSON.stringify(c);return a.record({type:"resource_read",method:"resources/read",toolName:t.uri,estimatedInputTokens:a.countTokens(t.uri),estimatedOutputTokens:a.countTokens(u),durationMs:Date.now()-o}),{jsonrpc:"2.0",id:n,result:c}}catch(o){let c=t.uri;for(let{manifest:a$1}of this.manifestCache.values()){let u=a$1.resources.find(f=>f.uri===c);if(u)return a.info(`[LIOP-Router] Resolved resource ${c} from cache (Peer: ${a$1.peerId})`),{jsonrpc:"2.0",id:n,result:{contents:[{uri:u.uri,mimeType:u.mimeType||"text/plain",text:u.text||u.description||"No content provided"}]}}}return {jsonrpc:"2.0",id:n,error:{code:-32e3,message:o instanceof Error?o.message:String(o)}}}}case "prompts/list":{let t=this.liopServer.listPrompts(),o=I.getInstance(),c=JSON.stringify(t);return o.record({type:"prompt_list",method:"prompts/list",estimatedInputTokens:0,estimatedOutputTokens:o.countTokens(c)}),{jsonrpc:"2.0",id:n,result:{prompts:t}}}case "prompts/get":{let t=s;if(!t?.name)return {jsonrpc:"2.0",id:n,error:{code:-32602,message:"Missing prompt name"}};try{let o=Date.now(),c=await this.liopServer.getPrompt({name:t.name,arguments:t.arguments||{}}),a=I.getInstance(),u=JSON.stringify({name:t.name,arguments:t.arguments}),f=JSON.stringify(c);return a.record({type:"prompt_get",method:"prompts/get",toolName:t.name,estimatedInputTokens:a.countTokens(u),estimatedOutputTokens:a.countTokens(f),durationMs:Date.now()-o}),{jsonrpc:"2.0",id:n,result:c}}catch(o){return {jsonrpc:"2.0",id:n,error:{code:-32e3,message:o instanceof Error?o.message:String(o)}}}}default:return {jsonrpc:"2.0",id:n,error:{code:-32601,message:`Method not found: ${r}`}}}}kickDiscoveryAfterInitialized(){return (async()=>{await new Promise(e=>setTimeout(e,250)),await Promise.race([this.refreshManifestCache(true),new Promise(e=>setTimeout(e,15e3))]).catch(()=>{});})()}async refreshManifestCache(e=false){if(this.meshNode){if(this.currentDiscovery)return this.currentDiscovery;if(!e&&this.manifestCache.size>0){let r=Date.now();if(Array.from(this.manifestCache.values()).every(({cachedAt:n})=>r-n<z*1e3))return}return this.currentDiscovery=(async()=>{try{let r=Array.from(this.manifestCache.values()).reduce((i,{manifest:p})=>i+p.tools.length,0);if(this.manifestCache.size===0)for(let i=0;i<3;i++){if((this.meshNode.node?.getConnections().length||0)>0){a.info("[LIOP-Router] P2P Connection established. Starting discovery...");break}a.info(`[LIOP-Router] Waiting for P2P connections (attempt ${i+1}/10)...`),await new Promise(l=>setTimeout(l,1e3));}let s=[],n=this.manifestCache.size===0?5:1;for(let i=0;i<n;i++){for(let g=0;g<$;g++){s=await this.meshNode?.discoverManifestProviders()||[];let P=this.meshNode?.getPeerId();if(s.filter(v=>v!==P).length>0)break;g<$-1&&(a.info(`[LIOP-Router] DHT discovery attempt ${g+1}/${$}...`),await new Promise(v=>setTimeout(v,1e3)));}let p=this.meshNode.node?.getConnections().map(g=>g.remotePeer.toString())||[];p.length>0&&(s=Array.from(new Set([...s,...p])));let l=this.meshNode?.getPeerId();if(s.filter(g=>g!==l).length>0)break;i<n-1&&(a.info(`[LIOP-Router] Initial discovery failed (0 providers). Retrying in 1s (${i+1}/${n})...`),await new Promise(g=>setTimeout(g,1e3)));}if(s.length===0){a.info("[LIOP-Router] No manifest providers found after all attempts.");return}e||a.info(`[LIOP-Router] Discovered ${s.length} candidate manifest providers`);let t=new Set((this.meshNode.node?.getConnections?.()||[]).map(i=>i.remotePeer.toString()));s=[...s].sort((i,p)=>{let l=t.has(i)?1:0;return (t.has(p)?1:0)-l});let o=0,c=0,a$1=!1,u=this.meshNode?.getPeerId(),f=s.filter(i=>{if(!this.meshNode||i===u||this.shouldSkipManifestQuery(i))return !1;let p=this.manifestCache.get(i);return p&&Date.now()-p.cachedAt<z*1e3?(o++,!1):!0}),m=await Promise.allSettled(f.map(async i=>this.meshNode?(a.info(`[LIOP-Router] Querying manifest from: ${i}`),{peerId:i,manifest:await this.meshNode.queryManifest(i)}):null));for(let i of m)if(i.status==="fulfilled"&&i.value?.manifest){let{peerId:p,manifest:l}=i.value;this.manifestCache.set(p,{manifest:l,cachedAt:Date.now()}),this.recordManifestQuerySuccess(p),a$1=!0,o++,a.info(`[LIOP-Router] Manifest received from ${p} (${l.tools.length} tools)`);}else i.status==="fulfilled"&&i.value?(this.recordManifestQueryFailure(i.value.peerId),c++,a.info(`[LIOP-Router] Manifest query returned NULL for ${i.value.peerId}`)):i.status==="rejected"&&(c++,a.info("[LIOP-Router] Fatal error querying manifest:",i.reason instanceof Error?i.reason.message:String(i.reason)));this._discoveryStats={candidates:s.length,success:o,failures:c,lastDiscovery:Date.now()},a$1&&Array.from(this.manifestCache.values()).reduce((p,{manifest:l})=>p+l.tools.length,0)!==r&&this.onToolsChanged&&(process.stderr.write(`[LIOP-Router] Mesh topology updated! Emitting notifications/tools/list_changed.
|
|
10
|
-
`),this.onToolsChanged());}finally{this.currentDiscovery=null;}})(),this.currentDiscovery}}getCacheSize(){return this.manifestCache.size}async getRemoteTools(){let e=Number.parseInt(process.env.LIOP_EXPECTED_PROVIDERS??"4",10);if(this.manifestCache.size<e&&this.meshNode){let t=Number.parseInt(process.env.LIOP_INITIAL_DISCOVERY_TIMEOUT_MS??"12000",10),o=Number.isFinite(t)&&t>0?t:12e3,c=Date.now()+o,a$1=0,u=-1;for(;Date.now()<c&&!(this.manifestCache.size>=e||(await Promise.race([this.refreshManifestCache(true),new Promise(f=>setTimeout(f,3e3))]).catch(()=>{}),this.manifestCache.size>=e));){if(this.manifestCache.size===u){if(a$1++,a$1>=3&&this.manifestCache.size>0){a.info(`[LIOP-Router] Provider count stabilized at ${this.manifestCache.size}/${e}. Proceeding with available mesh.`);break}}else a$1=0,u=this.manifestCache.size;await new Promise(f=>setTimeout(f,1e3));}this.manifestCache.size<e&&(a.info(`[LIOP-Router] \u26A0\uFE0F Mesh partially available: ${this.manifestCache.size}/${e} providers. Some tools may be unavailable. Check Docker containers.`),this.refreshManifestCache(true).catch(()=>{}));}let r=[],s=new Set,n=new Set(this.liopServer.listTools().map(t=>t.name));for(let[t,{manifest:o}]of this.manifestCache.entries())for(let c of o.tools){if(c.name==="LiopMeshStatus")continue;let a=c.name;(s.has(c.name)||n.has(c.name))&&(a=`${c.name}_${t.slice(-4)}`),s.add(a);let u=o.serverInfo?.name||"Unknown Provider",f=c.description||`Remote tool from ${u}`,m={name:a,description:M()?b(f):f,inputSchema:c.inputSchema||{type:"object",properties:{}}};typeof m.inputSchema=="object"&&!m.inputSchema.type&&(m.inputSchema.type="object"),typeof m.inputSchema=="object"&&!m.inputSchema.properties&&(m.inputSchema.properties={});let i="";o.taxonomy&&(i=`
|
|
11
|
-
[LIOP-DOMAIN: ${o.taxonomy.domain}]`);let p=m.inputSchema.properties||{},l="";!M()&&p.payload&&(l=`
|
|
12
|
-
[REQUIRES: LIOP-PROTO-V1 ENVELOPE]`),!M()&&m.description.includes("STRICT SCHEMA ADHERENCE")&&(m.description=m.description.replace("STRICT SCHEMA ADHERENCE:","[INDUSTRIAL-REQUISITE] STRICT SCHEMA ADHERENCE (MANDATORY):"));let d=M()?`
|
|
13
|
-
(Peer: ${t.slice(-8)})${i}`:`
|
|
14
|
-
(Origin: ${t.slice(-8)})${i}${l}`;m.description=`${m.description}${d}`,r.push(m);}return r}async getRemoteResources(){this.currentDiscovery||this.refreshManifestCache(true).catch(()=>{});let e=[],r=new Set(this.liopServer.listResources().map(s=>s.uri));for(let[s,{manifest:n}]of this.manifestCache.entries())for(let t of n.resources)if(!r.has(t.uri)){let o={...t},c=n.serverInfo?.name||"Unknown Provider",a="";n.taxonomy&&(a=`
|
|
15
|
-
|
|
16
|
-
[LIOP Zero-Trust Blueprint]
|
|
17
|
-
Domain: ${n.taxonomy.domain}
|
|
18
|
-
Clearance Tier: ${n.taxonomy.clearanceTier}`,n.taxonomy.executionTypes&&n.taxonomy.executionTypes.length>0&&(a+=`
|
|
19
|
-
Execution Types: ${n.taxonomy.executionTypes.join(", ")}`));let u=`
|
|
20
|
-
|
|
21
|
-
[LIOP Zero-Trust Origin]
|
|
22
|
-
Provider: ${c}
|
|
23
|
-
Network ID: ${s}${a}`;o.uri.startsWith("liop://schema/")?(o.name=`[SCHEMA] ${o.name}`,o.description=`[CRITICAL SCHEMA] ${o.description||"Data Dictionary for Zero-Shot Autonomy"}${u}`):o.description=o.description?`${o.description}${u}`:u.trim(),e.push(o),r.add(t.uri);}return e}resolveManifestTarget(e){for(let[s,{manifest:n}]of this.manifestCache.entries())if(n.tools.find(o=>o.name===e))return {peerId:s,originalToolName:e};let r=e.split("_");if(r.length>1){let s=r.pop(),n=r.join("_");for(let[t,{manifest:o}]of this.manifestCache.entries())if(t.endsWith(s||"")&&o.tools.find(a=>a.name===n))return {peerId:t,originalToolName:n}}return null}redactPeerId(e){return (process.env.LIOP_DIAGNOSTIC_LEVEL||"redacted")==="full"?e:`***${e.slice(-8)}`}async transcodeMcpToLiop(e,r){let s=r.name;if(s==="LiopMeshStatus"){this.refreshManifestCache(true).catch(()=>{});let t=this._discoveryStats||{candidates:0,success:0,failures:0},o=this.manifestCache.size,c=this.meshNode?"Active":"Offline",a=Array.from(this.manifestCache.values()).reduce((T,{manifest:k})=>T+k.tools.length,0),u=this.meshNode?this.meshNode.node?.getConnections().length:0,f=this.meshNode&&this.meshNode.config?.bootstrapNodes?this.meshNode.config.bootstrapNodes:[],m=f.length,p=(process.env.LIOP_DIAGNOSTIC_LEVEL||"redacted")!=="minimal",l=p?f.map(T=>{let k=T.split("/"),L=k[k.length-1];return ` \u2022 ${L?L.slice(-8):"Unknown"} (bootstrap)`}).join(`
|
|
24
|
-
`):"",d=this.meshNode?this.meshNode.getRoutingTableSize():0,g=this.meshNode?.getPeerId()||"Offline",P=g==="Offline"?g:this.redactPeerId(g),S=Array.from(this.manifestCache.entries()).flatMap(([T,{manifest:k}])=>k.tools.map(L=>` \u2022 ${L.name} (from origin: ${this.redactPeerId(T)})`)).join(`
|
|
25
|
-
`),v=[`LIOP Mesh Status: ${c==="Active"?"Active":"Offline"}`,`Local Agent Identity: ${P}`,`Network: ${u} Conns | ${d} Mesh Nodes | ${m} Bootstraps`,p&&m>0?`
|
|
26
|
-
Active Bootstraps:
|
|
27
|
-
${l}
|
|
28
|
-
`:"",`Discovery: ${t.candidates} Candidates | ${t.success} OK | ${t.failures} FAIL`,`Tooling: ${o} Providers | ${a} Total Remote Tools`,a>0?`
|
|
29
|
-
Discovered Remote Tools (Zero-Trust Origins):
|
|
30
|
-
${S}`:`
|
|
31
|
-
No remote tools discovered yet.`,I.getInstance().formatStatusBlock()].filter(T=>T!=="").join(`
|
|
32
|
-
`),O=I.getInstance();return O.record({type:"diagnostic",method:"tools/call",toolName:"LiopMeshStatus",estimatedInputTokens:0,estimatedOutputTokens:O.countTokens(v)}),{jsonrpc:"2.0",id:e,result:{content:[{type:"text",text:v}]}}}let n=this.liopServer.listTools().some(t=>t.name===s);if(!n&&this.meshNode){let t=this.resolveManifestTarget(s);if(t||(await this.refreshManifestCache(),t=this.resolveManifestTarget(s)),t)return a.info(`[LIOP-Router] Resolved ${s} via manifest cache (Peer: ${t.peerId}, Original: ${t.originalToolName})`),this.routeToRemoteProvider(e,t.originalToolName,t.peerId,r);let o=[];for(let c=0;c<3&&(o=await this.meshNode.findProviders(s),!(o.length>0));c++)c<2&&await new Promise(a=>setTimeout(a,1e3));if(o.length>0)return this.routeToRemoteProvider(e,s,o[0],r)}if(n)try{let t=Date.now(),o=await this.liopServer.callTool({name:s,arguments:r.arguments||{}}),c=I.getInstance(),a=JSON.stringify(r.arguments||{}),u=JSON.stringify(o);return c.record({type:"tool_call",method:"tools/call",toolName:s,estimatedInputTokens:c.countTokens(a),estimatedOutputTokens:c.countTokens(u),durationMs:Date.now()-t}),{jsonrpc:"2.0",id:e,result:o}}catch(t){return {jsonrpc:"2.0",id:e,error:{code:-32e3,message:t instanceof Error?t.message:String(t)}}}return {jsonrpc:"2.0",id:e,error:{code:-32002,message:`No provider found for tool: ${s}. Ensure the provider node is active and connected to the mesh.`}}}async routeToRemoteProvider(e,r,s,n){if(!this.meshNode)return {jsonrpc:"2.0",id:e,error:{code:-32603,message:"Mesh Node inactive"}};let t=this.manifestCache.get(s),o=this.defaultRpcPort;if(t)o=t.manifest.grpcPort;else {let i=await this.meshNode.queryManifest(s);i&&(o=i.grpcPort,this.manifestCache.set(s,{manifest:i,cachedAt:Date.now()}),t=this.manifestCache.get(s));}if(t&&process.env.LIOP_USE_PUBLISHED_GRPC_PORTS==="1"){let i=t.manifest.serverInfo?.name?.toLowerCase()||"";i.includes("vault")?o=13011:i.includes("bank")?o=13021:i.includes("oracle")&&(o=13031);}let c$1=await this.meshNode.resolvePeer(s),a$1=null,u=await import('os'),f=Object.values(u.networkInterfaces()).flat().filter(i=>i?.family==="IPv4").map(i=>i?.address);for(let i of c$1){let p=i.split("/"),l=p.indexOf("ip4");if(l!==-1){let d=p[l+1];if(d==="127.0.0.1"||f.includes(d)){a$1=`127.0.0.1:${o}`;break}a$1||(a$1=`${d}:${o}`);}}a$1||(a$1=`127.0.0.1:${o}`),a.info(`[LIOP-Router] Dynamic route: ${r} -> ${a$1} (PeerID: ${s})`);let m=new a$2.LogicMesh(a$1,c());return this.performTranscoding(e,m,r,n,s)}async performTranscoding(e,r,s,n,t){let o=s,c=this.meshNode?await this.meshNode.sign(Buffer.from(o)):Buffer.from([]),a=Date.now();return new Promise(u=>{r.negotiateIntent({agent_did:`did:liop:${this.meshNode?.getPeerId()||"mcp-proxy"}`,capability_hash:o,proof_of_intent:c},async(f,m)=>{if(f||!m.accepted)return u({jsonrpc:"2.0",id:e,result:{content:[{type:"text",text:`PQC Handshake Failed: ${f?.message||"Rejected"}`}],isError:true}});let{ciphertext:i,sharedSecret:p}=await a$3.encapsulateAsymmetric(m.kyber_public_key),l=JSON.stringify(n.arguments||{}),d=`return { "__liop_proxy_tool": "${s}", "__liop_proxy_args": ${l} };`,g=N.randomBytes(12),P=this.encryptWithNonce(Buffer.from(d),p,g),S=r.executeLogic({session_token:m.session_token,wasm_binary:new Uint8Array(P),inputs:{},pqc_ciphertext:i,aes_nonce:g}),v="",O=null;S.on("data",T=>{v+=T.semantic_evidence,O=T;}),S.on("end",async()=>{try{if(O&&!await this.verifier.verifyZkReceipt(Buffer.from(d),Buffer.from(O.cryptographic_proof).toString("hex"),Buffer.from(O.zk_receipt)))return u({jsonrpc:"2.0",id:e,result:{content:[{type:"text",text:"SECURITY ALERT: Remote response failed cryptographic integrity audit."}],isError:!0}});let T=JSON.parse(v),k=I.getInstance();k.record({type:"tool_call",method:"tools/call",toolName:s,peerId:t,estimatedInputTokens:k.countTokens(l),estimatedOutputTokens:k.countTokens(v),durationMs:Date.now()-a}),u({jsonrpc:"2.0",id:e,result:T});}catch{u({jsonrpc:"2.0",id:e,result:{content:[{type:"text",text:v}]}});}}),S.on("error",T=>u({jsonrpc:"2.0",id:e,result:{content:[{type:"text",text:`LIOP gRPC Error: ${T.message}`}],isError:true}}));});})}encryptWithNonce(e,r,s){let n=N.createCipheriv("aes-256-gcm",r,s),t=Buffer.concat([n.update(e),n.final()]);return Buffer.concat([t,n.getAuthTag()])}};export{C as a,R as b,B as c,U as d,E as e,I as f,F as g};//# sourceMappingURL=chunk-4ABAFG44.js.map
|
|
33
|
-
//# sourceMappingURL=chunk-4ABAFG44.js.map
|