@nekzus/liop 1.2.0 → 2.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,19 +4,19 @@
4
4
  <img alt="Logic-Injection-on-Origin Protocol Logo" src="https://res.cloudinary.com/dsvsl0b0b/image/upload/v1774702621/Neural-Mesh-Protocol/hoanw0m6tybpz5fbl12n.svg?v=20260328" width="700">
5
5
  </picture>
6
6
 
7
- <h1>Logic-Injection-on-Origin Protocol (LIOP) — TypeScript SDK</h1>
7
+ <h1>Logic-Injection-on-Origin Protocol (LIOP) — TypeScript SDK</h1>
8
8
  <p align="center">
9
- <a href="https://github.com/Nekzus/Neural-Mesh-Protocol/actions/workflows/ci.yml"><img src="https://github.com/Nekzus/Neural-Mesh-Protocol/actions/workflows/ci.yml/badge.svg?event=push" alt="Github Workflow"></a>
9
+ <a href="https://github.com/Nekzus/LIOP/actions/workflows/ci.yml"><img src="https://github.com/Nekzus/LIOP/actions/workflows/ci.yml/badge.svg?event=push" alt="Github Workflow"></a>
10
10
  <a href="https://www.npmjs.com/package/@nekzus/liop"><img src="https://img.shields.io/npm/v/@nekzus/liop.svg" alt="npm version"></a>
11
11
  <a href="https://www.npmjs.com/package/@nekzus/liop"><img src="https://img.shields.io/npm/dm/@nekzus/liop.svg" alt="npm-month"></a>
12
12
  <a href="https://www.npmjs.com/package/@nekzus/liop"><img src="https://img.shields.io/npm/dt/@nekzus/liop.svg?style=flat" alt="npm-total"></a>
13
- <a href="https://github.com/Nekzus/Neural-Mesh-Protocol/blob/main/LICENSE"><img src="https://img.shields.io/github/license/Nekzus/LIOP.svg" alt="License"></a>
14
- <a href="https://liop.mintlify.app/"><img src="https://img.shields.io/badge/docs-mintlify-0D9373?style=flat" alt="Docs"></a>
13
+ <a href="https://github.com/Nekzus/LIOP/blob/main/LICENSE"><img src="https://img.shields.io/github/license/Nekzus/LIOP.svg" alt="License"></a>
14
+ <a href="https://nekzus-32.mintlify.app/"><img src="https://img.shields.io/badge/docs-mintlify-0D9373?style=flat" alt="Docs"></a>
15
15
  <a href="https://deepwiki.com/Nekzus/LIOP"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
16
16
  <a href="https://paypal.me/maseortega"><img src="https://img.shields.io/badge/donate-paypal-blue.svg?style=flat-square" alt="Donate"></a>
17
17
  </p>
18
18
 
19
- <p><strong>The official TypeScript SDK for the Logic-Injection-on-Origin Protocol.</strong></p>
19
+ <p><strong>The official TypeScript SDK for the Logic-Injection-on-Origin Protocol.</strong></p>
20
20
  <p>Deploy Logic-on-Origin with WebAssembly sandboxing, gRPC-speed execution, and full MCP backward compatibility.</p>
21
21
  </div>
22
22
 
@@ -30,19 +30,19 @@ This fundamentally solves the data privacy, bandwidth, and latency challenges of
30
30
 
31
31
  ### Key Capabilities
32
32
 
33
- | Feature | Description |
34
- |:--|:--|
35
- | **Logic-Injection-on-Origin** | LLMs send code, not queries. Data never leaves the origin server. |
36
- | **MCP Drop-in Replacement** | `LiopServer` mirrors the Anthropic MCP `Server` API — tools, resources, and prompts with `Zod` schemas. |
37
- | **Guardian AST** | Zero-time heuristic inspection blocks sandbox escapes (`require`, `fs`, `eval`, `fetch`, prototype pollution). |
38
- | **WASI Sandbox** | JavaScript payloads execute inside V8 isolates with CPU fuel limits and no access to Node.js globals. |
39
- | **PII Shield** | Multi-layer egress filter with Regional Presets (Email, Credit Card with Luhn, IP, Phone, SSN, IBAN Mod-97, Passport MRZ) and custom keys. |
40
- | **ZK-Receipts** | Cryptographic proof (SHA-256 + SHA-512 seal) that the returned result was computed honestly from the injected logic. |
41
- | **Worker Pool** | Heavy computation (crypto, sandboxing) dispatched to OS threads via `piscina`, unblocking the V8 event loop. |
42
- | **Cross-AI Adapters**| Zero-Shot system prompts automatically adapt instructions for Claude (XML-heavy) vs OpenAI/Gemini (JSON-schema). |
43
- | **MCP Bridge** | `LiopMcpBridge` adapts any `LiopServer` to the JSON-RPC 2.0 / stdio protocol used by Claude Desktop, Cursor, etc. |
44
- | **Post-Quantum Ready** | ML-KEM-768 (Kyber) handshake + AES-256-GCM symmetric encryption for transport-layer security. |
45
- | **P2P Mesh** | Kademlia DHT discovery via `libp2p` with TCP + WebSocket + Yamux multiplexing and Noise encryption. |
33
+ | Feature | Description |
34
+ | :---------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------- |
35
+ | **Logic-Injection-on-Origin** | LLMs send code, not queries. Data never leaves the origin server. |
36
+ | **MCP Drop-in Replacement** | `LiopServer` mirrors the Anthropic MCP `Server` API — tools, resources, and prompts with `Zod` schemas. |
37
+ | **Guardian AST** | Zero-time heuristic inspection blocks sandbox escapes (`require`, `fs`, `eval`, `fetch`, prototype pollution). |
38
+ | **WASI Sandbox** | JavaScript payloads execute inside V8 isolates with CPU fuel limits and no access to Node.js globals. |
39
+ | **PII Shield** | Multi-layer egress filter with Regional Presets (Email, Credit Card with Luhn, IP, Phone, SSN, IBAN Mod-97, Passport MRZ) and custom keys. |
40
+ | **ZK-Receipts** | Cryptographic proof (SHA-256 ImageID + HMAC-SHA256 seal) that the returned result was computed honestly from the injected logic. |
41
+ | **Worker Pool** | Heavy computation (crypto, sandboxing) dispatched to OS threads via `piscina`, unblocking the V8 event loop. |
42
+ | **Cross-AI Adapters** | Zero-Shot system prompts automatically adapt instructions for Claude (XML-heavy) vs OpenAI/Gemini (JSON-schema). |
43
+ | **MCP Bridge** | `LiopMcpBridge` adapts any `LiopServer` to the JSON-RPC 2.0 / stdio protocol used by Claude Desktop, Cursor, etc. |
44
+ | **Post-Quantum Ready** | ML-KEM-768 (Kyber) handshake + AES-256-GCM symmetric encryption for transport-layer security. |
45
+ | **P2P Mesh** | Kademlia DHT discovery via `libp2p` with TCP + WebSocket + Yamux multiplexing and Noise encryption. |
46
46
 
47
47
  ---
48
48
 
@@ -91,6 +91,7 @@ To use the Neural Mesh inside Claude Desktop, update your `claude_desktop_config
91
91
  ### Persistence & Identity
92
92
 
93
93
  The agent automatically manages your P2P identity:
94
+
94
95
  - **Identity Path**: `~/.liop/identity.json`. This file contains your unique PeerID. Keep it safe if you want to maintain a consistent identity in the mesh.
95
96
  - **Bootstrap Nodes**: By default, the agent connects to the **LIOP Alpha Nexus**. You can provide custom bootstrap addresses as CLI arguments:
96
97
  ```bash
@@ -187,9 +188,24 @@ new LiopServer(
187
188
  serverInfo: { name: string; version: string },
188
189
  config?: {
189
190
  capabilities?: Record<string, unknown>;
191
+ workerPool?: {
192
+ enabled?: boolean; // Enable OS-thread sandboxing (default: true)
193
+ maxThreads?: number; // Max worker threads (default: CPU count)
194
+ maxHeapMb?: number; // V8 heap limit per worker (default: 64, env: LIOP_WORKER_MAX_HEAP_MB)
195
+ };
190
196
  security?: {
191
197
  piiPatterns?: PiiRule[]; // Regex/validator rules for PII detection
192
198
  forbiddenKeys?: string[]; // Keys stripped from outgoing responses
199
+ enableNerScanning?: boolean; // NLP entity detection via compromise (default: false)
200
+ rateLimit?: { // Sliding window rate limiter per tool
201
+ maxPerWindow?: number; // Max calls per window (default: 30)
202
+ windowMs?: number; // Window duration in ms (default: 60000)
203
+ };
204
+ };
205
+ taxonomy?: { // Data domain classification
206
+ domain?: string; // e.g., "finance", "healthcare"
207
+ clearanceTier?: string; // e.g., "tier-0", "tier-1"
208
+ executionTypes?: string[]; // e.g., ["aggregation", "analytics"]
193
209
  };
194
210
  }
195
211
  )
@@ -197,24 +213,24 @@ new LiopServer(
197
213
 
198
214
  #### Methods
199
215
 
200
- | Method | Signature | Description |
201
- |:--|:--|:--|
202
- | `tool()` | `(name, description, zodSchema, handler)` | Registers a callable tool with Zod input validation. |
203
- | `prompt()` | `(name, description, args, handler)` | Registers a dynamic prompt template. |
204
- | `resource()` | `(name, uri, description?, mimeType?, content?)` | Registers a readable resource. |
205
- | `dataDictionary()` | `(schema, name?, uri?, description?)` | Broadcasts a data schema so LLMs can write accurate Logic-Injection-on-Origin code. |
206
- | `setSandboxData()` | `(records: Record[])` | Injects data into the sandbox as `env.records` for Logic-on-Origin tools. |
207
- | `enableZeroShotAutonomy()` | `()` | Registers the "Blind Analyst" prompt for autonomous code generation. |
208
- | `callTool()` | `(request: CallToolRequest)` | Invokes a registered tool (used locally or via MCP Bridge). |
209
- | `listTools()` | `()` | Returns all registered tools. |
210
- | `listPrompts()` | `()` | Returns all registered prompts. |
211
- | `getPrompt()` | `(request: GetPromptRequest)` | Returns a specific prompt by name. |
212
- | `listResources()` | `()` | Returns all registered resources. |
213
- | `readResource()` | `(uri: string)` | Reads a resource by URI. |
214
- | `getServerInfo()` | `()` | Returns the server's name and version. |
215
- | `connectToMesh()` | `()` | Connects to the libp2p Kademlia DHT. |
216
- | `clearAstCache()` | `()` | Invalidates the Guardian AST logic cache. |
217
- | `close()` | `()` | Destroys the worker pool and releases threads. |
216
+ | Method | Signature | Description |
217
+ | :--------------------------- | :------------------------------------------------- | :---------------------------------------------------------------------------------- |
218
+ | `tool()` | `(name, description, zodSchema, handler)` | Registers a callable tool with Zod input validation. |
219
+ | `prompt()` | `(name, description, args, handler)` | Registers a dynamic prompt template. |
220
+ | `resource()` | `(name, uri, description?, mimeType?, content?)` | Registers a readable resource. |
221
+ | `dataDictionary()` | `(schema, name?, uri?, description?)` | Broadcasts a data schema so LLMs can write accurate Logic-Injection-on-Origin code. |
222
+ | `setSandboxData()` | `(records: Record[])` | Injects data into the sandbox as `env.records` for Logic-on-Origin tools. |
223
+ | `enableZeroShotAutonomy()` | `()` | Registers the "Blind Analyst" prompt for autonomous code generation. |
224
+ | `callTool()` | `(request: CallToolRequest)` | Invokes a registered tool (used locally or via MCP Bridge). |
225
+ | `listTools()` | `()` | Returns all registered tools. |
226
+ | `listPrompts()` | `()` | Returns all registered prompts. |
227
+ | `getPrompt()` | `(request: GetPromptRequest)` | Returns a specific prompt by name. |
228
+ | `listResources()` | `()` | Returns all registered resources. |
229
+ | `readResource()` | `(uri: string)` | Reads a resource by URI. |
230
+ | `getServerInfo()` | `()` | Returns the server's name and version. |
231
+ | `connectToMesh()` | `()` | Connects to the libp2p Kademlia DHT. |
232
+ | `clearAstCache()` | `()` | Invalidates the Guardian AST logic cache. |
233
+ | `close()` | `()` | Destroys the worker pool and releases threads. |
218
234
 
219
235
  ### `LiopMcpBridge`
220
236
 
@@ -226,6 +242,7 @@ await bridge.connect();
226
242
  ```
227
243
 
228
244
  **Supported JSON-RPC methods:**
245
+
229
246
  - `initialize` — Returns server capabilities and info
230
247
  - `tools/list` — Lists available tools
231
248
  - `tools/call` — Calls a tool (with ZK-Receipt verification)
@@ -241,22 +258,31 @@ await bridge.connect();
241
258
  ### The Shield — Multi-Layer Defense
242
259
 
243
260
  ```
244
- ┌─────────────────────────────────────────────────────┐
245
- │ Layer 1: Guardian AST (Zero-Time Static Analysis)
246
- │ Blocks: require, import(), fs, eval, fetch,
247
- process, global, __proto__, XMLHttpRequest
248
- ├─────────────────────────────────────────────────────┤
249
- │ Layer 2: WASI Sandbox (V8 Isolate)
250
- No Node.js globals CPU Fuel limits 3s timeout
251
- ├─────────────────────────────────────────────────────┤
252
- │ Layer 3: PII Shield (Egress Filter) │
253
- Scans output for Email, SSN, Credit Card, IP
254
- Strips forbidden keys from response objects
255
- ├─────────────────────────────────────────────────────┤
256
- │ Layer 4: ZK-Receipt (Integrity Verification) │
257
- SHA-256 ImageID + SHA-512 RISC0-style Seal
258
- LiopMcpBridge verifies before forwarding to LLM
259
- └─────────────────────────────────────────────────────┘
261
+ ┌───────────────────────────────────────────────────────────┐
262
+ │ Layer 1: Guardian AST (Zero-Time Static Analysis)
263
+ │ Blocks: require, import(), fs, eval, fetch, process,
264
+ │ global, __proto__, XMLHttpRequest • 128 import cap
265
+ ├───────────────────────────────────────────────────────────┤
266
+ │ Layer 2: WASI Sandbox (V8 Isolate)
267
+ 25 poisoned globals (incl. Date, TypedArrays)
268
+ │ CPU Fuel limits • 5s timeout • maxHeapMb (64MB default) │
269
+ ├───────────────────────────────────────────────────────────┤
270
+ Layer 3: Prototype Pollution Defense
271
+ Object.freeze() on 6 core prototypes (Object, Array,
272
+ │ String, Number, Boolean, Function) inside sandbox IIFE │
273
+ ├───────────────────────────────────────────────────────────┤
274
+ Layer 4: PII Shield (Egress Filter)
275
+ Scans output for Email, SSN, Credit Card, IP, IBAN,
276
+ │ Passport MRZ • Strips forbidden keys • NER opt-in │
277
+ ├───────────────────────────────────────────────────────────┤
278
+ │ Layer 5: Aggregation-First Policy │
279
+ │ Blocks raw row export • maxOutputRows (default: 10) • │
280
+ │ Conditional error: detailed (dev) vs opaque (production) │
281
+ ├───────────────────────────────────────────────────────────┤
282
+ │ Layer 6: ZK-Receipt (Integrity Verification) │
283
+ │ SHA-256 ImageID + HMAC-SHA256 Seal (Kyber768-derived) │
284
+ │ LiopMcpBridge verifies before forwarding to LLM │
285
+ └───────────────────────────────────────────────────────────┘
260
286
  ```
261
287
 
262
288
  ### PII Patterns
@@ -388,26 +414,27 @@ await server.connectToMesh();
388
414
 
389
415
  This package is continuously tested across multiple platforms and Node.js versions via CI/CD:
390
416
 
391
- - **51+ tests** spanning unit, integration, and conformance suites
417
+ - **227+ tests** spanning unit, integration, conformance, adversarial, and crossnet suites
392
418
  - **Multi-OS matrix:** Ubuntu, Windows, macOS
393
419
  - **Node.js versions:** 22.x, 24.x
394
420
  - **Code quality:** Enforced by [Biome.js](https://biomejs.dev/) (linting + formatting)
421
+ - **Security:** Verified defense-in-depth architecture — see [Security Architecture](https://nekzus-32.mintlify.app/typescript-sdk/security)
395
422
 
396
- > To run tests locally or contribute, clone the [repository](https://github.com/Nekzus/Neural-Mesh-Protocol) and follow the [Contributing Guide](https://github.com/Nekzus/Neural-Mesh-Protocol/blob/main/CONTRIBUTING.md).
423
+ > To run tests locally or contribute, clone the [repository](https://github.com/Nekzus/LIOP) and follow the [Contributing Guide](https://github.com/Nekzus/LIOP/blob/main/CONTRIBUTING.md).
397
424
 
398
425
  ---
399
426
 
400
427
  ## Related
401
428
 
402
- - [LIOP Documentation](https://liop.mintlify.app/) — Full conceptual and API documentation
403
- - [LIOP Specification](https://github.com/Nekzus/Neural-Mesh-Protocol/blob/main/protocol/SPECIFICATION.md) — Technical specification
404
- - [LIOP Manifesto](https://github.com/Nekzus/Neural-Mesh-Protocol/blob/main/MANIFESTO.md) — Project philosophy
405
- - [Contributing Guide](https://github.com/Nekzus/Neural-Mesh-Protocol/blob/main/CONTRIBUTING.md) — How to contribute
406
- - [Rust Mesh Node](https://github.com/Nekzus/Neural-Mesh-Protocol/tree/main/servers/liop-node) — Native high-performance backend
407
- - [LIOP CLI](https://github.com/Nekzus/Neural-Mesh-Protocol/tree/main/tools/liop-cli) — Developer diagnostics
429
+ - [LIOP Documentation](https://nekzus-32.mintlify.app/) — Full conceptual and API documentation
430
+ - [LIOP Specification](https://github.com/Nekzus/LIOP/blob/main/protocol/SPECIFICATION.md) — Technical specification
431
+ - [LIOP Manifesto](https://github.com/Nekzus/LIOP/blob/main/MANIFESTO.md) — Project philosophy
432
+ - [Contributing Guide](https://github.com/Nekzus/LIOP/blob/main/CONTRIBUTING.md) — How to contribute
433
+ - [Rust Mesh Node](https://github.com/Nekzus/LIOP/tree/main/servers/liop-node) — Native high-performance backend
434
+ - [LIOP CLI](https://github.com/Nekzus/LIOP/tree/main/tools/liop-cli) — Developer diagnostics
408
435
 
409
436
  ---
410
437
 
411
438
  ## License
412
439
 
413
- [MIT](https://github.com/Nekzus/Neural-Mesh-Protocol/blob/main/LICENSE) © [Nekzus](https://github.com/Nekzus)
440
+ [MIT](https://github.com/Nekzus/LIOP/blob/main/LICENSE) © [Nekzus](https://github.com/Nekzus)
@@ -120,16 +120,24 @@ export class LiopStreamBridge {
120
120
  }
121
121
  setupRoutes() {
122
122
  this.app.use("*", cors());
123
+ // Initialize strict zero-trust token if not provided
124
+ if (!process.env.ZERO_TRUST_TOKEN) {
125
+ process.env.ZERO_TRUST_TOKEN = randomUUID();
126
+ log.info("=".repeat(60));
127
+ log.info("⚠️ STRICT ZERO-TRUST MODE ENABLED ⚠️");
128
+ log.info("No ZERO_TRUST_TOKEN found in environment.");
129
+ log.info("A secure ephemeral token has been generated for this session:");
130
+ log.info(`Token: ${process.env.ZERO_TRUST_TOKEN}`);
131
+ log.info("=".repeat(60));
132
+ }
123
133
  // ZTA (Zero-Trust Architecture) Security Middleware
124
134
  this.app.use("/mcp", async (c, next) => {
125
135
  const auth = c.req.header("Authorization");
126
136
  const expectedToken = process.env.ZERO_TRUST_TOKEN;
127
- if (expectedToken) {
128
- if (!auth?.startsWith("Bearer ") ||
129
- auth.split(" ")[1] !== expectedToken) {
130
- log.info("[LIOP-StreamBridge] ALERT: Access denied - Invalid Zero-Trust token.");
131
- return c.json({ error: "Unauthorized: LIOP Zero-Trust Policy Enforced" }, 401);
132
- }
137
+ if (!auth?.startsWith("Bearer ") ||
138
+ auth.split(" ")[1] !== expectedToken) {
139
+ log.info("[LIOP-StreamBridge] ALERT: Access denied - Invalid Zero-Trust token.");
140
+ return c.json({ error: "Unauthorized: LIOP Zero-Trust Policy Enforced" }, 401);
133
141
  }
134
142
  await next();
135
143
  });
@@ -147,19 +147,19 @@ export class LiopClient {
147
147
  const _safePayload = _wasmPayload || Buffer.from("");
148
148
  // Encrypt WASM binary
149
149
  const { ciphertext: encryptedWasm, nonce: aesNonce } = AesGcmWrapper.encryptPayload(_safePayload, sharedSecret);
150
- // Encrypt inputs using the SAME session nonce for the multi-payload request (Standard LIOP V1)
150
+ // Encrypt inputs using a fresh random nonce per input to prevent AES-GCM nonce reuse
151
151
  const encryptedInputs = {};
152
+ const crypto = await import("node:crypto");
152
153
  for (const [key, value] of Object.entries(request.arguments || {})) {
153
- // We manually encrypt with the same nonce/key to match the Proto structure
154
- // ideally we'd have per-field nonces, but for Alpha we follow the liop_core.proto v1.
155
- const crypto = await import("node:crypto");
156
- const cipher = crypto.createCipheriv("aes-256-gcm", sharedSecret, aesNonce);
154
+ const inputNonce = crypto.randomBytes(12);
155
+ const cipher = crypto.createCipheriv("aes-256-gcm", sharedSecret, inputNonce);
157
156
  const encrypted = Buffer.concat([
158
157
  cipher.update(JSON.stringify(value)),
159
158
  cipher.final(),
160
159
  ]);
161
160
  const authTag = cipher.getAuthTag();
162
- encryptedInputs[key] = Buffer.concat([encrypted, authTag]);
161
+ // Prepend the 12-byte nonce to the ciphertext
162
+ encryptedInputs[key] = Buffer.concat([inputNonce, encrypted, authTag]);
163
163
  }
164
164
  // 4. Assemble and Execute gRPC LogicRequest
165
165
  const logicRequest = {
@@ -183,7 +183,7 @@ export class LiopClient {
183
183
  hasReceivedData = true;
184
184
  log.info("[LiopClient] Logic Executed. Verification in progress...");
185
185
  try {
186
- const isValid = await this.verifier.verifyZkReceipt(_safePayload, Buffer.from(response.cryptographic_proof).toString("hex"), Buffer.from(response.zk_receipt));
186
+ const isValid = await this.verifier.verifyZkReceipt(_safePayload, Buffer.from(response.cryptographic_proof).toString("hex"), Buffer.from(response.zk_receipt), Buffer.from(sharedSecret));
187
187
  if (!isValid) {
188
188
  reject(new Error("PROTOCOL INTEGRITY VIOLATION: ZK-Receipt verification failed."));
189
189
  return;
@@ -15,7 +15,7 @@ export declare class LiopVerifier {
15
15
  * @param remoteImageIdHex The ImageID reported by the provider (must match our local calculation).
16
16
  * @param zkReceipt The mathematical proof (Seal + Journal) from the zkVM.
17
17
  */
18
- verifyZkReceipt(logicPayload: Buffer, remoteImageIdHex: string, zkReceipt: Buffer): Promise<boolean>;
18
+ verifyZkReceipt(logicPayload: Buffer, remoteImageIdHex: string, zkReceipt: Buffer, sessionSecret?: Buffer): Promise<boolean>;
19
19
  /**
20
20
  * Verifies if a node is running inside an authenticated TEE (e.g. AWS Nitro).
21
21
  *
@@ -49,7 +49,7 @@ export class LiopVerifier {
49
49
  * @param remoteImageIdHex The ImageID reported by the provider (must match our local calculation).
50
50
  * @param zkReceipt The mathematical proof (Seal + Journal) from the zkVM.
51
51
  */
52
- async verifyZkReceipt(logicPayload, remoteImageIdHex, zkReceipt) {
52
+ async verifyZkReceipt(logicPayload, remoteImageIdHex, zkReceipt, sessionSecret) {
53
53
  const pool = this.getZkPool();
54
54
  if (!pool)
55
55
  throw new Error("Worker pool initialization failed");
@@ -58,6 +58,7 @@ export class LiopVerifier {
58
58
  logicPayload: new Uint8Array(logicPayload),
59
59
  remoteImageIdHex,
60
60
  zkReceipt: new Uint8Array(zkReceipt),
61
+ sessionSecret: sessionSecret ? new Uint8Array(sessionSecret) : undefined,
61
62
  });
62
63
  if (result.verified) {
63
64
  log.info(`[LiopVerifier] ${result.message}`);
@@ -62,6 +62,13 @@ export declare class LiopMcpRouter {
62
62
  * by searching the manifest cache. Supports exact names and suffixed names.
63
63
  */
64
64
  private resolveManifestTarget;
65
+ /**
66
+ * Redacts a PeerID for external-facing diagnostics.
67
+ * LIOP_DIAGNOSTIC_LEVEL controls verbosity:
68
+ * - "redacted" (default): truncated to last 8 chars
69
+ * - "full": complete PeerID (development only)
70
+ */
71
+ private redactPeerId;
65
72
  private transcodeMcpToLiop;
66
73
  private routeToRemoteProvider;
67
74
  private performTranscoding;
@@ -72,6 +72,11 @@ export class LiopMcpRouter {
72
72
  log.info(`[LIOP-Router] Failed to announce manifest: ${err instanceof Error ? err.message : String(err)}`);
73
73
  });
74
74
  }
75
+ // [OWASP-A01] Startup warning when diagnostic level exposes full topology
76
+ if (process.env.LIOP_DIAGNOSTIC_LEVEL === "full") {
77
+ process.stderr.write("⚠️ [LIOP-Security] Diagnostic level set to FULL — " +
78
+ "PeerIDs and network topology are exposed. Do NOT use in production.\n");
79
+ }
75
80
  }
76
81
  shouldSkipManifestQuery(peerId) {
77
82
  const state = this.manifestFailureState.get(peerId);
@@ -691,6 +696,18 @@ export class LiopMcpRouter {
691
696
  }
692
697
  return null;
693
698
  }
699
+ /**
700
+ * Redacts a PeerID for external-facing diagnostics.
701
+ * LIOP_DIAGNOSTIC_LEVEL controls verbosity:
702
+ * - "redacted" (default): truncated to last 8 chars
703
+ * - "full": complete PeerID (development only)
704
+ */
705
+ redactPeerId(peerId) {
706
+ const level = process.env.LIOP_DIAGNOSTIC_LEVEL || "redacted";
707
+ if (level === "full")
708
+ return peerId;
709
+ return `***${peerId.slice(-8)}`;
710
+ }
694
711
  // biome-ignore lint/suspicious/noExplicitAny: MCP JSON-RPC params/id are polymorphic
695
712
  async transcodeMcpToLiop(id, params) {
696
713
  const toolName = params.name;
@@ -724,16 +741,17 @@ export class LiopMcpRouter {
724
741
  .map((addr) => {
725
742
  const parts = addr.split("/");
726
743
  const id = parts[parts.length - 1];
727
- return ` • ${id ? id.slice(-8) : "Unknown"} (${addr})`;
744
+ return ` • ${id ? id.slice(-8) : "Unknown"} (bootstrap)`;
728
745
  })
729
746
  .join("\n");
730
747
  const routingTableSize = this.meshNode
731
748
  ? // biome-ignore lint/suspicious/noExplicitAny: access internal nodes
732
749
  this.meshNode.getRoutingTableSize()
733
750
  : 0;
734
- const localPeerId = this.meshNode?.getPeerId() || "Offline";
751
+ const rawPeerId = this.meshNode?.getPeerId() || "Offline";
752
+ const localPeerId = rawPeerId === "Offline" ? rawPeerId : this.redactPeerId(rawPeerId);
735
753
  const cachedToolList = Array.from(this.manifestCache.entries())
736
- .flatMap(([peerId, { manifest }]) => manifest.tools.map((t) => ` • ${t.name} (from origin: ${peerId})`))
754
+ .flatMap(([peerId, { manifest }]) => manifest.tools.map((t) => ` • ${t.name} (from origin: ${this.redactPeerId(peerId)})`))
737
755
  .join("\n");
738
756
  const statusText = [
739
757
  `LIOP Mesh Status: ${meshState === "Active" ? "Active" : "Offline"}`,
@@ -20,13 +20,36 @@ export const ASTGuardian = {
20
20
  analyze(module) {
21
21
  const imports = WebAssembly.Module.imports(module);
22
22
  let _importCount = 0;
23
+ const ALLOWED_WASI_FUNCTIONS = new Set([
24
+ "fd_write",
25
+ "fd_read",
26
+ "fd_close",
27
+ "fd_seek",
28
+ "environ_get",
29
+ "environ_sizes_get",
30
+ "args_get",
31
+ "args_sizes_get",
32
+ "clock_time_get",
33
+ "random_get",
34
+ "proc_exit",
35
+ "fd_prestat_get",
36
+ "fd_prestat_dir_name",
37
+ "fd_fdstat_get",
38
+ ]);
23
39
  for (const imp of imports) {
24
- // Strict Sandbox Validation: Only allow WASI preview 1 and native LIOP functions.
25
- // Reject any custom or unexpected host imports.
26
- if (imp.module !== "wasi_snapshot_preview1" && imp.module !== "LIOP") {
27
- throw new GuardianError(`Banned Host Import Detected: ${imp.module}/${imp.name}`);
40
+ // Strict Sandbox Validation: Only allow WASI preview 1 specific whitelisted functions.
41
+ if (imp.module === "wasi_snapshot_preview1") {
42
+ if (!ALLOWED_WASI_FUNCTIONS.has(imp.name)) {
43
+ throw new GuardianError(`Banned WASI Import Detected: ${imp.module}/${imp.name}`);
44
+ }
45
+ }
46
+ else {
47
+ throw new GuardianError(`Banned Host Import Module Detected: ${imp.module}`);
28
48
  }
29
49
  _importCount++;
50
+ if (_importCount > 128) {
51
+ throw new GuardianError("Import limit exceeded. Possible resource exhaustion attack.");
52
+ }
30
53
  }
31
54
  // In Node.js / V8, the maximum module size and function limits
32
55
  // are natively enforced by the engine during compilation.
@@ -116,6 +116,24 @@ export class WasiSandbox {
116
116
  sandboxEnv.queueMicrotask = undefined;
117
117
  sandboxEnv.eval = undefined;
118
118
  sandboxEnv.Function = undefined;
119
+ sandboxEnv.SharedArrayBuffer = undefined;
120
+ sandboxEnv.Date = undefined;
121
+ // [DoS Defense] Block off-heap memory allocation vectors.
122
+ // Logic-on-Origin operates on JSON data (env.records) — binary buffers
123
+ // serve no legitimate purpose and enable memory exhaustion DoS.
124
+ // (Uint8Array(2GB) bypassed Piscina's maxOldGenerationSizeMb limit)
125
+ sandboxEnv.ArrayBuffer = undefined;
126
+ sandboxEnv.Uint8Array = undefined;
127
+ sandboxEnv.Int8Array = undefined;
128
+ sandboxEnv.Uint16Array = undefined;
129
+ sandboxEnv.Int16Array = undefined;
130
+ sandboxEnv.Uint32Array = undefined;
131
+ sandboxEnv.Int32Array = undefined;
132
+ sandboxEnv.Float32Array = undefined;
133
+ sandboxEnv.Float64Array = undefined;
134
+ sandboxEnv.BigInt64Array = undefined;
135
+ sandboxEnv.BigUint64Array = undefined;
136
+ sandboxEnv.DataView = undefined;
119
137
  // Inject strictly monitored globals
120
138
  sandboxEnv.records = JSON.parse(JSON.stringify(records)); // Deep copy safety
121
139
  sandboxEnv.env = JSON.parse(JSON.stringify(env));
@@ -154,6 +172,13 @@ export class WasiSandbox {
154
172
  const scriptCode = `
155
173
  (function() {
156
174
  try {
175
+ Object.freeze(Object.prototype);
176
+ Object.freeze(Array.prototype);
177
+ Object.freeze(String.prototype);
178
+ Object.freeze(Number.prototype);
179
+ Object.freeze(Boolean.prototype);
180
+ Object.freeze(Object.getPrototypeOf(function(){}));
181
+
157
182
  ${processedLogic}
158
183
  if (typeof liop_main === 'function') {
159
184
  return liop_main(env);
@@ -26,7 +26,7 @@ export declare const ZkVerifier: {
26
26
  * @throws ZkVerificationError if the proof is invalid or image IDs mismatch
27
27
  * @returns true if the proof mathematically verifies the execution
28
28
  */
29
- verify(receipt: ZkReceipt, expectedImageId: Buffer): boolean;
29
+ verify(receipt: ZkReceipt, expectedImageId: Buffer, sessionSecret?: Buffer): boolean;
30
30
  /**
31
31
  * Derives a predictable ImageID (usually a Hash) from a raw WASM binary.
32
32
  *
@@ -22,7 +22,7 @@ export const ZkVerifier = {
22
22
  * @throws ZkVerificationError if the proof is invalid or image IDs mismatch
23
23
  * @returns true if the proof mathematically verifies the execution
24
24
  */
25
- verify(receipt, expectedImageId) {
25
+ verify(receipt, expectedImageId, sessionSecret) {
26
26
  // 1. Verify Image ID (Ensures the host executed the exact logic we sent, not a malicious one)
27
27
  if (!receipt.imageId.equals(expectedImageId)) {
28
28
  throw new ZkVerificationError("ImageID mismatch. The remote origin executed a different WASM payload.");
@@ -52,6 +52,16 @@ export const ZkVerifier = {
52
52
  catch (_e) {
53
53
  throw new ZkVerificationError("Failed to parse journal data.");
54
54
  }
55
+ // 4. Mathematical Verification (HMAC-SHA256)
56
+ if (sessionSecret && sessionSecret.length > 0) {
57
+ const expectedSeal = crypto
58
+ .createHmac("sha256", sessionSecret)
59
+ .update(journal)
60
+ .digest();
61
+ if (!crypto.timingSafeEqual(seal, expectedSeal)) {
62
+ throw new ZkVerificationError("Invalid seal: HMAC verification failed.");
63
+ }
64
+ }
55
65
  return true;
56
66
  },
57
67
  /**
@@ -1,8 +1,9 @@
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 { NerScanner } from "./ner-scanner.js";
4
5
  import { PII_PATTERNS, PII_PRESETS, type PiiRule, PiiScanner } from "./pii.js";
5
- export { PII_PATTERNS, PII_PRESETS, type PiiRule, PiiScanner };
6
+ export { NerScanner, PII_PATTERNS, PII_PRESETS, type PiiRule, PiiScanner };
6
7
  export type ToolHandler<T extends z.ZodRawShape = z.ZodRawShape> = (args: z.infer<z.ZodObject<T>>, extra: {
7
8
  signal?: AbortSignal;
8
9
  }) => Promise<CallToolResult>;
@@ -13,10 +14,21 @@ export interface LiopServerOptions {
13
14
  minThreads?: number;
14
15
  maxThreads?: number;
15
16
  idleTimeout?: number;
17
+ /** Max heap memory per worker in MB (default: 64). Prevents heap bomb DoS. */
18
+ maxHeapMb?: number;
16
19
  };
17
20
  security?: {
18
21
  piiPatterns?: PiiRule[];
19
22
  forbiddenKeys?: string[];
23
+ /** Enable NLP-based Named Entity Recognition scanning on output values. */
24
+ enableNerScanning?: boolean;
25
+ /** Rate limiting configuration for tool calls (OWASP A01). */
26
+ rateLimit?: {
27
+ /** Maximum calls per window per tool (default: 30). */
28
+ maxPerWindow?: number;
29
+ /** Sliding window duration in milliseconds (default: 60000 = 1 min). */
30
+ windowMs?: number;
31
+ };
20
32
  };
21
33
  taxonomy?: {
22
34
  domain?: string;
@@ -53,6 +65,9 @@ export declare class LiopServer {
53
65
  private readonly CACHE_TTL_MS;
54
66
  private readonly THROTTLE_THRESHOLD;
55
67
  private readonly THROTTLE_COOLDOWN_MS;
68
+ private toolCallWindows;
69
+ private readonly toolCallMaxPerWindow;
70
+ private readonly toolCallWindowMs;
56
71
  private tools;
57
72
  private resources;
58
73
  private prompts;
@@ -128,6 +143,13 @@ export declare class LiopServer {
128
143
  * Manually invalidates the AST Logic Cache (e.g. for Zero-Day patches).
129
144
  */
130
145
  clearAstCache(): void;
146
+ /**
147
+ * Sliding window rate limiter for tool call frequency.
148
+ * Prevents micro-query exfiltration attacks where an attacker
149
+ * makes hundreds of individually-legitimate calls to reconstruct
150
+ * the full dataset field by field. (OWASP A01)
151
+ */
152
+ private checkToolCallRateLimit;
131
153
  /**
132
154
  * Emulates calling a tool (used locally or via LIOPMcpBridge)
133
155
  */