@nekzus/liop 1.2.0-alpha.9 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +12 -3
  2. package/dist/bin/agent.js +222 -51
  3. package/dist/bridge/index.js +7 -6
  4. package/dist/bridge/stream.js +11 -11
  5. package/dist/client/index.js +46 -35
  6. package/dist/crypto/logic-image-id.d.ts +3 -0
  7. package/dist/crypto/logic-image-id.js +27 -0
  8. package/dist/crypto/verifier.js +7 -19
  9. package/dist/economy/estimator.d.ts +53 -0
  10. package/dist/economy/estimator.js +69 -0
  11. package/dist/economy/index.d.ts +5 -0
  12. package/dist/economy/index.js +3 -0
  13. package/dist/economy/otel.d.ts +38 -0
  14. package/dist/economy/otel.js +100 -0
  15. package/dist/economy/telemetry.d.ts +77 -0
  16. package/dist/economy/telemetry.js +224 -0
  17. package/dist/errors.d.ts +14 -0
  18. package/dist/errors.js +19 -0
  19. package/dist/gateway/hybrid.d.ts +3 -1
  20. package/dist/gateway/hybrid.js +38 -13
  21. package/dist/gateway/router.d.ts +25 -9
  22. package/dist/gateway/router.js +484 -133
  23. package/dist/index.d.ts +3 -0
  24. package/dist/index.js +3 -0
  25. package/dist/mesh/node.d.ts +16 -0
  26. package/dist/mesh/node.js +394 -113
  27. package/dist/prompts/adapters.d.ts +16 -0
  28. package/dist/prompts/adapters.js +55 -0
  29. package/dist/rpc/proto.js +2 -1
  30. package/dist/rpc/server.d.ts +1 -1
  31. package/dist/rpc/server.js +4 -3
  32. package/dist/rpc/tls.js +3 -2
  33. package/dist/sandbox/wasi.d.ts +1 -1
  34. package/dist/sandbox/wasi.js +43 -3
  35. package/dist/security/guardian.js +3 -2
  36. package/dist/security/zk.d.ts +2 -3
  37. package/dist/security/zk.js +22 -9
  38. package/dist/server/index.d.ts +53 -4
  39. package/dist/server/index.js +362 -49
  40. package/dist/server/pii.d.ts +12 -0
  41. package/dist/server/pii.js +90 -0
  42. package/dist/types.d.ts +16 -0
  43. package/dist/utils/logger.d.ts +21 -0
  44. package/dist/utils/logger.js +70 -0
  45. package/dist/utils/mcpCompact.d.ts +11 -0
  46. package/dist/utils/mcpCompact.js +29 -0
  47. package/dist/workers/logic-execution.d.ts +1 -1
  48. package/dist/workers/logic-execution.js +38 -20
  49. package/dist/workers/zk-verifier.js +37 -33
  50. package/package.json +14 -2
@@ -0,0 +1,16 @@
1
+ /**
2
+ * LIOP Cross-AI Prompt Adapters (Fase 92)
3
+ *
4
+ * Normalizes system instructions for different LLM providers (Claude, OpenAI, Gemini)
5
+ * to ensure they understand how to generate "Logic-on-Origin" WASM-compatible payload structures.
6
+ */
7
+ export type AIProvider = "claude" | "openai" | "gemini";
8
+ export interface PromptConfig {
9
+ xmlStandard: boolean;
10
+ jsonSchemaPreferred: boolean;
11
+ }
12
+ /**
13
+ * Generates specific System Prompts optimized for the provided AI.
14
+ * This instructs the LLM on how to bypass Context-Pulling and use Logic-Injection (Zero-Shot).
15
+ */
16
+ export declare function generateSystemInstructions(provider: AIProvider): string;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * LIOP Cross-AI Prompt Adapters (Fase 92)
3
+ *
4
+ * Normalizes system instructions for different LLM providers (Claude, OpenAI, Gemini)
5
+ * to ensure they understand how to generate "Logic-on-Origin" WASM-compatible payload structures.
6
+ */
7
+ const PROVIDER_CONFIGS = {
8
+ claude: { xmlStandard: true, jsonSchemaPreferred: false },
9
+ openai: { xmlStandard: false, jsonSchemaPreferred: true },
10
+ gemini: { xmlStandard: false, jsonSchemaPreferred: true },
11
+ };
12
+ /**
13
+ * Generates specific System Prompts optimized for the provided AI.
14
+ * This instructs the LLM on how to bypass Context-Pulling and use Logic-Injection (Zero-Shot).
15
+ */
16
+ export function generateSystemInstructions(provider) {
17
+ const config = PROVIDER_CONFIGS[provider];
18
+ let instructions = `[LIOP-PROTO-V1: LOGIC-ON-ORIGIN SPECIFICATION]
19
+ You are interacting with a Logic-Injection-on-Origin Protocol (LIOP) Mesh Network.
20
+ Unlike standard MCP where you pull context to evaluate it remotely, in LIOP you WRITE code that executes on the data's origin.
21
+
22
+ ### CORE PARADIGM
23
+ When you call a tool or resource, you MUST provide a payload that represents secure sandboxed logic to be executed on the remote Node.
24
+ The node will execute your logic securely on the raw secure data, and return only the RESULT, avoiding PII data egress.
25
+
26
+ ### EXECUTION RULES
27
+ 1. Provide a self-contained JavaScript syntax block that we will compile to WASM-Sandboxed logic.
28
+ 2. Rely only on standard ECMA script features (No Node.js polyfills).
29
+ 3. The logic must end by returning the calculated insights, not the raw data.
30
+ `;
31
+ if (config.xmlStandard) {
32
+ instructions += `
33
+ ### PAYLOAD FORMATTING (CLAUDE-XML PREFERRED)
34
+ You must wrap your logic precisely within <liop_logic> tags.
35
+ Example:
36
+ <liop_logic>
37
+ const records = await liop.readResource("liop://vault/patients");
38
+ const filtered = records.filter(r => r.disease === "Hypertension");
39
+ return { alert: "High risk demographic", targetCount: filtered.length };
40
+ </liop_logic>
41
+ `;
42
+ }
43
+ else if (config.jsonSchemaPreferred) {
44
+ instructions += `
45
+ ### PAYLOAD FORMATTING (JSON PARSING PREFERRED)
46
+ You must provide your logic strictly within a JSON string key called \`"logic_blob"\` inside your tool call parameters.
47
+ Example:
48
+ {
49
+ "target": "liop://vault/patients",
50
+ "logic_blob": "const records = await liop.readResource(args.target); return { targetCount: records.filter(r => r.disease === 'Hypertension').length };"
51
+ }
52
+ `;
53
+ }
54
+ return instructions;
55
+ }
package/dist/rpc/proto.js CHANGED
@@ -5,6 +5,7 @@ import * as protoLoader from "@grpc/proto-loader";
5
5
  const __filename = fileURLToPath(import.meta.url);
6
6
  const __dirname = path.dirname(__filename);
7
7
  import * as fs from "node:fs";
8
+ import { log } from "../utils/logger.js";
8
9
  // Selection logic
9
10
  const PROD_PROTO_PATH = path.resolve(__dirname, "../protocol/liop_core.proto");
10
11
  // 2. Fallback to monorepo development path
@@ -14,7 +15,7 @@ const PROTO_PATH = fs.existsSync(PROD_PROTO_PATH)
14
15
  ? PROD_PROTO_PATH
15
16
  : DEV_PROTO_PATH;
16
17
  if (!fs.existsSync(PROTO_PATH)) {
17
- console.error(`[LIOP-Proto] CRITICAL: Proto file not found at ${PROTO_PATH}`);
18
+ log.error(`[LIOP-Proto] CRITICAL: Proto file not found at ${PROTO_PATH}`);
18
19
  }
19
20
  /**
20
21
  * LIOP Proto Loader
@@ -8,6 +8,6 @@ export declare class LiopRpcServer {
8
8
  negotiateIntent: (call: grpc.ServerUnaryCall<IntentRequest, IntentResponse>, callback: grpc.sendUnaryData<IntentResponse>) => void;
9
9
  executeLogic: (call: grpc.ServerWritableStream<LogicRequest, LogicResponse>) => void;
10
10
  }): void;
11
- listen(port?: number, tls?: LiopTlsOptions): Promise<void>;
11
+ listen(port?: number, tls?: LiopTlsOptions): Promise<number>;
12
12
  stop(): Promise<void>;
13
13
  }
@@ -1,4 +1,5 @@
1
1
  import * as grpc from "@grpc/grpc-js";
2
+ import { log } from "../utils/logger.js";
2
3
  import { liopV1 } from "./proto.js";
3
4
  import { createServerCredentials } from "./tls.js";
4
5
  /**
@@ -33,15 +34,15 @@ export class LiopRpcServer {
33
34
  reject(error);
34
35
  return;
35
36
  }
36
- console.error(`[LIOP-RPC] Server listening on port ${assignedPort}`);
37
- resolve();
37
+ log.info(`[LIOP-RPC] Server listening on port ${assignedPort}`);
38
+ resolve(assignedPort);
38
39
  });
39
40
  });
40
41
  }
41
42
  async stop() {
42
43
  return new Promise((resolve) => {
43
44
  this.server.tryShutdown(() => {
44
- console.error("[LIOP-RPC] Server shut down");
45
+ log.info("[LIOP-RPC] Server shut down");
45
46
  resolve();
46
47
  });
47
48
  });
package/dist/rpc/tls.js CHANGED
@@ -7,6 +7,7 @@
7
7
  */
8
8
  import * as fs from "node:fs";
9
9
  import * as grpc from "@grpc/grpc-js";
10
+ import { log } from "../utils/logger.js";
10
11
  /**
11
12
  * Creates gRPC server credentials from TLS options.
12
13
  * Falls back to insecure if no options are provided.
@@ -24,7 +25,7 @@ export function createServerCredentials(tls) {
24
25
  ]);
25
26
  }
26
27
  catch (error) {
27
- console.error(`[LIOP-TLS] Failed to load certificates, falling back to insecure: ${error}`);
28
+ log.info(`[LIOP-TLS] Failed to load certificates, falling back to insecure: ${error}`);
28
29
  return grpc.ServerCredentials.createInsecure();
29
30
  }
30
31
  }
@@ -47,7 +48,7 @@ export function createChannelCredentials(tls) {
47
48
  return grpc.credentials.createSsl(rootCert, privateKey, certChain);
48
49
  }
49
50
  catch (error) {
50
- console.error(`[LIOP-TLS] Failed to load certificates, falling back to insecure: ${error}`);
51
+ log.info(`[LIOP-TLS] Failed to load certificates, falling back to insecure: ${error}`);
51
52
  return grpc.credentials.createInsecure();
52
53
  }
53
54
  }
@@ -26,7 +26,7 @@ export declare class WasiSandbox {
26
26
  * Executes logic (WASM or JS-Wrapped) with hard resource limits.
27
27
  */
28
28
  execute(compiledLogic: Buffer | string, records?: Record<string, unknown>[], inputs?: Record<string, unknown>): Promise<{
29
- output: string;
29
+ output: unknown;
30
30
  fuelConsumed: number;
31
31
  }>;
32
32
  /**
@@ -101,19 +101,60 @@ export class WasiSandbox {
101
101
  else {
102
102
  // Path B: Hardened V8 Isolate Fallback
103
103
  // Uses node:vm with zero-prototype objects to prevent prototype pollution escapes.
104
+ // biome-ignore lint/suspicious/noExplicitAny: Required for Sandbox global poisoning
104
105
  const sandboxEnv = Object.create(null); // Isolated global object
105
106
  const env = { records, ...inputs };
107
+ // Explicitly poison Node.js escape vectors in the context
108
+ sandboxEnv.require = undefined;
109
+ sandboxEnv.process = undefined;
110
+ sandboxEnv.global = undefined;
111
+ sandboxEnv.globalThis = undefined;
112
+ sandboxEnv.Buffer = undefined;
113
+ sandboxEnv.setTimeout = undefined;
114
+ sandboxEnv.setInterval = undefined;
115
+ sandboxEnv.setImmediate = undefined;
116
+ sandboxEnv.queueMicrotask = undefined;
117
+ sandboxEnv.eval = undefined;
118
+ sandboxEnv.Function = undefined;
106
119
  // Inject strictly monitored globals
107
120
  sandboxEnv.records = JSON.parse(JSON.stringify(records)); // Deep copy safety
108
121
  sandboxEnv.env = JSON.parse(JSON.stringify(env));
109
122
  for (const [key, value] of Object.entries(inputs)) {
110
123
  sandboxEnv[key] = JSON.parse(JSON.stringify(value));
111
124
  }
125
+ // Freeze the sandbox context to prevent mutation (SEC-GAP-1)
126
+ // biome-ignore lint/suspicious/noExplicitAny: Required for recursive deep freeze of unknown data
127
+ const deepFreeze = (obj) => {
128
+ if (obj && typeof obj === "object" && !Object.isFrozen(obj)) {
129
+ Object.freeze(obj);
130
+ for (const key of Object.keys(obj)) {
131
+ deepFreeze(obj[key]);
132
+ }
133
+ }
134
+ return obj;
135
+ };
136
+ deepFreeze(sandboxEnv.records);
137
+ deepFreeze(sandboxEnv.env);
138
+ // Prevent property addition/modification on global scope
139
+ for (const key of Object.keys(sandboxEnv)) {
140
+ Object.defineProperty(sandboxEnv, key, {
141
+ writable: false,
142
+ configurable: false,
143
+ });
144
+ }
112
145
  // LIOP Execution Wrapper
146
+ // Host-side logic transformation to avoid 'new Function' in sandbox
147
+ let processedLogic = String(compiledLogic);
148
+ if (/^\s*return\s/m.test(processedLogic) ||
149
+ !processedLogic.includes("function liop_main")) {
150
+ if (!processedLogic.includes("function liop_main")) {
151
+ processedLogic = `function liop_main(env) {\n${processedLogic}\n}`;
152
+ }
153
+ }
113
154
  const scriptCode = `
114
155
  (function() {
115
156
  try {
116
- ${compiledLogic}
157
+ ${processedLogic}
117
158
  if (typeof liop_main === 'function') {
118
159
  return liop_main(env);
119
160
  }
@@ -142,8 +183,7 @@ export class WasiSandbox {
142
183
  if (fuelUsed > 1000000) {
143
184
  throw new Error("LIOP_RESOURCE_EXHAUSTED: Execution fuel limit exceeded.");
144
185
  }
145
- const finalOutput = typeof output === "object" ? JSON.stringify(output) : String(output);
146
- return { output: finalOutput, fuelConsumed: fuelUsed };
186
+ return { output, fuelConsumed: fuelUsed };
147
187
  }
148
188
  catch (error) {
149
189
  throw new Error(`V8 Isolate Fault: ${error instanceof Error ? error.message : "Execution Timeout"}`);
@@ -1,3 +1,4 @@
1
+ import { log } from "../utils/logger.js";
1
2
  /**
2
3
  * Represents a violation of the LIOP Zero-Trust Sandbox policy.
3
4
  */
@@ -22,7 +23,7 @@ export const GuardianTS = {
22
23
  * @throws {GuardianViolationError} If forbidden host imports are detected
23
24
  */
24
25
  async analyzeAst(wasmBytes) {
25
- console.error("[Guardian-TS] Starting Zero-Time AST heuristic inspection...");
26
+ log.info("[Guardian-TS] Starting Zero-Time AST heuristic inspection...");
26
27
  // This throws if the WASM is structurally invalid or a decompression bomb
27
28
  let module;
28
29
  try {
@@ -45,7 +46,7 @@ export const GuardianTS = {
45
46
  }
46
47
  importCount++;
47
48
  }
48
- console.error(`[Guardian-TS] OK: AST clean. Validated ${importCount} WASI/LIOP imports.`);
49
+ log.info(`[Guardian-TS] OK: AST clean. Validated ${importCount} WASI/LIOP imports.`);
49
50
  return module;
50
51
  },
51
52
  };
@@ -18,9 +18,8 @@ export declare class ZkVerificationError extends Error {
18
18
  */
19
19
  export declare const ZkVerifier: {
20
20
  /**
21
- * Mocks the validation of a ZK receipt.
22
- * In a production environment, this would call into the native verifier of the zkVM
23
- * (e.g., RISC Zero's `verify_receipt` FFI binding).
21
+ * Validates a ZK receipt using structural Binary Receipt verification.
22
+ * Parses the HMAC-SHA256 commitment format (v1) and verifies journal integrity.
24
23
  *
25
24
  * @param receipt - Complete ZkReceipt to verify
26
25
  * @param expectedImageId - Hash or ImageID of the WASM file dispatched to the host
@@ -14,9 +14,8 @@ export class ZkVerificationError extends Error {
14
14
  */
15
15
  export const ZkVerifier = {
16
16
  /**
17
- * Mocks the validation of a ZK receipt.
18
- * In a production environment, this would call into the native verifier of the zkVM
19
- * (e.g., RISC Zero's `verify_receipt` FFI binding).
17
+ * Validates a ZK receipt using structural Binary Receipt verification.
18
+ * Parses the HMAC-SHA256 commitment format (v1) and verifies journal integrity.
20
19
  *
21
20
  * @param receipt - Complete ZkReceipt to verify
22
21
  * @param expectedImageId - Hash or ImageID of the WASM file dispatched to the host
@@ -32,12 +31,26 @@ export const ZkVerifier = {
32
31
  if (receipt.proof.length === 0) {
33
32
  throw new ZkVerificationError("Empty or malformed zero-knowledge proof array.");
34
33
  }
35
- // 3. Cryptographic Validation (Mock)
36
- // Here LIOP will bind to Rust/C++ verifiers depending on the chosen zkVM.
37
- // For now, we simulate a constant-time execution check.
38
- const isVerified = crypto.timingSafeEqual(crypto.createHash("sha256").update(receipt.proof).digest(), crypto.createHash("sha256").update(receipt.proof).digest());
39
- if (!isVerified) {
40
- throw new ZkVerificationError("Mathematical proof validation failed.");
34
+ // 3. Cryptographic Validation (Binary Receipt)
35
+ const proofBuf = Buffer.from(receipt.proof);
36
+ if (proofBuf.length < 35 || proofBuf[0] !== 0x01) {
37
+ throw new ZkVerificationError("Malformed receipt: invalid header or length.");
38
+ }
39
+ const journalLen = proofBuf.readUInt16BE(1);
40
+ const journal = proofBuf.subarray(3, 3 + journalLen);
41
+ const seal = proofBuf.subarray(3 + journalLen);
42
+ if (seal.length !== 32) {
43
+ throw new ZkVerificationError("Invalid seal: expected 32-byte HMAC-SHA256.");
44
+ }
45
+ // Verify journal contains matching imageId
46
+ try {
47
+ const journalData = JSON.parse(journal.toString());
48
+ if (journalData.image_id !== receipt.imageId.toString("hex")) {
49
+ throw new ZkVerificationError("Journal imageId does not match receipt header.");
50
+ }
51
+ }
52
+ catch (_e) {
53
+ throw new ZkVerificationError("Failed to parse journal data.");
41
54
  }
42
55
  return true;
43
56
  },
@@ -1,8 +1,8 @@
1
1
  import { z } from "zod";
2
2
  import { MeshNode } from "../mesh/node.js";
3
3
  import type { CallToolRequest, CallToolResult, GetPromptRequest, GetPromptResult, Prompt, Resource, ServerInfo, Tool } from "../types.js";
4
- import { PII_PATTERNS, type PiiRule, PiiScanner } from "./pii.js";
5
- export { PII_PATTERNS, type PiiRule, PiiScanner };
4
+ import { PII_PATTERNS, PII_PRESETS, type PiiRule, PiiScanner } from "./pii.js";
5
+ export { PII_PATTERNS, PII_PRESETS, type PiiRule, PiiScanner };
6
6
  export type ToolHandler<T extends z.ZodRawShape = z.ZodRawShape> = (args: z.infer<z.ZodObject<T>>, extra: {
7
7
  signal?: AbortSignal;
8
8
  }) => Promise<CallToolResult>;
@@ -24,6 +24,27 @@ export interface LiopServerOptions {
24
24
  executionTypes?: string[];
25
25
  };
26
26
  }
27
+ export interface AggregationPolicy {
28
+ /** Maximum number of object-type array elements allowed (default: 10) */
29
+ maxOutputRows?: number;
30
+ /** Allow arrays containing only primitive values (default: true) */
31
+ allowPrimitiveArrays?: boolean;
32
+ }
33
+ export interface LogicExecutionPolicy {
34
+ /**
35
+ * Validate the business payload returned by sandbox logic (post-execution).
36
+ * This runs before final egress checks and blocks non-conforming outputs.
37
+ */
38
+ outputSchema?: z.ZodType<unknown>;
39
+ /**
40
+ * Enforce aggregation-first heuristics (preflight + post-check).
41
+ */
42
+ enforceAggregationFirst?: boolean | AggregationPolicy;
43
+ /**
44
+ * Optional additional deny patterns checked against extracted logic source.
45
+ */
46
+ preflightDenyPatterns?: RegExp[];
47
+ }
27
48
  export declare class LiopServer {
28
49
  private serverInfo;
29
50
  private config?;
@@ -41,10 +62,37 @@ export declare class LiopServer {
41
62
  private workerPool;
42
63
  private meshNode;
43
64
  private rpcServer;
65
+ private boundPort;
44
66
  private sessions;
45
- private static readonly LIOP_LOGIC_REGEX;
67
+ private static readonly LIOP_COMPACT_REGEX;
46
68
  private extractLogic;
69
+ private parseUnknownJson;
70
+ private runPreflightPolicy;
71
+ private validateOutputPolicy;
72
+ /**
73
+ * Proxied tools stringify a full MCP CallToolResult (`{ content: [...] }`).
74
+ * Aggregation-first heuristics must scan the inner business JSON, not the MCP envelope
75
+ * (otherwise `content` looks like a tabular array of objects and everything blocks).
76
+ */
77
+ private unwrapForAggregationPolicyScan;
78
+ private violatesAggregationFirstPolicy;
47
79
  constructor(serverInfo: ServerInfo, config?: LiopServerOptions | undefined);
80
+ /**
81
+ * Builds the centralized LIOP envelope specification document.
82
+ * Served as a single Resource (liop://protocol/envelope-spec) instead
83
+ * of being duplicated across every tool description.
84
+ */
85
+ private buildEnvelopeSpec;
86
+ /**
87
+ * Extracts a compact, human-readable field summary from a JSON Schema.
88
+ *
89
+ * Walks the schema structure to find actual data property names and types,
90
+ * rather than returning top-level schema metadata keys (type, items, etc.).
91
+ *
92
+ * Example output for a banking schema:
93
+ * "Array of {id(string), accountHolder(string), balance(number), transactions(array of {date(string), amount(number)})}"
94
+ */
95
+ private extractSchemaFieldSummary;
48
96
  /**
49
97
  * Convenience alias for connectToMesh(), matching official documentation.
50
98
  */
@@ -59,7 +107,7 @@ export declare class LiopServer {
59
107
  /**
60
108
  * Register a new Tool
61
109
  */
62
- tool<T extends z.ZodRawShape>(name: string, description: string, shape: T, handler: ToolHandler<T>): void;
110
+ tool<T extends z.ZodRawShape>(name: string, description: string, shape: T, handler: ToolHandler<T>, policy?: LogicExecutionPolicy): void;
63
111
  /**
64
112
  * Register a dynamic prompt
65
113
  */
@@ -116,6 +164,7 @@ export declare class LiopServer {
116
164
  * Injects data into the secure sandbox context for Logic-on-Origin tools.
117
165
  */
118
166
  setSandboxData(records: Record<string, unknown>[]): void;
167
+ getBoundPort(): number | null;
119
168
  /**
120
169
  * Connects to the libp2p Kademlia DHT and announces capabilities.
121
170
  * Boots the gRPC server for secure Logic-on-Origin.