enigma-memory 0.1.17 → 0.1.22

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 (290) hide show
  1. package/README.md +85 -27
  2. package/apps/cli/bin/enigma-desktop.mjs +140 -0
  3. package/apps/cli/bin/enigma-terminal.mjs +78 -0
  4. package/apps/cli/bin/enigma.mjs +4979 -3263
  5. package/apps/desktop/electron-main.cjs +217 -0
  6. package/apps/desktop/package.json +12 -0
  7. package/apps/desktop/src/app.js +264 -7
  8. package/apps/desktop/src/index.html +3514 -1373
  9. package/apps/desktop/src/launch-electron.mjs +51 -0
  10. package/apps/desktop/src/server.mjs +2914 -0
  11. package/apps/desktop/src/styles.css +2972 -260
  12. package/apps/desktop/src/zk-browser-prove.mjs +53 -0
  13. package/apps/desktop/src/zk-state.mjs +1789 -0
  14. package/apps/gateway/bin/enigma-gateway.mjs +102 -5
  15. package/apps/gateway/src/server.mjs +271 -8
  16. package/apps/ios/EnigmaCore/Package.swift +12 -0
  17. package/apps/ios/EnigmaCore/Sources/EnigmaCore/EnigmaAPIClient.swift +227 -0
  18. package/apps/ios/EnigmaCore/Sources/EnigmaCore/Models.swift +278 -0
  19. package/apps/ios/EnigmaCore/Sources/EnigmaCore/PKCE.swift +96 -0
  20. package/apps/ios/EnigmaCore/Sources/EnigmaCore/PrivacyMinimizer.swift +187 -0
  21. package/apps/ios/EnigmaCore/Sources/EnigmaCore/ToolModels.swift +129 -0
  22. package/apps/ios/EnigmaCore/Tests/EnigmaCoreTests/EnigmaCoreTests.swift +42 -0
  23. package/apps/ios/EnigmaIOS/Enigma/AppModel.swift +346 -0
  24. package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AccentColor.colorset/Contents.json +12 -0
  25. package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AppIcon.appiconset/Contents.json +11 -0
  26. package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/AppIcon.appiconset/EnigmaAppIcon.png +0 -0
  27. package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/Contents.json +3 -0
  28. package/apps/ios/EnigmaIOS/Enigma/Assets.xcassets/LaunchBackground.colorset/Contents.json +12 -0
  29. package/apps/ios/EnigmaIOS/Enigma/ChatView.swift +181 -0
  30. package/apps/ios/EnigmaIOS/Enigma/CouncilView.swift +78 -0
  31. package/apps/ios/EnigmaIOS/Enigma/CreateView.swift +152 -0
  32. package/apps/ios/EnigmaIOS/Enigma/EnigmaApp.swift +52 -0
  33. package/apps/ios/EnigmaIOS/Enigma/Info.plist +52 -0
  34. package/apps/ios/EnigmaIOS/Enigma/NaturalLanguagePrivacyTagger.swift +26 -0
  35. package/apps/ios/EnigmaIOS/Enigma/OAuthClient.swift +321 -0
  36. package/apps/ios/EnigmaIOS/Enigma/OnboardingView.swift +105 -0
  37. package/apps/ios/EnigmaIOS/Enigma/PrivateVaultView.swift +275 -0
  38. package/apps/ios/EnigmaIOS/Enigma/SecureStore.swift +76 -0
  39. package/apps/ios/EnigmaIOS/Enigma/SettingsView.swift +60 -0
  40. package/apps/ios/EnigmaIOS/Enigma/Theme.swift +80 -0
  41. package/apps/ios/EnigmaIOS/EnigmaIOS.xcodeproj/project.pbxproj +211 -0
  42. package/apps/ios/EnigmaIOS/EnigmaIOS.xcodeproj/xcshareddata/xcschemes/Enigma.xcscheme +23 -0
  43. package/apps/native-host/README.md +19 -8
  44. package/apps/native-host/bin/enigma-native-host.mjs +229 -13
  45. package/apps/relay/bin/enigma-relay.mjs +103 -5
  46. package/apps/relay/src/federation-runtime.mjs +618 -0
  47. package/apps/relay/src/server.mjs +310 -9
  48. package/apps/verifier/bin/enigma-verify.mjs +327 -11
  49. package/cortex-v3/circuits/build/intent_vk_bytes.json +35 -0
  50. package/cortex-v3/circuits/build/sale_vk_bytes.json +35 -0
  51. package/cortex-v3/circuits/build/vk_bytes.json +32 -0
  52. package/cortex-v3/proving-assets.json +64 -0
  53. package/cortex-v3/zk/BUILD-CONTRACT.md +87 -0
  54. package/cortex-v3/zk/action-transition-vk.json +119 -0
  55. package/cortex-v3/zk/alias-adversarial.test.mjs +220 -0
  56. package/cortex-v3/zk/groth16-verify-child.mjs +17 -0
  57. package/cortex-v3/zk/intent-witness.mjs +365 -0
  58. package/cortex-v3/zk/intent-witness.test.mjs +485 -0
  59. package/cortex-v3/zk/proving-assets.mjs +203 -0
  60. package/cortex-v3/zk/sale-witness.mjs +783 -0
  61. package/cortex-v3/zk/sale-witness.test.mjs +784 -0
  62. package/cortex-v3/zk/sealed-sale-release-vk.json +119 -0
  63. package/cortex-v3/zk/settlement-evidence.mjs +722 -0
  64. package/cortex-v3/zk/setup-intent.mjs +688 -0
  65. package/cortex-v3/zk/setup-sale.mjs +666 -0
  66. package/cortex-v3/zk/setup.mjs +594 -0
  67. package/cortex-v3/zk/witness.mjs +184 -0
  68. package/cortex-v3/zk/zk-codec.mjs +232 -0
  69. package/cortex-v3/zk/zk-codec.test.mjs +293 -0
  70. package/cortex-v3/zk/zk-settle.mjs +370 -0
  71. package/cortex-v3/zk/zk-tree.mjs +256 -0
  72. package/cortex-v3/zk/zk-tree.test.mjs +419 -0
  73. package/deploy/SIMULATION.md +14 -9
  74. package/deploy/docker-compose.local-production-simulation.yml +54 -12
  75. package/docs/benchmark-attestation-network.md +487 -487
  76. package/docs/benchmark-reproducibility.md +289 -289
  77. package/docs/blockchain-only-mechanisms.md +400 -400
  78. package/docs/browser-extension-install.md +8 -6
  79. package/docs/client-connectors.md +16 -12
  80. package/docs/demo-proof-network.md +275 -275
  81. package/docs/developer-ecosystem.md +15 -13
  82. package/docs/developer-proof-quickstart.md +325 -325
  83. package/docs/enigma-memory-ready-conformance.md +378 -376
  84. package/docs/install-anywhere.md +64 -30
  85. package/docs/installers-and-desktop.md +8 -7
  86. package/docs/memory-benchmarks.md +1 -1
  87. package/docs/memory-drive-health-model.md +690 -690
  88. package/docs/novelty-invention-candidates.md +161 -161
  89. package/docs/proof-network-build-notes.md +240 -240
  90. package/docs/proof-network-claim-boundaries.md +320 -318
  91. package/docs/proof-network.md +339 -339
  92. package/docs/sdk-api.md +324 -324
  93. package/docs/solana-proof-rail.md +453 -453
  94. package/examples/01-quickstart-agent/index.mjs +49 -0
  95. package/examples/01_agent_memory_quickstart.mjs +57 -0
  96. package/examples/02-multi-agent-swarm/index.mjs +57 -0
  97. package/examples/02_cross_model_passport.mjs +64 -0
  98. package/examples/03-langchain-memory/index.mjs +41 -0
  99. package/examples/03_poseidon_commitment_verification.mjs +71 -0
  100. package/examples/04-python-trading-agent/trader.py +49 -0
  101. package/examples/README.md +27 -0
  102. package/examples/ci/github-actions.yml +7 -2
  103. package/package.json +410 -278
  104. package/packages/adapters/PACKAGE_CONTRACT.md +1 -1
  105. package/packages/connectors/src/index.js +196 -4
  106. package/packages/connectors/swarm-router.mjs +168 -0
  107. package/packages/core/src/index.js +249 -2
  108. package/packages/core/src/version.mjs +7 -0
  109. package/packages/dev-tools/package.json +19 -0
  110. package/packages/dev-tools/src/index.js +4 -0
  111. package/packages/dev-tools/src/memory-benchmark-suite.js +112 -0
  112. package/packages/dev-tools/src/swarm-simulator.js +101 -0
  113. package/packages/dev-tools/src/vault-inspector.js +114 -0
  114. package/packages/dev-tools/src/vector-benchmark.js +100 -0
  115. package/packages/developer-platform/src/access-credentials.js +341 -0
  116. package/packages/developer-platform/src/http.js +132 -0
  117. package/packages/developer-platform/src/index.js +4 -0
  118. package/packages/developer-platform/src/usage-http.js +60 -0
  119. package/packages/developer-platform/src/usage.js +295 -0
  120. package/packages/enclave-runtime/attestation.mjs +159 -0
  121. package/packages/enclave-runtime/index.mjs +47 -0
  122. package/packages/enclave-runtime/session-manager.mjs +253 -0
  123. package/packages/enclave-runtime/zeroization-proof.mjs +227 -0
  124. package/packages/enigma-reflex/package.json +14 -0
  125. package/packages/enigma-reflex/src/index.js +204 -0
  126. package/packages/enigma-reflex/training/generate-dataset.mjs +40 -0
  127. package/packages/enigma-reflex/training/requirements.txt +8 -0
  128. package/packages/enigma-reflex/training/train.py +314 -0
  129. package/packages/enigma-weave/LICENSE +22 -0
  130. package/packages/enigma-weave/UPSTREAM.json +21 -0
  131. package/packages/enigma-weave/package.json +14 -0
  132. package/packages/enigma-weave/src/index.js +286 -0
  133. package/packages/hosted-cloud/src/index.js +80 -5
  134. package/packages/importers/src/index.js +432 -0
  135. package/packages/inference-runtime/src/browser.js +401 -0
  136. package/packages/inference-runtime/src/chat.js +265 -0
  137. package/packages/inference-runtime/src/code.js +407 -0
  138. package/packages/inference-runtime/src/contracts.js +162 -0
  139. package/packages/inference-runtime/src/http.js +232 -0
  140. package/packages/inference-runtime/src/image.js +186 -0
  141. package/packages/inference-runtime/src/index.js +10 -0
  142. package/packages/inference-runtime/src/model-router.js +320 -0
  143. package/packages/inference-runtime/src/platform.js +125 -0
  144. package/packages/inference-runtime/src/privacy.js +400 -0
  145. package/packages/inference-runtime/src/video.js +253 -0
  146. package/packages/mcp-server/README.md +22 -6
  147. package/packages/mcp-server/bin/enigma-mcp.mjs +2 -1
  148. package/packages/mcp-server/src/index.js +2498 -1185
  149. package/packages/mcp-server/src/oauth.js +561 -0
  150. package/packages/mcp-server/src/private-handoff.js +84 -0
  151. package/packages/mcp-server/src/remote-http.js +273 -0
  152. package/packages/mcp-server/src/remote-policy.js +72 -0
  153. package/packages/mcp-server/swarm-bridge.mjs +361 -0
  154. package/packages/mesh/index.d.ts +283 -0
  155. package/packages/mesh/package.json +23 -0
  156. package/packages/mesh/src/crypto.js +189 -0
  157. package/packages/mesh/src/federation-packets.js +353 -0
  158. package/packages/mesh/src/gossip.js +311 -0
  159. package/packages/mesh/src/index.js +6 -0
  160. package/packages/mesh/src/protocol.js +255 -0
  161. package/packages/mesh/src/router.js +279 -0
  162. package/packages/mesh/src/transport.js +306 -0
  163. package/packages/passport/src/index.js +436 -7
  164. package/packages/private-economy/src/credits-http.js +100 -0
  165. package/packages/private-economy/src/credits.js +447 -0
  166. package/packages/private-economy/src/index.js +5 -0
  167. package/packages/private-economy/src/payments-http.js +120 -0
  168. package/packages/private-economy/src/payments.js +509 -0
  169. package/packages/private-economy/src/x402.js +346 -0
  170. package/packages/proof-network/PACKAGE_CONTRACT.md +21 -0
  171. package/packages/rag/index.d.ts +182 -0
  172. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/THIRD_PARTY_LICENSES.txt +207 -0
  173. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/config.json +25 -0
  174. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/onnx/model_quantized.onnx +0 -0
  175. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/sha256-manifest.json +28 -0
  176. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/tokenizer.json +30686 -0
  177. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/tokenizer_config.json +15 -0
  178. package/packages/rag/package.json +27 -0
  179. package/packages/rag/src/blinded-search.js +109 -0
  180. package/packages/rag/src/bm25.js +169 -0
  181. package/packages/rag/src/embeddings.js +459 -0
  182. package/packages/rag/src/hybrid.js +76 -0
  183. package/packages/rag/src/index.js +38 -0
  184. package/packages/rag/src/reranker.js +61 -0
  185. package/packages/rag/src/research.js +107 -0
  186. package/packages/rag/src/vector-store.js +430 -0
  187. package/packages/rag/src/verify-model-artifacts.mjs +4 -0
  188. package/packages/sdk/index.d.ts +760 -0
  189. package/packages/sdk/package.json +33 -0
  190. package/packages/sdk/python/README.md +24 -0
  191. package/packages/sdk/python/enigma_sdk.py +250 -0
  192. package/packages/sdk/python/pyproject.toml +34 -0
  193. package/packages/sdk/python/requirements.txt +1 -0
  194. package/packages/sdk/python/setup.py +20 -0
  195. package/packages/sdk/src/federation/capability-grant.js +389 -0
  196. package/packages/sdk/src/federation/federation-router.js +360 -0
  197. package/packages/sdk/src/federation/ghostmesh-bridge.js +497 -0
  198. package/packages/sdk/src/federation/index.js +3 -0
  199. package/packages/sdk/src/index.js +1796 -0
  200. package/packages/sdk/src/intelligence/contradiction.js +337 -0
  201. package/packages/sdk/src/intelligence/decision-engine.js +155 -0
  202. package/packages/sdk/src/intelligence/index.js +4 -0
  203. package/packages/sdk/src/intelligence/ontology.js +122 -0
  204. package/packages/sdk/src/intelligence/temporal.js +123 -0
  205. package/packages/sdk/src/market-client.js +142 -0
  206. package/packages/sdk/src/mesh-client.js +110 -0
  207. package/packages/sdk/src/middleware/index.js +3 -0
  208. package/packages/sdk/src/middleware/langchain.js +159 -0
  209. package/packages/sdk/src/middleware/llamaindex.js +101 -0
  210. package/packages/sdk/src/middleware/vercel-ai.js +112 -0
  211. package/packages/sdk/src/rag-client.js +85 -0
  212. package/packages/sdk/src/swarm-orchestrator.js +260 -0
  213. package/packages/settlement/PACKAGE_CONTRACT.md +1 -1
  214. package/packages/snapcompact/THIRD_PARTY_LICENSES.txt +40 -0
  215. package/packages/snapcompact/assets/8x13-latin1.bdf +3837 -0
  216. package/packages/snapcompact/index.d.ts +284 -0
  217. package/packages/snapcompact/package.json +25 -0
  218. package/packages/snapcompact/src/index.js +716 -0
  219. package/packages/storage/PACKAGE_CONTRACT.md +1 -1
  220. package/packages/terminal-console/animations.mjs +240 -0
  221. package/packages/terminal-console/auto-anchor.mjs +220 -0
  222. package/packages/terminal-console/banner.mjs +91 -0
  223. package/packages/terminal-console/commands.mjs +459 -0
  224. package/packages/terminal-console/delegation.mjs +152 -0
  225. package/packages/terminal-console/index.mjs +5 -0
  226. package/packages/terminal-console/outbox.mjs +143 -0
  227. package/packages/terminal-console/phantom-bridge.mjs +637 -0
  228. package/packages/terminal-console/repl.mjs +136 -0
  229. package/packages/terminal-console/signer-store.mjs +130 -0
  230. package/packages/terminal-console/solana-rpc.mjs +214 -0
  231. package/packages/terminal-console/solana-transport.mjs +189 -0
  232. package/packages/terminal-tui/dashboard.mjs +214 -0
  233. package/packages/terminal-tui/index.mjs +28 -0
  234. package/packages/terminal-tui/merkle-tree-renderer.mjs +268 -0
  235. package/packages/terminal-tui/telemetry-hud.mjs +137 -0
  236. package/packages/vault/index.d.ts +449 -0
  237. package/packages/vault/package.json +27 -0
  238. package/packages/vault/src/e2ee.mjs +393 -0
  239. package/packages/vault/src/enclave.js +481 -0
  240. package/packages/vault/src/erasure.js +207 -0
  241. package/packages/vault/src/index.js +1150 -125
  242. package/packages/vault/src/persistence.js +307 -0
  243. package/packages/vault/src/poseidon.js +354 -0
  244. package/packages/vault/src/receipt.js +459 -0
  245. package/scripts/benchmark-optical-context.mjs +166 -0
  246. package/scripts/bootstrap-enigma.mjs +502 -0
  247. package/scripts/build-edge-backend-workers.mjs +20 -5
  248. package/scripts/build-goal-completion-audit.mjs +72 -25
  249. package/scripts/build-hosted-api-key-lifecycle.mjs +292 -274
  250. package/scripts/build-hosted-customer-lifecycle.mjs +493 -476
  251. package/scripts/build-hosted-probe-worker.mjs +19 -4
  252. package/scripts/build-installer-assets.mjs +409 -389
  253. package/scripts/build-operator-evidence-starter.mjs +59 -1
  254. package/scripts/build-production-backend-env-kit.mjs +2 -0
  255. package/scripts/build-production-unblocker.mjs +4 -1
  256. package/scripts/build-proof-network-packet.mjs +213 -213
  257. package/scripts/check.mjs +25 -4
  258. package/scripts/collect-hosted-backend-live-evidence.mjs +49 -12
  259. package/scripts/install-enigma-local.mjs +18 -5
  260. package/scripts/release-audit.mjs +74 -115
  261. package/scripts/release-provenance.mjs +12 -2
  262. package/scripts/run-backend-readiness-smoke.mjs +112 -10
  263. package/scripts/run-standard-memory-benchmarks.mjs +1354 -1352
  264. package/scripts/scan-secrets.mjs +178 -0
  265. package/scripts/simulate-production-env.mjs +71 -10
  266. package/scripts/validate-hosted-backend-live.mjs +112 -1
  267. package/specs/antibody-pack-v1.schema.json +95 -0
  268. package/specs/antigen-envelope-v1.schema.json +81 -0
  269. package/specs/boundary-manifest-v1.schema.json +35 -35
  270. package/specs/capsule-v1.schema.json +55 -55
  271. package/specs/claim-boundary-manifest-v1.schema.json +22 -22
  272. package/specs/claim-ledger-v1.schema.json +291 -0
  273. package/specs/context-passport-v1.schema.json +59 -0
  274. package/specs/deletion-tombstone-v1.schema.json +26 -26
  275. package/specs/evidence-packet-v1.schema.json +177 -0
  276. package/specs/hosted-backend-live-evidence-v1.schema.json +72 -3
  277. package/specs/immune-scan-report-v1.schema.json +112 -0
  278. package/specs/lifecycle-receipt-log-v1.schema.json +67 -0
  279. package/specs/memory-atom-v1.schema.json +59 -0
  280. package/specs/memory-event-v1.schema.json +42 -42
  281. package/specs/passport-v1.schema.json +50 -50
  282. package/specs/proof-of-non-use-v1.schema.json +65 -0
  283. package/specs/quarantine-record-v1.schema.json +126 -0
  284. package/specs/receipt-v1.schema.json +61 -61
  285. package/specs/state-checkpoint-v1.schema.json +37 -37
  286. package/specs/trust-bundle-v1.schema.json +56 -56
  287. package/specs/trust-card-v1.schema.json +119 -0
  288. package/docs/proof-network-launch-plan.md +0 -421
  289. package/packages/metering/PACKAGE_CONTRACT.md +0 -20
  290. package/scripts/build-ai-orchestration-plan.mjs +0 -248
@@ -0,0 +1,273 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { createServer } from 'node:http';
3
+ import { isAbsolute, join, relative, resolve } from 'node:path';
4
+ import { requiredScopesForMcpPayload } from './remote-policy.js';
5
+
6
+ const JSON_CONTENT_TYPE = 'application/json';
7
+ const SSE_CONTENT_TYPE = 'text/event-stream';
8
+ const SUPPORTED_PROTOCOL_VERSIONS = new Set(['2024-11-05', '2025-03-26', '2025-06-18']);
9
+
10
+ class HttpMcpError extends Error {
11
+ constructor(status, code, message) {
12
+ super(message);
13
+ this.name = 'HttpMcpError';
14
+ this.status = status;
15
+ this.code = code;
16
+ }
17
+ }
18
+
19
+ function integer(value, name, minimum, maximum, fallback) {
20
+ const resolved = value === undefined ? fallback : value;
21
+ if (!Number.isInteger(resolved) || resolved < minimum || resolved > maximum) {
22
+ throw new TypeError(`${name} must be an integer from ${minimum} through ${maximum}`);
23
+ }
24
+ return resolved;
25
+ }
26
+
27
+ function normalizeEndpoint(value) {
28
+ const endpoint = String(value || '/mcp');
29
+ if (!endpoint.startsWith('/') || endpoint.includes('?') || endpoint.includes('#') || endpoint.includes('..')) {
30
+ throw new TypeError('MCP endpoint must be an absolute path');
31
+ }
32
+ return endpoint.length > 1 ? endpoint.replace(/\/+$/, '') : endpoint;
33
+ }
34
+
35
+ function normalizeAllowedOrigins(values = []) {
36
+ if (!Array.isArray(values)) throw new TypeError('allowedOrigins must be an array');
37
+ return new Set(values.map((value) => {
38
+ const url = new URL(String(value));
39
+ if (url.username || url.password || url.pathname !== '/' || url.search || url.hash) {
40
+ throw new TypeError('allowed MCP origins must contain only scheme, host, and port');
41
+ }
42
+ if (url.protocol !== 'https:' && !(url.protocol === 'http:' && ['127.0.0.1', 'localhost'].includes(url.hostname))) {
43
+ throw new TypeError('allowed MCP origins must use HTTPS outside localhost');
44
+ }
45
+ return url.origin;
46
+ }));
47
+ }
48
+
49
+ function requestUrl(request) {
50
+ const authority = request.headers.host || 'localhost';
51
+ return new URL(request.url || '/', `http://${authority}`);
52
+ }
53
+
54
+ function setSecurityHeaders(response, requestId) {
55
+ response.setHeader('Cache-Control', 'no-store, max-age=0');
56
+ response.setHeader('Cross-Origin-Resource-Policy', 'same-site');
57
+ response.setHeader('Referrer-Policy', 'no-referrer');
58
+ response.setHeader('X-Content-Type-Options', 'nosniff');
59
+ response.setHeader('X-Frame-Options', 'DENY');
60
+ response.setHeader('X-Enigma-Request-Id', requestId);
61
+ }
62
+
63
+ function setCorsHeaders(request, response, allowedOrigins) {
64
+ const origin = request.headers.origin;
65
+ if (!origin) return;
66
+ if (!allowedOrigins.has(origin)) throw new HttpMcpError(403, 'origin_denied', 'request origin is not allowed');
67
+ response.setHeader('Access-Control-Allow-Origin', origin);
68
+ response.setHeader('Access-Control-Allow-Credentials', 'false');
69
+ response.setHeader('Vary', 'Origin');
70
+ }
71
+
72
+ function writeJson(response, status, value) {
73
+ const body = JSON.stringify(value);
74
+ response.statusCode = status;
75
+ response.setHeader('Content-Type', `${JSON_CONTENT_TYPE}; charset=utf-8`);
76
+ response.setHeader('Content-Length', Buffer.byteLength(body));
77
+ response.end(body);
78
+ }
79
+
80
+ function writeSse(response, value) {
81
+ const body = `event: message\ndata: ${JSON.stringify(value)}\n\n`;
82
+ response.statusCode = 200;
83
+ response.setHeader('Content-Type', `${SSE_CONTENT_TYPE}; charset=utf-8`);
84
+ response.setHeader('Content-Length', Buffer.byteLength(body));
85
+ response.setHeader('Connection', 'close');
86
+ response.end(body);
87
+ }
88
+
89
+ async function readJsonBody(request, maxBodyBytes) {
90
+ const contentType = String(request.headers['content-type'] || '').split(';', 1)[0].trim().toLowerCase();
91
+ if (contentType !== JSON_CONTENT_TYPE) throw new HttpMcpError(415, 'unsupported_media_type', 'Content-Type must be application/json');
92
+ const declaredLength = Number(request.headers['content-length']);
93
+ if (Number.isFinite(declaredLength) && declaredLength > maxBodyBytes) {
94
+ request.resume();
95
+ throw new HttpMcpError(413, 'payload_too_large', 'MCP request body exceeds the configured limit');
96
+ }
97
+ const chunks = [];
98
+ let bytes = 0;
99
+ let tooLarge = false;
100
+ for await (const chunk of request) {
101
+ bytes += chunk.length;
102
+ if (bytes > maxBodyBytes) {
103
+ tooLarge = true;
104
+ continue;
105
+ }
106
+ chunks.push(chunk);
107
+ }
108
+ if (tooLarge) throw new HttpMcpError(413, 'payload_too_large', 'MCP request body exceeds the configured limit');
109
+ if (bytes === 0) throw new HttpMcpError(400, 'empty_body', 'MCP request body is required');
110
+ try {
111
+ return JSON.parse(Buffer.concat(chunks, bytes).toString('utf8'));
112
+ } catch {
113
+ throw new HttpMcpError(400, 'parse_error', 'MCP request body is not valid JSON');
114
+ }
115
+ }
116
+
117
+ function accepts(request, mediaType) {
118
+ const header = String(request.headers.accept || '*/*').toLowerCase();
119
+ return header.includes('*/*') || header.includes(mediaType);
120
+ }
121
+
122
+ function bearerChallenge(resourceMetadataUrl, details = {}) {
123
+ const parameters = [];
124
+ if (resourceMetadataUrl) parameters.push(`resource_metadata="${resourceMetadataUrl}"`);
125
+ if (details.error) parameters.push(`error="${details.error}"`);
126
+ if (details.scope) parameters.push(`scope="${details.scope}"`);
127
+ return parameters.length ? `Bearer ${parameters.join(', ')}` : 'Bearer';
128
+ }
129
+
130
+
131
+ export function createSubjectVaultResolver(options = {}) {
132
+ const root = resolve(String(options.root || ''));
133
+ if (!options.root) throw new TypeError('subject vault resolver requires an operator-controlled root');
134
+ const policyId = String(options.policyId || 'remote_oauth');
135
+ return async function resolveSubjectVault(principal) {
136
+ const subject = String(principal?.subject || '').trim();
137
+ const tenant = String(principal?.tenantId || principal?.tenant_id || 'default').trim();
138
+ const clientId = String(principal?.clientId || 'remote-mcp').trim();
139
+ if (!subject || subject.length > 512 || !tenant || tenant.length > 512) throw new Error('authenticated principal cannot be mapped to a vault');
140
+ const tenantRef = createHash('sha256').update(`tenant\\0${tenant}`).digest('hex');
141
+ const subjectRef = createHash('sha256').update(`subject\\0${tenant}\\0${subject}`).digest('hex');
142
+ const actorRef = createHash('sha256').update(`actor\\0${clientId}`).digest('hex');
143
+ const bundlePath = resolve(join(root, tenantRef, subjectRef, 'bundle.json'));
144
+ const relativePath = relative(root, bundlePath);
145
+ if (!relativePath || relativePath.startsWith('..') || isAbsolute(relativePath)) {
146
+ throw new Error('resolved subject vault escaped the configured root');
147
+ }
148
+ return Object.freeze({
149
+ bundlePath,
150
+ tenant_id: `tenant_${tenantRef}`,
151
+ subject_id: `subject_${subjectRef}`,
152
+ actor_id: `actor_${actorRef}`,
153
+ policy_id: policyId,
154
+ });
155
+ };
156
+ }
157
+
158
+ export function createStreamableHttpMcpHandler(options = {}) {
159
+ if (typeof options.rpcHandler !== 'function') throw new TypeError('rpcHandler is required');
160
+ if (typeof options.authorize !== 'function') throw new TypeError('authorize is required for remote MCP');
161
+ const endpoint = normalizeEndpoint(options.endpoint);
162
+ const maxBodyBytes = integer(options.maxBodyBytes, 'maxBodyBytes', 1_024, 8 * 1_024 * 1_024, 1_048_576);
163
+ const allowedOrigins = normalizeAllowedOrigins(options.allowedOrigins || []);
164
+ const resourceMetadataUrl = options.resourceMetadataUrl ? new URL(String(options.resourceMetadataUrl)).toString() : null;
165
+ const resolveVaultContext = typeof options.resolveVaultContext === 'function'
166
+ ? options.resolveVaultContext
167
+ : options.vaultRoot
168
+ ? createSubjectVaultResolver({ root: options.vaultRoot, policyId: options.vaultPolicyId })
169
+ : null;
170
+ if (!resolveVaultContext) throw new TypeError('remote MCP requires resolveVaultContext() or an operator-controlled vaultRoot');
171
+
172
+ return async function streamableHttpMcpHandler(request, response) {
173
+ const requestId = randomUUID();
174
+ setSecurityHeaders(response, requestId);
175
+ try {
176
+ const url = requestUrl(request);
177
+ if (url.pathname !== endpoint || url.search) throw new HttpMcpError(404, 'not_found', 'MCP endpoint not found');
178
+ setCorsHeaders(request, response, allowedOrigins);
179
+
180
+ if (request.method === 'OPTIONS') {
181
+ if (!request.headers.origin) throw new HttpMcpError(400, 'origin_required', 'CORS preflight requires Origin');
182
+ response.statusCode = 204;
183
+ response.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
184
+ response.setHeader('Access-Control-Allow-Headers', 'Authorization, Content-Type, MCP-Protocol-Version');
185
+ response.setHeader('Access-Control-Max-Age', '600');
186
+ response.end();
187
+ return;
188
+ }
189
+ if (request.method !== 'POST') {
190
+ response.setHeader('Allow', 'POST, OPTIONS');
191
+ throw new HttpMcpError(405, 'method_not_allowed', 'stateless MCP accepts POST requests only');
192
+ }
193
+ if (request.headers['mcp-session-id']) {
194
+ throw new HttpMcpError(400, 'unexpected_session', 'this MCP endpoint is stateless and does not issue session identifiers');
195
+ }
196
+ const protocolVersion = request.headers['mcp-protocol-version'];
197
+ if (protocolVersion && !SUPPORTED_PROTOCOL_VERSIONS.has(String(protocolVersion))) {
198
+ throw new HttpMcpError(400, 'unsupported_protocol_version', 'unsupported MCP protocol version');
199
+ }
200
+ if (!accepts(request, JSON_CONTENT_TYPE) && !accepts(request, SSE_CONTENT_TYPE)) {
201
+ throw new HttpMcpError(406, 'not_acceptable', 'Accept must include application/json or text/event-stream');
202
+ }
203
+
204
+ let principal;
205
+ try {
206
+ principal = await options.authorize({
207
+ authorization: request.headers.authorization || null,
208
+ headers: request.headers,
209
+ method: request.method,
210
+ path: url.pathname,
211
+ requestId,
212
+ });
213
+ } catch {
214
+ principal = null;
215
+ }
216
+ if (!principal) {
217
+ response.setHeader('WWW-Authenticate', bearerChallenge(resourceMetadataUrl));
218
+ throw new HttpMcpError(401, 'invalid_token', 'a valid OAuth access token is required');
219
+ }
220
+ const principalScopes = new Set(Array.isArray(principal.scopes) ? principal.scopes : []);
221
+ if (!principalScopes.has('mcp:invoke')) {
222
+ response.setHeader('WWW-Authenticate', bearerChallenge(resourceMetadataUrl, { error: 'insufficient_scope', scope: 'mcp:invoke' }));
223
+ throw new HttpMcpError(403, 'insufficient_scope', 'OAuth token lacks the MCP invocation scope');
224
+ }
225
+
226
+ const payload = await readJsonBody(request, maxBodyBytes);
227
+ const requiredScopes = requiredScopesForMcpPayload(payload);
228
+ const missingScopes = requiredScopes.filter((scope) => !principalScopes.has(scope));
229
+ if (missingScopes.length) {
230
+ response.setHeader('WWW-Authenticate', bearerChallenge(resourceMetadataUrl, { error: 'insufficient_scope', scope: requiredScopes.join(' ') }));
231
+ throw new HttpMcpError(403, 'insufficient_scope', 'OAuth token lacks one or more tool scopes');
232
+ }
233
+ const result = await options.rpcHandler(payload, { principal, requestId, transport: 'streamable-http', resolveVaultContext });
234
+ if (result === undefined) {
235
+ response.statusCode = 202;
236
+ response.end();
237
+ return;
238
+ }
239
+ if (!accepts(request, JSON_CONTENT_TYPE) && accepts(request, SSE_CONTENT_TYPE)) writeSse(response, result);
240
+ else writeJson(response, 200, result);
241
+ } catch (error) {
242
+ if (response.writableEnded) return;
243
+ const status = error instanceof HttpMcpError ? error.status : 500;
244
+ const code = error instanceof HttpMcpError ? error.code : 'internal_error';
245
+ const message = error instanceof HttpMcpError ? error.message : 'internal server error';
246
+ writeJson(response, status, { error: { code, message }, requestId });
247
+ }
248
+ };
249
+ }
250
+
251
+ export async function startStreamableHttpMcpServer(options = {}) {
252
+ const host = String(options.host || '127.0.0.1');
253
+ const port = integer(options.port, 'port', 0, 65_535, 0);
254
+ if (!['127.0.0.1', '::1', 'localhost'].includes(host) && options.allowPublicListener !== true) {
255
+ throw new Error('public MCP listeners require allowPublicListener=true and an external TLS terminator');
256
+ }
257
+ const handler = createStreamableHttpMcpHandler(options);
258
+ const server = createServer((request, response) => {
259
+ handler(request, response).catch(() => {
260
+ if (!response.writableEnded) writeJson(response, 500, { error: { code: 'internal_error', message: 'internal server error' } });
261
+ });
262
+ });
263
+ await new Promise((resolve, reject) => {
264
+ server.once('error', reject);
265
+ server.listen(port, host, resolve);
266
+ });
267
+ const address = server.address();
268
+ return Object.freeze({
269
+ server,
270
+ address,
271
+ close: () => new Promise((resolve, reject) => server.close((error) => error ? reject(error) : resolve())),
272
+ });
273
+ }
@@ -0,0 +1,72 @@
1
+ const VAULT_CUSTODY_FIELDS = Object.freeze(['bundlePath', 'bundle_path', 'insecureDevMode', 'insecure_dev_mode']);
2
+ const VAULT_READ_POLICY_FIELDS = Object.freeze([...VAULT_CUSTODY_FIELDS, 'allowOldEpochReads', 'allow_old_epoch_reads']);
3
+ const VAULT_IDENTITY_FIELDS = Object.freeze([...VAULT_CUSTODY_FIELDS, 'tenant_id', 'subject_id', 'actor_id', 'policy_id']);
4
+
5
+ function policy(scopes = [], options = {}) {
6
+ return Object.freeze({
7
+ requiredScopes: Object.freeze(['mcp:invoke', ...scopes]),
8
+ vaultBinding: options.vaultBinding || 'none',
9
+ tenantBinding: options.tenantBinding || 'none',
10
+ clientForbiddenFields: Object.freeze([...(options.clientForbiddenFields || [])]),
11
+ });
12
+ }
13
+
14
+ export const MCP_REMOTE_TOOL_POLICY = Object.freeze({
15
+ enigma_private_handoff_health: policy(),
16
+ enigma_routing_contract: policy(),
17
+ enigma_start_private_session: policy(),
18
+ enigma_complete: policy(['models:invoke']),
19
+ enigma_generate_image: policy(['images:generate']),
20
+ enigma_init: policy(['memory:write'], { vaultBinding: 'write', tenantBinding: 'inject', clientForbiddenFields: VAULT_IDENTITY_FIELDS }),
21
+ enigma_remember: policy(['memory:write'], { vaultBinding: 'write', clientForbiddenFields: VAULT_CUSTODY_FIELDS }),
22
+ enigma_search: policy(['memory:read'], { vaultBinding: 'read', clientForbiddenFields: VAULT_READ_POLICY_FIELDS }),
23
+ enigma_context_pack: policy(['memory:read'], { vaultBinding: 'read', clientForbiddenFields: VAULT_READ_POLICY_FIELDS }),
24
+ enigma_delete: policy(['memory:delete'], { vaultBinding: 'write', clientForbiddenFields: VAULT_CUSTODY_FIELDS }),
25
+ enigma_x402_execute: policy(['payments:execute']),
26
+ enigma_vault_rotate: policy(['vault:admin'], { vaultBinding: 'admin', clientForbiddenFields: VAULT_CUSTODY_FIELDS }),
27
+ enigma_vault_seal: policy(['vault:admin'], { vaultBinding: 'admin', clientForbiddenFields: VAULT_CUSTODY_FIELDS }),
28
+ enigma_vault_reset: policy(['vault:admin'], { vaultBinding: 'admin', clientForbiddenFields: VAULT_CUSTODY_FIELDS }),
29
+ enigma_verify_receipts: policy(['memory:read'], { vaultBinding: 'read', clientForbiddenFields: ['bundlePath', 'bundle_path'] }),
30
+ enigma_swarm_register_agent: policy(['swarm:write'], { vaultBinding: 'write', clientForbiddenFields: ['bundlePath', 'bundle_path'] }),
31
+ enigma_graph_query: policy(['swarm:read'], { vaultBinding: 'read', clientForbiddenFields: ['bundlePath', 'bundle_path'] }),
32
+ enigma_cluster_memories: policy(['swarm:read'], { vaultBinding: 'read', clientForbiddenFields: ['bundlePath', 'bundle_path'] }),
33
+ enigma_swarm_sync: policy(['swarm:write'], { vaultBinding: 'write', clientForbiddenFields: ['bundlePath', 'bundle_path'] }),
34
+ enigma_immune_ingress: policy(['security:inspect']),
35
+ enigma_meter_usage: policy(['metering:write'], { tenantBinding: 'inject', clientForbiddenFields: ['tenant_id', 'tenantId'] }),
36
+ enigma_settlement_job: policy(['settlement:write'], { tenantBinding: 'inject', clientForbiddenFields: ['tenant_id', 'tenantId'] }),
37
+ enigma_settlement_capacity: policy(['settlement:operator']),
38
+ enigma_settlement_quote: policy(['settlement:write'], { tenantBinding: 'validate_nested' }),
39
+ enigma_settlement_receipt: policy(['settlement:write'], { tenantBinding: 'validate_nested' }),
40
+ enigma_settlement_verify: policy(['settlement:read'], { tenantBinding: 'validate_nested' }),
41
+ enigma_settlement_batch: policy(['settlement:write'], { tenantBinding: 'validate_nested' }),
42
+ enigma_nullifier_record_tombstone: policy(['nullifier:prepare']),
43
+ });
44
+
45
+ export function remoteToolPolicy(name) {
46
+ return Object.prototype.hasOwnProperty.call(MCP_REMOTE_TOOL_POLICY, name) ? MCP_REMOTE_TOOL_POLICY[name] : null;
47
+ }
48
+
49
+ export function assertRemoteToolPolicyCoverage(descriptors) {
50
+ if (!Array.isArray(descriptors)) throw new TypeError('tool descriptors must be an array');
51
+ const descriptorNames = new Set(descriptors.map((descriptor) => descriptor?.name));
52
+ const policyNames = new Set(Object.keys(MCP_REMOTE_TOOL_POLICY));
53
+ const missing = [...descriptorNames].filter((name) => !policyNames.has(name));
54
+ const stale = [...policyNames].filter((name) => !descriptorNames.has(name));
55
+ if (missing.length || stale.length || descriptorNames.has(undefined)) {
56
+ throw new Error(`remote MCP policy coverage mismatch; missing=${missing.join(',') || 'none'} stale=${stale.join(',') || 'none'}`);
57
+ }
58
+ return true;
59
+ }
60
+
61
+ export function requiredScopesForMcpPayload(payload) {
62
+ const required = new Set(['mcp:invoke']);
63
+ const requests = Array.isArray(payload) ? payload : [payload];
64
+ for (const request of requests) {
65
+ if (request?.method !== 'tools/call') continue;
66
+ const name = request?.params?.name;
67
+ const toolPolicy = remoteToolPolicy(name);
68
+ if (!toolPolicy) continue;
69
+ for (const scope of toolPolicy.requiredScopes) required.add(scope);
70
+ }
71
+ return [...required];
72
+ }