enigma-memory 0.1.18 → 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 (276) hide show
  1. package/README.md +76 -24
  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 +1923 -285
  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/docker-compose.local-production-simulation.yml +36 -0
  74. package/docs/browser-extension-install.md +8 -6
  75. package/docs/client-connectors.md +15 -11
  76. package/docs/developer-ecosystem.md +15 -13
  77. package/docs/enigma-memory-ready-conformance.md +11 -9
  78. package/docs/install-anywhere.md +61 -28
  79. package/docs/installers-and-desktop.md +8 -7
  80. package/docs/novelty-invention-candidates.md +161 -161
  81. package/docs/proof-network-claim-boundaries.md +320 -318
  82. package/examples/01-quickstart-agent/index.mjs +49 -0
  83. package/examples/01_agent_memory_quickstart.mjs +57 -0
  84. package/examples/02-multi-agent-swarm/index.mjs +57 -0
  85. package/examples/02_cross_model_passport.mjs +64 -0
  86. package/examples/03-langchain-memory/index.mjs +41 -0
  87. package/examples/03_poseidon_commitment_verification.mjs +71 -0
  88. package/examples/04-python-trading-agent/trader.py +49 -0
  89. package/examples/README.md +27 -0
  90. package/examples/ci/github-actions.yml +7 -2
  91. package/package.json +142 -11
  92. package/packages/adapters/PACKAGE_CONTRACT.md +1 -1
  93. package/packages/connectors/src/index.js +196 -4
  94. package/packages/connectors/swarm-router.mjs +168 -0
  95. package/packages/core/src/index.js +248 -1
  96. package/packages/core/src/version.mjs +7 -0
  97. package/packages/dev-tools/package.json +19 -0
  98. package/packages/dev-tools/src/index.js +4 -0
  99. package/packages/dev-tools/src/memory-benchmark-suite.js +112 -0
  100. package/packages/dev-tools/src/swarm-simulator.js +101 -0
  101. package/packages/dev-tools/src/vault-inspector.js +114 -0
  102. package/packages/dev-tools/src/vector-benchmark.js +100 -0
  103. package/packages/developer-platform/src/access-credentials.js +341 -0
  104. package/packages/developer-platform/src/http.js +132 -0
  105. package/packages/developer-platform/src/index.js +4 -0
  106. package/packages/developer-platform/src/usage-http.js +60 -0
  107. package/packages/developer-platform/src/usage.js +295 -0
  108. package/packages/enclave-runtime/attestation.mjs +159 -0
  109. package/packages/enclave-runtime/index.mjs +47 -0
  110. package/packages/enclave-runtime/session-manager.mjs +253 -0
  111. package/packages/enclave-runtime/zeroization-proof.mjs +227 -0
  112. package/packages/enigma-reflex/package.json +14 -0
  113. package/packages/enigma-reflex/src/index.js +204 -0
  114. package/packages/enigma-reflex/training/generate-dataset.mjs +40 -0
  115. package/packages/enigma-reflex/training/requirements.txt +8 -0
  116. package/packages/enigma-reflex/training/train.py +314 -0
  117. package/packages/enigma-weave/LICENSE +22 -0
  118. package/packages/enigma-weave/UPSTREAM.json +21 -0
  119. package/packages/enigma-weave/package.json +14 -0
  120. package/packages/enigma-weave/src/index.js +286 -0
  121. package/packages/hosted-cloud/src/index.js +80 -5
  122. package/packages/importers/src/index.js +432 -0
  123. package/packages/inference-runtime/src/browser.js +401 -0
  124. package/packages/inference-runtime/src/chat.js +265 -0
  125. package/packages/inference-runtime/src/code.js +407 -0
  126. package/packages/inference-runtime/src/contracts.js +162 -0
  127. package/packages/inference-runtime/src/http.js +232 -0
  128. package/packages/inference-runtime/src/image.js +186 -0
  129. package/packages/inference-runtime/src/index.js +10 -0
  130. package/packages/inference-runtime/src/model-router.js +320 -0
  131. package/packages/inference-runtime/src/platform.js +125 -0
  132. package/packages/inference-runtime/src/privacy.js +400 -0
  133. package/packages/inference-runtime/src/video.js +253 -0
  134. package/packages/mcp-server/README.md +22 -6
  135. package/packages/mcp-server/bin/enigma-mcp.mjs +2 -1
  136. package/packages/mcp-server/src/index.js +1418 -105
  137. package/packages/mcp-server/src/oauth.js +561 -0
  138. package/packages/mcp-server/src/private-handoff.js +84 -0
  139. package/packages/mcp-server/src/remote-http.js +273 -0
  140. package/packages/mcp-server/src/remote-policy.js +72 -0
  141. package/packages/mcp-server/swarm-bridge.mjs +361 -0
  142. package/packages/mesh/index.d.ts +283 -0
  143. package/packages/mesh/package.json +23 -0
  144. package/packages/mesh/src/crypto.js +189 -0
  145. package/packages/mesh/src/federation-packets.js +353 -0
  146. package/packages/mesh/src/gossip.js +311 -0
  147. package/packages/mesh/src/index.js +6 -0
  148. package/packages/mesh/src/protocol.js +255 -0
  149. package/packages/mesh/src/router.js +279 -0
  150. package/packages/mesh/src/transport.js +306 -0
  151. package/packages/passport/src/index.js +426 -1
  152. package/packages/private-economy/src/credits-http.js +100 -0
  153. package/packages/private-economy/src/credits.js +447 -0
  154. package/packages/private-economy/src/index.js +5 -0
  155. package/packages/private-economy/src/payments-http.js +120 -0
  156. package/packages/private-economy/src/payments.js +509 -0
  157. package/packages/private-economy/src/x402.js +346 -0
  158. package/packages/proof-network/PACKAGE_CONTRACT.md +21 -0
  159. package/packages/rag/index.d.ts +182 -0
  160. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/THIRD_PARTY_LICENSES.txt +207 -0
  161. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/config.json +25 -0
  162. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/onnx/model_quantized.onnx +0 -0
  163. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/sha256-manifest.json +28 -0
  164. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/tokenizer.json +30686 -0
  165. package/packages/rag/models/Xenova/all-MiniLM-L6-v2/tokenizer_config.json +15 -0
  166. package/packages/rag/package.json +27 -0
  167. package/packages/rag/src/blinded-search.js +109 -0
  168. package/packages/rag/src/bm25.js +169 -0
  169. package/packages/rag/src/embeddings.js +459 -0
  170. package/packages/rag/src/hybrid.js +76 -0
  171. package/packages/rag/src/index.js +38 -0
  172. package/packages/rag/src/reranker.js +61 -0
  173. package/packages/rag/src/research.js +107 -0
  174. package/packages/rag/src/vector-store.js +430 -0
  175. package/packages/rag/src/verify-model-artifacts.mjs +4 -0
  176. package/packages/sdk/index.d.ts +760 -0
  177. package/packages/sdk/package.json +33 -0
  178. package/packages/sdk/python/README.md +24 -0
  179. package/packages/sdk/python/enigma_sdk.py +250 -0
  180. package/packages/sdk/python/pyproject.toml +34 -0
  181. package/packages/sdk/python/requirements.txt +1 -0
  182. package/packages/sdk/python/setup.py +20 -0
  183. package/packages/sdk/src/federation/capability-grant.js +389 -0
  184. package/packages/sdk/src/federation/federation-router.js +360 -0
  185. package/packages/sdk/src/federation/ghostmesh-bridge.js +497 -0
  186. package/packages/sdk/src/federation/index.js +3 -0
  187. package/packages/sdk/src/index.js +1796 -0
  188. package/packages/sdk/src/intelligence/contradiction.js +337 -0
  189. package/packages/sdk/src/intelligence/decision-engine.js +155 -0
  190. package/packages/sdk/src/intelligence/index.js +4 -0
  191. package/packages/sdk/src/intelligence/ontology.js +122 -0
  192. package/packages/sdk/src/intelligence/temporal.js +123 -0
  193. package/packages/sdk/src/market-client.js +142 -0
  194. package/packages/sdk/src/mesh-client.js +110 -0
  195. package/packages/sdk/src/middleware/index.js +3 -0
  196. package/packages/sdk/src/middleware/langchain.js +159 -0
  197. package/packages/sdk/src/middleware/llamaindex.js +101 -0
  198. package/packages/sdk/src/middleware/vercel-ai.js +112 -0
  199. package/packages/sdk/src/rag-client.js +85 -0
  200. package/packages/sdk/src/swarm-orchestrator.js +260 -0
  201. package/packages/settlement/PACKAGE_CONTRACT.md +1 -1
  202. package/packages/snapcompact/THIRD_PARTY_LICENSES.txt +40 -0
  203. package/packages/snapcompact/assets/8x13-latin1.bdf +3837 -0
  204. package/packages/snapcompact/index.d.ts +284 -0
  205. package/packages/snapcompact/package.json +25 -0
  206. package/packages/snapcompact/src/index.js +716 -0
  207. package/packages/storage/PACKAGE_CONTRACT.md +1 -1
  208. package/packages/terminal-console/animations.mjs +240 -0
  209. package/packages/terminal-console/auto-anchor.mjs +220 -0
  210. package/packages/terminal-console/banner.mjs +91 -0
  211. package/packages/terminal-console/commands.mjs +459 -0
  212. package/packages/terminal-console/delegation.mjs +152 -0
  213. package/packages/terminal-console/index.mjs +5 -0
  214. package/packages/terminal-console/outbox.mjs +143 -0
  215. package/packages/terminal-console/phantom-bridge.mjs +637 -0
  216. package/packages/terminal-console/repl.mjs +136 -0
  217. package/packages/terminal-console/signer-store.mjs +130 -0
  218. package/packages/terminal-console/solana-rpc.mjs +214 -0
  219. package/packages/terminal-console/solana-transport.mjs +189 -0
  220. package/packages/terminal-tui/dashboard.mjs +214 -0
  221. package/packages/terminal-tui/index.mjs +28 -0
  222. package/packages/terminal-tui/merkle-tree-renderer.mjs +268 -0
  223. package/packages/terminal-tui/telemetry-hud.mjs +137 -0
  224. package/packages/vault/index.d.ts +449 -0
  225. package/packages/vault/package.json +27 -0
  226. package/packages/vault/src/e2ee.mjs +393 -0
  227. package/packages/vault/src/enclave.js +481 -0
  228. package/packages/vault/src/erasure.js +207 -0
  229. package/packages/vault/src/index.js +1018 -155
  230. package/packages/vault/src/persistence.js +307 -0
  231. package/packages/vault/src/poseidon.js +354 -0
  232. package/packages/vault/src/receipt.js +459 -0
  233. package/scripts/benchmark-optical-context.mjs +166 -0
  234. package/scripts/bootstrap-enigma.mjs +502 -0
  235. package/scripts/build-edge-backend-workers.mjs +20 -5
  236. package/scripts/build-goal-completion-audit.mjs +72 -25
  237. package/scripts/build-hosted-api-key-lifecycle.mjs +26 -8
  238. package/scripts/build-hosted-customer-lifecycle.mjs +20 -3
  239. package/scripts/build-hosted-probe-worker.mjs +19 -4
  240. package/scripts/build-installer-assets.mjs +41 -21
  241. package/scripts/build-operator-evidence-starter.mjs +59 -1
  242. package/scripts/build-production-backend-env-kit.mjs +2 -0
  243. package/scripts/build-production-unblocker.mjs +3 -0
  244. package/scripts/check.mjs +17 -3
  245. package/scripts/collect-hosted-backend-live-evidence.mjs +49 -12
  246. package/scripts/install-enigma-local.mjs +18 -5
  247. package/scripts/release-audit.mjs +65 -109
  248. package/scripts/release-provenance.mjs +6 -0
  249. package/scripts/run-backend-readiness-smoke.mjs +112 -10
  250. package/scripts/scan-secrets.mjs +1 -0
  251. package/scripts/simulate-production-env.mjs +7 -2
  252. package/scripts/validate-hosted-backend-live.mjs +112 -1
  253. package/specs/antibody-pack-v1.schema.json +95 -0
  254. package/specs/antigen-envelope-v1.schema.json +81 -0
  255. package/specs/boundary-manifest-v1.schema.json +35 -35
  256. package/specs/capsule-v1.schema.json +55 -55
  257. package/specs/claim-boundary-manifest-v1.schema.json +22 -22
  258. package/specs/claim-ledger-v1.schema.json +291 -0
  259. package/specs/context-passport-v1.schema.json +59 -0
  260. package/specs/deletion-tombstone-v1.schema.json +26 -26
  261. package/specs/evidence-packet-v1.schema.json +177 -0
  262. package/specs/hosted-backend-live-evidence-v1.schema.json +72 -3
  263. package/specs/immune-scan-report-v1.schema.json +112 -0
  264. package/specs/lifecycle-receipt-log-v1.schema.json +67 -0
  265. package/specs/memory-atom-v1.schema.json +59 -0
  266. package/specs/memory-event-v1.schema.json +42 -42
  267. package/specs/passport-v1.schema.json +50 -50
  268. package/specs/proof-of-non-use-v1.schema.json +65 -0
  269. package/specs/quarantine-record-v1.schema.json +126 -0
  270. package/specs/receipt-v1.schema.json +61 -61
  271. package/specs/state-checkpoint-v1.schema.json +37 -37
  272. package/specs/trust-bundle-v1.schema.json +56 -56
  273. package/specs/trust-card-v1.schema.json +119 -0
  274. package/docs/proof-network-launch-plan.md +0 -421
  275. package/packages/metering/PACKAGE_CONTRACT.md +0 -20
  276. package/scripts/build-ai-orchestration-plan.mjs +0 -248
@@ -0,0 +1,211 @@
1
+ // !$*UTF8*$!
2
+ {
3
+ archiveVersion = 1;
4
+ classes = {};
5
+ objectVersion = 60;
6
+ objects = {
7
+
8
+ /* Begin PBXBuildFile section */
9
+ A10000000000000000000001 /* EnigmaApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A20000000000000000000001 /* EnigmaApp.swift */; };
10
+ A10000000000000000000002 /* AppModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A20000000000000000000002 /* AppModel.swift */; };
11
+ A10000000000000000000003 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = A20000000000000000000003 /* Theme.swift */; };
12
+ A10000000000000000000004 /* SecureStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A20000000000000000000004 /* SecureStore.swift */; };
13
+ A10000000000000000000005 /* OAuthClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = A20000000000000000000005 /* OAuthClient.swift */; };
14
+ A10000000000000000000006 /* OnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A20000000000000000000006 /* OnboardingView.swift */; };
15
+ A10000000000000000000007 /* ChatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A20000000000000000000007 /* ChatView.swift */; };
16
+ A10000000000000000000008 /* CouncilView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A20000000000000000000008 /* CouncilView.swift */; };
17
+ A10000000000000000000009 /* CreateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A20000000000000000000009 /* CreateView.swift */; };
18
+ A1000000000000000000000A /* PrivateVaultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2000000000000000000000A /* PrivateVaultView.swift */; };
19
+ A1000000000000000000000B /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2000000000000000000000B /* SettingsView.swift */; };
20
+ A1000000000000000000000E /* NaturalLanguagePrivacyTagger.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2000000000000000000000F /* NaturalLanguagePrivacyTagger.swift */; };
21
+ A1000000000000000000000C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A2000000000000000000000C /* Assets.xcassets */; };
22
+ A1000000000000000000000D /* EnigmaCore in Frameworks */ = {isa = PBXBuildFile; productRef = A90000000000000000000001 /* EnigmaCore */; };
23
+ /* End PBXBuildFile section */
24
+
25
+ /* Begin PBXFileReference section */
26
+ A20000000000000000000001 /* EnigmaApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnigmaApp.swift; sourceTree = "<group>"; };
27
+ A20000000000000000000002 /* AppModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppModel.swift; sourceTree = "<group>"; };
28
+ A20000000000000000000003 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
29
+ A20000000000000000000004 /* SecureStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureStore.swift; sourceTree = "<group>"; };
30
+ A20000000000000000000005 /* OAuthClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthClient.swift; sourceTree = "<group>"; };
31
+ A20000000000000000000006 /* OnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingView.swift; sourceTree = "<group>"; };
32
+ A20000000000000000000007 /* ChatView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatView.swift; sourceTree = "<group>"; };
33
+ A20000000000000000000008 /* CouncilView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CouncilView.swift; sourceTree = "<group>"; };
34
+ A20000000000000000000009 /* CreateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateView.swift; sourceTree = "<group>"; };
35
+ A2000000000000000000000A /* PrivateVaultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivateVaultView.swift; sourceTree = "<group>"; };
36
+ A2000000000000000000000B /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
37
+ A2000000000000000000000F /* NaturalLanguagePrivacyTagger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NaturalLanguagePrivacyTagger.swift; sourceTree = "<group>"; };
38
+ A2000000000000000000000C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
39
+ A2000000000000000000000D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
40
+ A2000000000000000000000E /* Enigma.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Enigma.app; sourceTree = BUILT_PRODUCTS_DIR; };
41
+ /* End PBXFileReference section */
42
+
43
+ /* Begin PBXFrameworksBuildPhase section */
44
+ A30000000000000000000001 /* Frameworks */ = {
45
+ isa = PBXFrameworksBuildPhase;
46
+ buildActionMask = 2147483647;
47
+ files = (A1000000000000000000000D /* EnigmaCore in Frameworks */,);
48
+ runOnlyForDeploymentPostprocessing = 0;
49
+ };
50
+ /* End PBXFrameworksBuildPhase section */
51
+
52
+ /* Begin PBXGroup section */
53
+ A40000000000000000000001 = {
54
+ isa = PBXGroup;
55
+ children = (A40000000000000000000002 /* Enigma */, A40000000000000000000003 /* Products */);
56
+ sourceTree = "<group>";
57
+ };
58
+ A40000000000000000000002 /* Enigma */ = {
59
+ isa = PBXGroup;
60
+ path = Enigma;
61
+ sourceTree = "<group>";
62
+ children = (
63
+ A20000000000000000000001 /* EnigmaApp.swift */,
64
+ A20000000000000000000002 /* AppModel.swift */,
65
+ A20000000000000000000003 /* Theme.swift */,
66
+ A20000000000000000000004 /* SecureStore.swift */,
67
+ A20000000000000000000005 /* OAuthClient.swift */,
68
+ A20000000000000000000006 /* OnboardingView.swift */,
69
+ A20000000000000000000007 /* ChatView.swift */,
70
+ A20000000000000000000008 /* CouncilView.swift */,
71
+ A20000000000000000000009 /* CreateView.swift */,
72
+ A2000000000000000000000A /* PrivateVaultView.swift */,
73
+ A2000000000000000000000B /* SettingsView.swift */,
74
+ A2000000000000000000000F /* NaturalLanguagePrivacyTagger.swift */,
75
+ A2000000000000000000000C /* Assets.xcassets */,
76
+ A2000000000000000000000D /* Info.plist */,
77
+ );
78
+ };
79
+ A40000000000000000000003 /* Products */ = {
80
+ isa = PBXGroup;
81
+ children = (A2000000000000000000000E /* Enigma.app */,);
82
+ name = Products;
83
+ sourceTree = "<group>";
84
+ };
85
+ /* End PBXGroup section */
86
+
87
+ /* Begin PBXNativeTarget section */
88
+ A50000000000000000000001 /* Enigma */ = {
89
+ isa = PBXNativeTarget;
90
+ buildConfigurationList = A80000000000000000000002 /* Build configuration list for PBXNativeTarget Enigma */;
91
+ buildPhases = (A30000000000000000000003 /* Sources */, A30000000000000000000001 /* Frameworks */, A30000000000000000000002 /* Resources */);
92
+ buildRules = ();
93
+ dependencies = ();
94
+ name = Enigma;
95
+ packageProductDependencies = (A90000000000000000000001 /* EnigmaCore */,);
96
+ productName = Enigma;
97
+ productReference = A2000000000000000000000E /* Enigma.app */;
98
+ productType = "com.apple.product-type.application";
99
+ };
100
+ /* End PBXNativeTarget section */
101
+
102
+ /* Begin PBXProject section */
103
+ A60000000000000000000001 /* Project object */ = {
104
+ isa = PBXProject;
105
+ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1600; LastUpgradeCheck = 1600; TargetAttributes = { A50000000000000000000001 = { CreatedOnToolsVersion = 16.0; }; }; };
106
+ buildConfigurationList = A80000000000000000000001 /* Build configuration list for PBXProject EnigmaIOS */;
107
+ compatibilityVersion = "Xcode 15.0";
108
+ developmentRegion = en;
109
+ hasScannedForEncodings = 0;
110
+ knownRegions = (en, Base);
111
+ mainGroup = A40000000000000000000001;
112
+ packageReferences = (A90000000000000000000002 /* XCLocalSwiftPackageReference ../EnigmaCore */,);
113
+ productRefGroup = A40000000000000000000003 /* Products */;
114
+ projectDirPath = "";
115
+ projectRoot = "";
116
+ targets = (A50000000000000000000001 /* Enigma */,);
117
+ };
118
+ /* End PBXProject section */
119
+
120
+ /* Begin PBXResourcesBuildPhase section */
121
+ A30000000000000000000002 /* Resources */ = {
122
+ isa = PBXResourcesBuildPhase;
123
+ buildActionMask = 2147483647;
124
+ files = (A1000000000000000000000C /* Assets.xcassets in Resources */,);
125
+ runOnlyForDeploymentPostprocessing = 0;
126
+ };
127
+ /* End PBXResourcesBuildPhase section */
128
+
129
+ /* Begin PBXSourcesBuildPhase section */
130
+ A30000000000000000000003 /* Sources */ = {
131
+ isa = PBXSourcesBuildPhase;
132
+ buildActionMask = 2147483647;
133
+ files = (
134
+ A10000000000000000000001 /* EnigmaApp.swift in Sources */,
135
+ A10000000000000000000002 /* AppModel.swift in Sources */,
136
+ A10000000000000000000003 /* Theme.swift in Sources */,
137
+ A10000000000000000000004 /* SecureStore.swift in Sources */,
138
+ A10000000000000000000005 /* OAuthClient.swift in Sources */,
139
+ A10000000000000000000006 /* OnboardingView.swift in Sources */,
140
+ A10000000000000000000007 /* ChatView.swift in Sources */,
141
+ A10000000000000000000008 /* CouncilView.swift in Sources */,
142
+ A10000000000000000000009 /* CreateView.swift in Sources */,
143
+ A1000000000000000000000A /* PrivateVaultView.swift in Sources */,
144
+ A1000000000000000000000B /* SettingsView.swift in Sources */,
145
+ A1000000000000000000000E /* NaturalLanguagePrivacyTagger.swift in Sources */,
146
+ );
147
+ runOnlyForDeploymentPostprocessing = 0;
148
+ };
149
+ /* End PBXSourcesBuildPhase section */
150
+
151
+ /* Begin XCBuildConfiguration section */
152
+ A70000000000000000000001 /* Debug */ = {isa = XCBuildConfiguration; buildSettings = {CLANG_ENABLE_MODULES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu17; IPHONEOS_DEPLOYMENT_TARGET = 17.0; SDKROOT = iphoneos; SWIFT_VERSION = 5.0; }; name = Debug; };
153
+ A70000000000000000000002 /* Release */ = {isa = XCBuildConfiguration; buildSettings = {CLANG_ENABLE_MODULES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu17; IPHONEOS_DEPLOYMENT_TARGET = 17.0; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_VERSION = 5.0; VALIDATE_PRODUCT = YES; }; name = Release; };
154
+ A70000000000000000000003 /* Debug */ = {
155
+ isa = XCBuildConfiguration;
156
+ buildSettings = {
157
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
158
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
159
+ CODE_SIGN_STYLE = Automatic;
160
+ CURRENT_PROJECT_VERSION = 1;
161
+ ENABLE_PREVIEWS = YES;
162
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
163
+ INFOPLIST_FILE = Enigma/Info.plist;
164
+ IPHONEOS_DEPLOYMENT_TARGET = 17.0;
165
+ MARKETING_VERSION = 1.0;
166
+ PRODUCT_BUNDLE_IDENTIFIER = com.enigmamemory.ios;
167
+ PRODUCT_NAME = "$(TARGET_NAME)";
168
+ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
169
+ SWIFT_EMIT_LOC_STRINGS = YES;
170
+ SWIFT_VERSION = 5.0;
171
+ TARGETED_DEVICE_FAMILY = "1,2";
172
+ };
173
+ name = Debug;
174
+ };
175
+ A70000000000000000000004 /* Release */ = {
176
+ isa = XCBuildConfiguration;
177
+ buildSettings = {
178
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
179
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
180
+ CODE_SIGN_STYLE = Automatic;
181
+ CURRENT_PROJECT_VERSION = 1;
182
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
183
+ INFOPLIST_FILE = Enigma/Info.plist;
184
+ IPHONEOS_DEPLOYMENT_TARGET = 17.0;
185
+ MARKETING_VERSION = 1.0;
186
+ PRODUCT_BUNDLE_IDENTIFIER = com.enigmamemory.ios;
187
+ PRODUCT_NAME = "$(TARGET_NAME)";
188
+ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
189
+ SWIFT_EMIT_LOC_STRINGS = YES;
190
+ SWIFT_VERSION = 5.0;
191
+ TARGETED_DEVICE_FAMILY = "1,2";
192
+ };
193
+ name = Release;
194
+ };
195
+ /* End XCBuildConfiguration section */
196
+
197
+ /* Begin XCConfigurationList section */
198
+ A80000000000000000000001 /* Build configuration list for PBXProject EnigmaIOS */ = {isa = XCConfigurationList; buildConfigurations = (A70000000000000000000001 /* Debug */, A70000000000000000000002 /* Release */); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; };
199
+ A80000000000000000000002 /* Build configuration list for PBXNativeTarget Enigma */ = {isa = XCConfigurationList; buildConfigurations = (A70000000000000000000003 /* Debug */, A70000000000000000000004 /* Release */); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; };
200
+ /* End XCConfigurationList section */
201
+
202
+ /* Begin XCLocalSwiftPackageReference section */
203
+ A90000000000000000000002 /* XCLocalSwiftPackageReference ../EnigmaCore */ = {isa = XCLocalSwiftPackageReference; relativePath = ../EnigmaCore; };
204
+ /* End XCLocalSwiftPackageReference section */
205
+
206
+ /* Begin XCSwiftPackageProductDependency section */
207
+ A90000000000000000000001 /* EnigmaCore */ = {isa = XCSwiftPackageProductDependency; package = A90000000000000000000002 /* XCLocalSwiftPackageReference ../EnigmaCore */; productName = EnigmaCore; };
208
+ /* End XCSwiftPackageProductDependency section */
209
+ };
210
+ rootObject = A60000000000000000000001 /* Project object */;
211
+ }
@@ -0,0 +1,23 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Scheme LastUpgradeVersion="1600" version="1.7">
3
+ <BuildAction parallelizeBuildables="YES" buildImplicitDependencies="YES">
4
+ <BuildActionEntries>
5
+ <BuildActionEntry buildForTesting="YES" buildForRunning="YES" buildForProfiling="YES" buildForArchiving="YES" buildForAnalyzing="YES">
6
+ <BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="A50000000000000000000001" BuildableName="Enigma.app" BlueprintName="Enigma" ReferencedContainer="container:EnigmaIOS.xcodeproj"/>
7
+ </BuildActionEntry>
8
+ </BuildActionEntries>
9
+ </BuildAction>
10
+ <TestAction buildConfiguration="Debug" selectedDebuggerIdentifier="Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier="Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv="YES"/>
11
+ <LaunchAction buildConfiguration="Debug" selectedDebuggerIdentifier="Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier="Xcode.DebuggerFoundation.Launcher.LLDB" launchStyle="0" useCustomWorkingDirectory="NO" ignoresPersistentStateOnLaunch="NO" debugDocumentVersioning="YES" debugServiceExtension="internal" allowLocationSimulation="YES">
12
+ <BuildableProductRunnable runnableDebuggingMode="0">
13
+ <BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="A50000000000000000000001" BuildableName="Enigma.app" BlueprintName="Enigma" ReferencedContainer="container:EnigmaIOS.xcodeproj"/>
14
+ </BuildableProductRunnable>
15
+ </LaunchAction>
16
+ <ProfileAction buildConfiguration="Release" shouldUseLaunchSchemeArgsEnv="YES" savedToolIdentifier="" useCustomWorkingDirectory="NO" debugDocumentVersioning="YES">
17
+ <BuildableProductRunnable runnableDebuggingMode="0">
18
+ <BuildableReference BuildableIdentifier="primary" BlueprintIdentifier="A50000000000000000000001" BuildableName="Enigma.app" BlueprintName="Enigma" ReferencedContainer="container:EnigmaIOS.xcodeproj"/>
19
+ </BuildableProductRunnable>
20
+ </ProfileAction>
21
+ <AnalyzeAction buildConfiguration="Debug"/>
22
+ <ArchiveAction buildConfiguration="Release" revealArchiveInOrganizer="YES"/>
23
+ </Scheme>
@@ -33,19 +33,28 @@ The CLI manifest generator and install-plan preview are the recommended path bec
33
33
 
34
34
  ```sh
35
35
  mkdir -p "$HOME/.enigma"
36
- enigma init --bundle "$HOME/.enigma/bundle.json" --subject local-user --display-name "Local user"
36
+ ENIGMA_PASSPHRASE_FILE="$HOME/.enigma/passphrase"
37
+ test -s "$ENIGMA_PASSPHRASE_FILE" || { printf '%s\n' 'Create the passphrase file with an approved secret manager or secure editor and restrict it to your user.' >&2; exit 1; }
38
+ enigma init --bundle "$HOME/.enigma/bundle.json" --passphrase-file "$ENIGMA_PASSPHRASE_FILE" --subject local-user --display-name "Local user"
37
39
  export ENIGMA_BUNDLE="$HOME/.enigma/bundle.json"
40
+ export ENIGMA_PASSPHRASE_FILE
38
41
  ```
39
42
 
40
43
  Windows PowerShell:
41
44
 
42
45
  ```powershell
43
46
  New-Item -ItemType Directory -Force "$HOME\.enigma"
44
- enigma init --bundle "$HOME\.enigma\bundle.json" --subject local-user --display-name "Local user"
47
+ $PassphraseFile = "$HOME\.enigma\passphrase"
48
+ if (-not (Test-Path -LiteralPath $PassphraseFile -PathType Leaf)) { throw 'Create the passphrase file with an approved secret manager or secure editor and restrict it to your user.' }
49
+ enigma init --bundle "$HOME\.enigma\bundle.json" --passphrase-file $PassphraseFile --subject local-user --display-name "Local user"
45
50
  [Environment]::SetEnvironmentVariable('ENIGMA_BUNDLE', "$HOME\.enigma\bundle.json", 'User')
51
+ [Environment]::SetEnvironmentVariable('ENIGMA_PASSPHRASE_FILE', $PassphraseFile, 'User')
46
52
  $env:ENIGMA_BUNDLE="$HOME\.enigma\bundle.json"
53
+ $env:ENIGMA_PASSPHRASE_FILE=$PassphraseFile
47
54
  ```
48
55
 
56
+ The native host fails closed for persistent access unless the bundle keyring is protected and the passphrase is supplied out of band. Set `ENIGMA_PASSPHRASE`, set `ENIGMA_PASSPHRASE_FILE`, or start the host with `--passphrase-file <owner-readable-path>`. Passphrases are never accepted as command-line values, and every host write re-exports an encrypted keyring atomically.
57
+
49
58
  3. Resolve the absolute path to the host executable. Native messaging manifests do not expand `~`, `$HOME`, `%USERPROFILE%`, shell aliases, or `PATH` lookups. Use the full executable path, for example:
50
59
 
51
60
  - macOS/Linux: `/Users/REPLACE_WITH_USER/.npm-global/bin/enigma-native-host` or `/usr/local/bin/enigma-native-host`
@@ -53,7 +62,7 @@ The CLI manifest generator and install-plan preview are the recommended path bec
53
62
 
54
63
  Useful checks: `command -v enigma-native-host` on macOS/Linux, or `(Get-Command enigma-native-host.cmd).Source` in Windows PowerShell. If you use a wrapper to set `ENIGMA_BUNDLE`, resolve the wrapper's absolute path instead.
55
64
 
56
- 4. If your browser does not inherit the `ENIGMA_BUNDLE` user environment, create a small local wrapper that sets `ENIGMA_BUNDLE` and then execs the absolute `enigma-native-host` path. Point the manifest `path` to that wrapper. Keep the wrapper owner-writable only.
65
+ 4. If your browser does not inherit `ENIGMA_BUNDLE` and one passphrase source, create a small local wrapper that sets `ENIGMA_BUNDLE` plus `ENIGMA_PASSPHRASE_FILE` and then execs the absolute `enigma-native-host` path. Point the manifest `path` to that wrapper. Keep both the wrapper and passphrase file owner-readable only.
57
66
 
58
67
 
59
68
  ## Fast MCP client setup
@@ -61,16 +70,18 @@ The CLI manifest generator and install-plan preview are the recommended path bec
61
70
  For Claude Desktop, Cursor, Kimi Code, and VS Code Cline, avoid hand-editing MCP JSON. After installing the package, use the CLI to create the local bundle and merge only the Enigma MCP server entry into the selected client config:
62
71
 
63
72
  ```sh
64
- npm install -g enigma-memory && enigma setup --client claude-desktop --write-connectors --overwrite
65
- npm install -g enigma-memory && enigma setup --client cursor --write-connectors --overwrite
66
- npm install -g enigma-memory && enigma setup --client kimi-code --write-connectors --overwrite
67
- npm install -g enigma-memory && enigma setup --client vscode-cline --write-connectors --overwrite
73
+ PASSPHRASE_FILE="$HOME/.enigma/passphrase"
74
+ test -s "$PASSPHRASE_FILE" || { printf '%s\n' 'Create the protected passphrase file before setup.' >&2; exit 1; }
75
+ npm install -g enigma-memory && enigma setup --passphrase-file "$PASSPHRASE_FILE" --client claude-desktop --write-connectors --overwrite
76
+ npm install -g enigma-memory && enigma setup --passphrase-file "$PASSPHRASE_FILE" --client cursor --write-connectors --overwrite
77
+ npm install -g enigma-memory && enigma setup --passphrase-file "$PASSPHRASE_FILE" --client kimi-code --write-connectors --overwrite
78
+ npm install -g enigma-memory && enigma setup --passphrase-file "$PASSPHRASE_FILE" --client vscode-cline --write-connectors --overwrite
68
79
  ```
69
80
 
70
81
  To connect only clients whose config files already exist, use:
71
82
 
72
83
  ```sh
73
- npm install -g enigma-memory && enigma setup --client auto --connect-installed --overwrite
84
+ npm install -g enigma-memory && enigma setup --passphrase-file "$HOME/.enigma/passphrase" --client auto --connect-installed --overwrite
74
85
  ```
75
86
 
76
87
  The generated MCP entry uses `enigma-mcp` with `ENIGMA_BUNDLE` pointing at the local bundle. Existing sibling MCP servers are preserved; changed configs are backed up by `enigma connect`.
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { realpathSync } from 'node:fs';
3
- import { readFile, writeFile } from 'node:fs/promises';
3
+ import { readFile } from 'node:fs/promises';
4
4
  import { isAbsolute, posix, win32 } from 'node:path';
5
5
  import { pathToFileURL } from 'node:url';
6
6
  import { canonicalize, receiptHash, sha256Hex } from '../../../packages/core/src/index.js';
7
7
  import { compileContextPack } from '../../../packages/passport/src/index.js';
8
- import { exportBundle, importBundle } from '../../../packages/vault/src/index.js';
8
+ import { exportBundle, importBundle, remember } from '../../../packages/vault/src/index.js';
9
+ import { readFileRevision, writeJsonFileAtomic } from '../../../packages/vault/src/persistence.js';
9
10
 
10
11
  export const NATIVE_HOST_NAME = 'com.enigma.native_host';
11
12
  export const NATIVE_BROWSER_PROTOCOL = 'enigma.native.browser.v1';
@@ -16,6 +17,7 @@ const CONTEXT_RESPONSE = 'enigma.browser.context.response';
16
17
  const INSERTION_RECORD = 'enigma.browser.insertion.record';
17
18
  const INSERTION_RECORDED = 'enigma.browser.insertion.recorded';
18
19
  const GENERIC_ERROR = 'enigma.native.error';
20
+ const NATIVE_VAULT_CACHE = Symbol('enigma.native.vaultCache');
19
21
  const SHA256_ROOT_RE = /^sha256:[a-f0-9]{64}$/;
20
22
  const SUPPORTED_PROVIDER_IDS = new Set(['chatgpt', 'claude', 'kimi', 'perplexity']);
21
23
  const SAFE_MESSAGE_ID_RE = /^[A-Za-z0-9._:-]{1,80}$/;
@@ -188,6 +190,8 @@ export async function handleNativeBrowserMessage(message, options = {}) {
188
190
  if (message.type === INSERTION_RECORD) return await handleInsertionRecord(message, options);
189
191
  return safeError({ id, type: responseType, code: 'ENIGMA_UNSUPPORTED_REQUEST', message: 'Native host received an unsupported request type.' });
190
192
  } catch {
193
+ const cache = options[NATIVE_VAULT_CACHE];
194
+ if (cache) cache.loaded = undefined;
191
195
  return safeError({ id, type: responseType, code: 'ENIGMA_NATIVE_HOST_ERROR', message: 'Enigma native host failed without exposing local memory.' });
192
196
  }
193
197
  }
@@ -204,9 +208,10 @@ export function createNativeHostRuntime(options = {}) {
204
208
  ...options,
205
209
  argv: options.argv ?? process.argv.slice(2),
206
210
  env: options.env ?? process.env,
211
+ [NATIVE_VAULT_CACHE]: { loaded: undefined, source: undefined },
207
212
  };
208
213
 
209
- async function handleChunk(chunk) {
214
+ async function processChunk(chunk) {
210
215
  pending = pending.length === 0 ? Buffer.from(chunk) : Buffer.concat([pending, Buffer.from(chunk)]);
211
216
  let decoded;
212
217
  try {
@@ -223,10 +228,15 @@ export function createNativeHostRuntime(options = {}) {
223
228
  }
224
229
  }
225
230
 
226
- function onData(chunk) {
227
- queue = queue.then(() => handleChunk(chunk)).catch(() => {
231
+ function handleChunk(chunk) {
232
+ queue = queue.then(() => processChunk(chunk)).catch(() => {
228
233
  stdout.write(encodeNativeMessage(safeError({ type: GENERIC_ERROR, code: 'ENIGMA_NATIVE_HOST_ERROR', message: 'Enigma native host failed without exposing local memory.' })));
229
234
  });
235
+ return queue;
236
+ }
237
+
238
+ function onData(chunk) {
239
+ void handleChunk(chunk);
230
240
  }
231
241
 
232
242
  function onError() {
@@ -256,12 +266,13 @@ function nativeHostUsage() {
256
266
  return {
257
267
  manifest_generator: 'enigma native-host manifest --browser <chrome|edge|firefox> --host-path <absolute path> --extension-id <id> [--out <file>]',
258
268
  install_planner: 'enigma native-host install-plan --browser <chrome|edge|firefox> --manifest <absolute path> [--os <windows|macos|linux>] [--home <absolute path>]',
259
- usage: 'enigma-native-host [--bundle <path>]',
269
+ usage: 'enigma-native-host [--bundle <path>] [--passphrase-file <path>]',
260
270
  native_host: NATIVE_HOST_NAME,
261
271
  protocol: NATIVE_BROWSER_PROTOCOL,
262
272
  transport: 'Chrome/Edge/Firefox native messaging: 4-byte little-endian length-prefixed JSON over stdio.',
263
273
  options: {
264
274
  '--bundle <path>': 'Local Enigma bundle path. Defaults to ENIGMA_BUNDLE.',
275
+ '--passphrase-file <path>': 'Owner-readable passphrase file. Defaults to ENIGMA_PASSPHRASE_FILE; ENIGMA_PASSPHRASE is also accepted.',
265
276
  '--help': 'Print this JSON help and exit without starting the native messaging loop.',
266
277
  },
267
278
  claim_boundaries: 'The native host reads local Enigma bundles and returns user-approved context plus receipt summaries. It does not prove provider deletion, model forgetting, or provider-side memory behavior.',
@@ -290,6 +301,42 @@ async function handleContextRequest(message, options) {
290
301
  const loaded = await loadVault(options);
291
302
  if (!loaded.ok) return safeError({ id, type: CONTEXT_RESPONSE, ...loaded.error });
292
303
 
304
+ const selection = selectedBrowserContext(message);
305
+ let selectionMemoryAddr;
306
+ if (selection) {
307
+ const memoryOperation = typeof options.memoryOperation === 'function' ? options.memoryOperation : remember;
308
+ const memoryResult = await memoryOperation({
309
+ vault: loaded.vault,
310
+ content: selection.text,
311
+ kind: 'browser_selection',
312
+ confidence: 'user_confirmed',
313
+ sensitivity: 'sensitive',
314
+ purpose_tags: ['browser_context'],
315
+ source_refs: [{
316
+ type: 'browser_selection',
317
+ provider: selection.provider,
318
+ origin_commitment: selection.page.origin_commitment,
319
+ metadata_commitment: selection.page.metadata_commitment,
320
+ }],
321
+ metadata: {
322
+ browser_provider: selection.provider,
323
+ browser_selection_source: selection.source,
324
+ page_origin_commitment: selection.page.origin_commitment,
325
+ page_hostname_commitment: selection.page.hostname_commitment,
326
+ page_metadata_commitment: selection.page.metadata_commitment,
327
+ page_title_present: selection.page.raw.display.titlePresent,
328
+ page_title_char_count: selection.page.raw.display.titleCharCount,
329
+ page_top_level: selection.page.topLevel,
330
+ },
331
+ browser_context: {
332
+ page: selection.page.raw,
333
+ selection: { source: selection.source },
334
+ },
335
+ now: options.now,
336
+ });
337
+ selectionMemoryAddr = typeof memoryResult?.memory_addr === 'string' ? memoryResult.memory_addr : undefined;
338
+ }
339
+
293
340
  const activeAddresses = [...(loaded.vault.activeAddresses ?? [])];
294
341
  if (activeAddresses.length === 0) {
295
342
  return safeError({
@@ -300,11 +347,16 @@ async function handleContextRequest(message, options) {
300
347
  action: 'Run enigma remember, then retry from the browser extension.',
301
348
  });
302
349
  }
350
+ const orderedAddresses = selectionMemoryAddr && activeAddresses.includes(selectionMemoryAddr)
351
+ ? [selectionMemoryAddr, ...activeAddresses.filter((address) => address !== selectionMemoryAddr)]
352
+ : undefined;
303
353
 
304
354
  const contextPack = compileContextPack({
305
355
  vault: loaded.vault,
356
+ memory_addresses: orderedAddresses,
306
357
  provider: safeProvider(message.provider),
307
358
  purpose: 'browser_context_injection',
359
+ query: selection?.text ?? '',
308
360
  limit: options.limit ?? options.maxMemories ?? 12,
309
361
  now: options.now,
310
362
  });
@@ -366,10 +418,46 @@ async function handleInsertionRecord(message, options) {
366
418
  }
367
419
 
368
420
  async function loadVault(options) {
369
- if (options.vault) return { ok: true, vault: options.vault, bundlePath: options.bundlePath, source: 'options.vault' };
421
+ const cache = options[NATIVE_VAULT_CACHE];
422
+ const importOperation = typeof options.importOperation === 'function' ? options.importOperation : importBundle;
423
+
424
+ if (options.vault) {
425
+ if (cache?.source === options.vault && cache.loaded) return cache.loaded;
426
+ const passphraseResult = await resolveNativePassphrase(options);
427
+ if (!passphraseResult.ok) return passphraseResult;
428
+ if (options.persist !== false && options.bundlePath && !passphraseResult.passphrase) return missingPassphraseResult();
429
+ const loaded = {
430
+ ok: true,
431
+ vault: options.vault,
432
+ bundlePath: options.bundlePath,
433
+ passphrase: passphraseResult.passphrase,
434
+ source: 'options.vault',
435
+ };
436
+ if (cache) {
437
+ cache.source = options.vault;
438
+ cache.loaded = loaded;
439
+ }
440
+ return loaded;
441
+ }
442
+
370
443
  if (options.bundle) {
444
+ if (cache?.source === options.bundle && cache.loaded) return cache.loaded;
445
+ const passphraseResult = await resolveNativePassphrase(options);
446
+ if (!passphraseResult.ok) return passphraseResult;
447
+ if (bundleNeedsPassphrase(options.bundle, options) && !passphraseResult.passphrase) return missingPassphraseResult();
371
448
  try {
372
- return { ok: true, ...importBundle({ bundle: options.bundle }), bundlePath: options.bundlePath, source: 'options.bundle' };
449
+ const loaded = {
450
+ ok: true,
451
+ ...importOperation({ bundle: options.bundle, passphrase: passphraseResult.passphrase, strict: bundleNeedsPassphrase(options.bundle, options) }),
452
+ bundlePath: options.bundlePath,
453
+ passphrase: passphraseResult.passphrase,
454
+ source: 'options.bundle',
455
+ };
456
+ if (cache) {
457
+ cache.source = options.bundle;
458
+ cache.loaded = loaded;
459
+ }
460
+ return loaded;
373
461
  } catch {
374
462
  return { ok: false, error: invalidBundleError() };
375
463
  }
@@ -388,8 +476,26 @@ async function loadVault(options) {
388
476
  }
389
477
 
390
478
  try {
391
- const bundle = JSON.parse(await readFile(bundlePath, 'utf8'));
392
- return { ok: true, ...importBundle({ bundle }), bundlePath, source: 'bundlePath' };
479
+ const snapshot = await readFileRevision(bundlePath);
480
+ if (cache?.source === bundlePath && cache.loaded?.revision === snapshot.revision) return cache.loaded;
481
+ if (cache?.source === bundlePath) cache.loaded = undefined;
482
+ const bundle = JSON.parse(snapshot.raw.toString('utf8'));
483
+ const passphraseResult = await resolveNativePassphrase(options);
484
+ if (!passphraseResult.ok) return passphraseResult;
485
+ if (bundleNeedsPassphrase(bundle, options) && !passphraseResult.passphrase) return missingPassphraseResult();
486
+ const loaded = {
487
+ ok: true,
488
+ ...importOperation({ bundle, passphrase: passphraseResult.passphrase, strict: bundleNeedsPassphrase(bundle, options) }),
489
+ bundlePath,
490
+ passphrase: passphraseResult.passphrase,
491
+ revision: snapshot.revision,
492
+ source: 'bundlePath',
493
+ };
494
+ if (cache) {
495
+ cache.source = bundlePath;
496
+ cache.loaded = loaded;
497
+ }
498
+ return loaded;
393
499
  } catch {
394
500
  return { ok: false, error: invalidBundleError() };
395
501
  }
@@ -397,15 +503,86 @@ async function loadVault(options) {
397
503
 
398
504
  async function persistVault(loaded, options) {
399
505
  if (options.persist === false || !loaded.bundlePath || !loaded.vault) return;
400
- const bundle = exportBundle({ vault: loaded.vault, now: options.now });
401
- await writeFile(loaded.bundlePath, `${JSON.stringify(bundle, null, 2)}\n`);
506
+ if (!loaded.passphrase) throw new Error('Native host persistence requires a passphrase.');
507
+ try {
508
+ const bundle = exportBundle({ vault: loaded.vault, passphrase: loaded.passphrase, now: options.now });
509
+ const persisted = await writeJsonFileAtomic(loaded.bundlePath, bundle, {
510
+ ...(loaded.revision ? { expectedRevision: loaded.revision } : {}),
511
+ });
512
+ loaded.revision = persisted.revision;
513
+ } catch (error) {
514
+ const cache = options[NATIVE_VAULT_CACHE];
515
+ if (cache?.loaded === loaded) cache.loaded = undefined;
516
+ throw error;
517
+ }
518
+ }
519
+
520
+ function missingPassphraseResult() {
521
+ return {
522
+ ok: false,
523
+ error: {
524
+ code: 'ENIGMA_PASSPHRASE_REQUIRED',
525
+ message: 'Enigma native host requires ENIGMA_PASSPHRASE or --passphrase-file for persistent bundle access.',
526
+ action: 'Set ENIGMA_PASSPHRASE in the native host environment or pass --passphrase-file with an owner-readable secret file.',
527
+ },
528
+ };
529
+ }
530
+
531
+ function bundleNeedsPassphrase(bundle, options) {
532
+ return options.persist !== false || bundle?.keyring?.type === 'local_secret_encrypted';
533
+ }
534
+
535
+ async function resolveNativePassphrase(options) {
536
+ const env = options.env && typeof options.env === 'object' ? options.env : {};
537
+ const envPassphrase = typeof env.ENIGMA_PASSPHRASE === 'string' && env.ENIGMA_PASSPHRASE.trim().length > 0
538
+ ? env.ENIGMA_PASSPHRASE
539
+ : undefined;
540
+ const passphraseFile = passphraseFileFromOptions(options);
541
+ if (!passphraseFile) return { ok: true, passphrase: envPassphrase };
542
+
543
+ let filePassphrase;
544
+ try {
545
+ filePassphrase = (await readFile(passphraseFile, 'utf8')).replace(/[\r\n]+$/u, '');
546
+ } catch {
547
+ return {
548
+ ok: false,
549
+ error: {
550
+ code: 'ENIGMA_PASSPHRASE_FILE_INVALID',
551
+ message: 'Enigma native host could not read the configured passphrase file.',
552
+ action: 'Check --passphrase-file permissions and provide a non-empty passphrase file.',
553
+ },
554
+ };
555
+ }
556
+ if (filePassphrase.trim().length === 0 || (envPassphrase !== undefined && envPassphrase !== filePassphrase)) {
557
+ return {
558
+ ok: false,
559
+ error: {
560
+ code: 'ENIGMA_PASSPHRASE_CONFLICT',
561
+ message: 'Enigma native host passphrase sources are empty or conflicting.',
562
+ action: 'Use one non-empty passphrase source, or make ENIGMA_PASSPHRASE match --passphrase-file.',
563
+ },
564
+ };
565
+ }
566
+ return { ok: true, passphrase: filePassphrase };
567
+ }
568
+
569
+ function passphraseFileFromOptions(options) {
570
+ const argv = Array.isArray(options.argv) ? options.argv : [];
571
+ for (let index = 0; index < argv.length; index += 1) {
572
+ if (argv[index] === '--passphrase-file' && typeof argv[index + 1] === 'string' && argv[index + 1].length > 0) return argv[index + 1];
573
+ if (argv[index]?.startsWith('--passphrase-file=')) return argv[index].slice('--passphrase-file='.length);
574
+ }
575
+ const env = options.env && typeof options.env === 'object' ? options.env : {};
576
+ return typeof env.ENIGMA_PASSPHRASE_FILE === 'string' && env.ENIGMA_PASSPHRASE_FILE.length > 0
577
+ ? env.ENIGMA_PASSPHRASE_FILE
578
+ : undefined;
402
579
  }
403
580
 
404
581
  function invalidBundleError() {
405
582
  return {
406
583
  code: 'ENIGMA_BUNDLE_INVALID',
407
584
  message: 'Enigma native host could not load the local bundle.',
408
- action: 'Check that ENIGMA_BUNDLE points to an enigma.vault_bundle.v1 JSON file.',
585
+ action: 'Check that ENIGMA_BUNDLE points to an enigma.vault_bundle.v1 JSON file and that its passphrase is correct.',
409
586
  };
410
587
  }
411
588
 
@@ -420,6 +597,45 @@ function bundlePathFromOptions(options) {
420
597
  return typeof env.ENIGMA_BUNDLE === 'string' && env.ENIGMA_BUNDLE.length > 0 ? env.ENIGMA_BUNDLE : undefined;
421
598
  }
422
599
 
600
+ function selectedBrowserContext(message) {
601
+ const text = typeof message.selection?.text === 'string' ? message.selection.text : '';
602
+ if (text.length === 0) return undefined;
603
+ if (text.length > 4000) throw new Error('Browser selection exceeds the native host limit.');
604
+ const source = typeof message.selection.source === 'string' && message.selection.source.length > 0
605
+ ? message.selection.source.slice(0, 80)
606
+ : 'user-selection';
607
+ const rawPage = message.page && typeof message.page === 'object' && !Array.isArray(message.page) ? message.page : {};
608
+ const rawDisplay = rawPage.display && typeof rawPage.display === 'object' && !Array.isArray(rawPage.display) ? rawPage.display : {};
609
+ const raw = {
610
+ providerId: safeProvider(rawPage.providerId ?? message.provider),
611
+ origin: boundedString(rawPage.origin, 512),
612
+ hostname: boundedString(rawPage.hostname, 255).toLowerCase(),
613
+ display: {
614
+ providerLabel: boundedString(rawDisplay.providerLabel, 80),
615
+ hostLabel: boundedString(rawDisplay.hostLabel, 255).toLowerCase(),
616
+ titlePresent: rawDisplay.titlePresent === true,
617
+ titleCharCount: safeCount(rawDisplay.titleCharCount),
618
+ },
619
+ topLevel: rawPage.topLevel === true,
620
+ };
621
+ return {
622
+ text,
623
+ source,
624
+ provider: safeProvider(message.provider),
625
+ page: {
626
+ raw,
627
+ topLevel: raw.topLevel,
628
+ origin_commitment: `sha256:${sha256Hex(raw.origin)}`,
629
+ hostname_commitment: `sha256:${sha256Hex(raw.hostname)}`,
630
+ metadata_commitment: `sha256:${sha256Hex(canonicalize(raw))}`,
631
+ },
632
+ };
633
+ }
634
+
635
+ function boundedString(value, maxLength) {
636
+ return typeof value === 'string' ? value.slice(0, maxLength) : '';
637
+ }
638
+
423
639
  function renderContextText(contextPack) {
424
640
  return contextPack.memories
425
641
  .map((memory, index) => {