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,459 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { existsSync } from 'node:fs';
3
+ import { resolve, dirname } from 'node:path';
4
+ import { ANSI } from '../terminal-tui/merkle-tree-renderer.mjs';
5
+ import { main as enigmaMain } from '../../apps/cli/bin/enigma.mjs';
6
+ import { renderHelpCatalog, OFFICIAL_TOKEN_CA } from './banner.mjs';
7
+ import { runConstellationAnimation, runMatrixStream, runSolanaHeartbeatStream } from './animations.mjs';
8
+ import { probeSolanaRpc, formatSolanaStatusReport, formatSolanaAnchorVerificationReport } from './solana-rpc.mjs';
9
+ import { PhantomBrowserBridge } from './phantom-bridge.mjs';
10
+ import { AutoAnchorEngine } from './auto-anchor.mjs';
11
+
12
+ export const DEFAULT_SOLANA_CLUSTER = 'mainnet-beta';
13
+
14
+ export function normalizeReplArgv(rawArgv, defaultBundlePath) {
15
+ if (!Array.isArray(rawArgv) || rawArgv.length === 0) return [];
16
+
17
+ const command = String(rawArgv[0]).toLowerCase();
18
+ const rest = rawArgv.slice(1);
19
+ const flags = [];
20
+ const positional = [];
21
+
22
+ for (let i = 0; i < rest.length; i++) {
23
+ const token = rest[i];
24
+ if (token.startsWith('-')) {
25
+ flags.push(token);
26
+ if (i + 1 < rest.length && !rest[i + 1].startsWith('-')) {
27
+ flags.push(rest[i + 1]);
28
+ i++;
29
+ }
30
+ } else {
31
+ positional.push(token);
32
+ }
33
+ }
34
+
35
+ const hasFlag = (...names) => flags.some((f) => names.includes(f));
36
+ const result = [command];
37
+
38
+ if (command === 'remember') {
39
+ if (!hasFlag('--text', '-t', '--text-file', '--textFile') && positional.length > 0) {
40
+ result.push('--text', positional.join(' '));
41
+ }
42
+ result.push(...flags);
43
+ } else if (command === 'context') {
44
+ if (!hasFlag('--query', '-q', '--search') && positional.length > 0) {
45
+ result.push('--query', positional.join(' '));
46
+ }
47
+ result.push(...flags);
48
+ } else if (command === 'tui' || command === 'dashboard' || command === 'monitor') {
49
+ if (!hasFlag('--once')) {
50
+ result.push('--once');
51
+ }
52
+ result.push(...flags);
53
+ } else if (command === 'enclave') {
54
+ const sub = positional[0]?.toLowerCase() || 'cycle';
55
+ const subPositional = positional.slice(1);
56
+
57
+ if (sub === 'verify' || sub === 'verify-zeroization') {
58
+ result.push('verify-zeroization');
59
+ if (!hasFlag('--receipt', '-r') && subPositional.length > 0) {
60
+ result.push('--receipt', subPositional[0]);
61
+ }
62
+ result.push(...flags);
63
+ } else if (sub === 'attest') {
64
+ result.push('attest');
65
+ result.push(...flags);
66
+ } else {
67
+ result.push('cycle');
68
+ if (!hasFlag('--receipt-out', '--receiptOut', '--out') && subPositional.length > 0) {
69
+ result.push('--receipt-out', subPositional[0]);
70
+ }
71
+ result.push(...flags);
72
+ }
73
+ } else if (command === 'tree') {
74
+ if (!hasFlag('--depth', '-d') && positional.length > 0 && /^\d+$/.test(positional[0])) {
75
+ result.push('--depth', positional[0]);
76
+ }
77
+ result.push(...flags);
78
+ } else if (command === 'export') {
79
+ if (!hasFlag('--out', '-o') && positional.length > 0) {
80
+ result.push('--out', positional[0]);
81
+ }
82
+ result.push(...flags);
83
+ } else if (command === 'verify') {
84
+ if (!hasFlag('--export', '-e', '--file') && positional.length > 0) {
85
+ result.push('--export', positional[0]);
86
+ }
87
+ result.push(...flags);
88
+ } else {
89
+ result.push(...rest);
90
+ }
91
+
92
+ // Attach active bundle if needed and not supplied
93
+ const needsBundle = ['quickstart', 'remember', 'update', 'delete', 'context', 'doctor', 'tree', 'tui', 'dashboard', 'monitor', 'enclave', 'swarm', 'chain', 'export', 'status'].includes(command);
94
+ const hasBundleFlag = result.some((arg) => arg === '--bundle' || arg === '-b' || arg === '--file');
95
+ if (needsBundle && !hasBundleFlag) {
96
+ result.push('--bundle', defaultBundlePath);
97
+ }
98
+
99
+ return result;
100
+ }
101
+
102
+ export class TerminalSession {
103
+ constructor({
104
+ bundlePath = '.enigma/bundle.json',
105
+ color = true,
106
+ io = { stdout: process.stdout, stderr: process.stderr },
107
+ fetchFn = globalThis.fetch,
108
+ } = {}) {
109
+ this.bundlePath = bundlePath;
110
+ this.color = color;
111
+ this.io = io;
112
+ this.fetchFn = fetchFn;
113
+ this.phantomBridge = null;
114
+ this._connectedWallet = null;
115
+ this.activeAbortController = null;
116
+ this.autoAnchorEngine = new AutoAnchorEngine({
117
+ rootDir: dirname(this.bundlePath),
118
+ cluster: DEFAULT_SOLANA_CLUSTER,
119
+ });
120
+ }
121
+
122
+ get connectedWallet() {
123
+ return this.phantomBridge?.connectedWallet ?? this._connectedWallet ?? null;
124
+ }
125
+
126
+ set connectedWallet(wallet) {
127
+ this._connectedWallet = wallet;
128
+ if (this.phantomBridge) {
129
+ this.phantomBridge.connectedWallet = wallet;
130
+ }
131
+ }
132
+
133
+ setBundlePath(path) {
134
+ this.bundlePath = path;
135
+ }
136
+
137
+ async getVaultSummary() {
138
+ try {
139
+ const data = JSON.parse(await readFile(resolve(this.bundlePath), 'utf8'));
140
+ const activeAddresses = Array.isArray(data?.active_memory_addresses)
141
+ ? data.active_memory_addresses
142
+ : (Array.isArray(data?.vault?.active_memory_addresses)
143
+ ? data.vault.active_memory_addresses
144
+ : (Array.isArray(data?.activeAddresses) ? data.activeAddresses : []));
145
+ const activeCount = activeAddresses.length;
146
+ const root = data?.vault?.active_set_root || data?.vault?.set_root || data?.active_set_root || 'uninitialized';
147
+ const shortRoot = root.startsWith('sha256:') ? root.slice(0, 15) + '...' : root.slice(0, 8);
148
+ return { activeCount, shortRoot, initialized: Boolean(data?.vault || data?.schema) };
149
+ } catch {
150
+ return { activeCount: 0, shortRoot: 'uninitialized', initialized: false };
151
+ }
152
+ }
153
+
154
+ async renderPrompt() {
155
+ const summary = await this.getVaultSummary();
156
+ const c = (text, code) => (this.color ? `${code}${text}${ANSI.reset}` : text);
157
+
158
+ const vaultBadge = summary.initialized
159
+ ? `${c('vault:', ANSI.dimText)}${c(`active (${summary.activeCount})`, ANSI.green)} ${c(summary.shortRoot, ANSI.gray)}`
160
+ : `${c('vault:', ANSI.dimText)}${c('new', ANSI.amber)}`;
161
+
162
+ return `${c('enigma', `${ANSI.bold}${ANSI.amber}`)} [${vaultBadge}] ${c('>', ANSI.white)} `;
163
+ }
164
+
165
+ parseArgv(line) {
166
+ const trimmed = String(line || '').trim();
167
+ if (!trimmed) return [];
168
+
169
+ const tokens = [];
170
+ let current = '';
171
+ let inQuote = false;
172
+ let quoteChar = '';
173
+
174
+ for (let i = 0; i < trimmed.length; i++) {
175
+ const char = trimmed[i];
176
+ if (inQuote) {
177
+ if (char === quoteChar) {
178
+ inQuote = false;
179
+ } else {
180
+ current += char;
181
+ }
182
+ } else if (char === '"' || char === "'") {
183
+ inQuote = true;
184
+ quoteChar = char;
185
+ } else if (/\s/.test(char)) {
186
+ if (current) {
187
+ tokens.push(current);
188
+ current = '';
189
+ }
190
+ } else {
191
+ current += char;
192
+ }
193
+ }
194
+ if (current) tokens.push(current);
195
+ return tokens;
196
+ }
197
+
198
+ async executeCommand(line, { signal = undefined } = {}) {
199
+ const rawArgv = this.parseArgv(line);
200
+ if (rawArgv.length === 0) return 0;
201
+ const shouldStop = (signal || this.activeAbortController)
202
+ ? () => Boolean(signal?.aborted || this.activeAbortController?.signal?.aborted)
203
+ : undefined;
204
+
205
+ const command = rawArgv[0].toLowerCase();
206
+ const c = (text, code) => (this.color ? `${code}${text}${ANSI.reset}` : text);
207
+
208
+ // Shell-local builtins
209
+ switch (command) {
210
+ case 'help':
211
+ case '?':
212
+ this.io.stdout.write(renderHelpCatalog({ color: this.color }) + '\n');
213
+ return 0;
214
+
215
+ case 'token':
216
+ case 'ca':
217
+ this.io.stdout.write(`\n ${c('ENIGMA OFFICIAL TOKEN COORDINATES', `${ANSI.bold}${ANSI.amber}`)}\n`);
218
+ this.io.stdout.write(` ${c('Solana Mint CA:', ANSI.dimText)} ${c(OFFICIAL_TOKEN_CA, `${ANSI.bold}${ANSI.white}`)}\n`);
219
+ this.io.stdout.write(` ${c('Solscan:', ANSI.dimText)} https://solscan.io/token/${OFFICIAL_TOKEN_CA}\n`);
220
+ this.io.stdout.write(` ${c('Pump.fun:', ANSI.dimText)} https://pump.fun/coin/${OFFICIAL_TOKEN_CA}\n`);
221
+ this.io.stdout.write(` ${c('Website:', ANSI.dimText)} https://enigmamemory.com\n`);
222
+ this.io.stdout.write(` ${c('X (Twitter):', ANSI.dimText)} https://x.com/Engimamemory\n\n`);
223
+ return 0;
224
+
225
+ case 'solana': {
226
+ const sub = rawArgv[1]?.toLowerCase();
227
+ if (sub === 'submit' || sub === 'submit-solana') {
228
+ const args = rawArgv.slice(2);
229
+ const hasCluster = args.some((arg) => arg === '--cluster');
230
+ const hasFile = args.some((arg) => arg === '--file' || arg === '-f' || arg === '--in');
231
+ const defaultAnchorPath = resolve(this.bundlePath ? (this.bundlePath.includes('/') || this.bundlePath.includes('\\') ? this.bundlePath.replace(/[^/\\]+$/, 'anchor-batch.json') : 'anchor-batch.json') : 'anchor-batch.json');
232
+ const resolvedArgs = [...args];
233
+ if (!hasCluster) resolvedArgs.push('--cluster', DEFAULT_SOLANA_CLUSTER);
234
+ if (!hasFile && existsSync(defaultAnchorPath)) resolvedArgs.push('--file', defaultAnchorPath);
235
+ return await enigmaMain(['chain', 'submit-solana', ...resolvedArgs], this.io);
236
+ } else if (sub === 'verify-anchor' || sub === 'verify-solana' || sub === 'verify') {
237
+ const args = rawArgv.slice(2);
238
+ if (args.includes('--help') || args.includes('-h')) {
239
+ return await enigmaMain(['chain', 'verify-solana', ...args], this.io);
240
+ }
241
+ const hasCluster = args.some((arg) => arg === '--cluster');
242
+ const hasFile = args.some((arg) => arg === '--file' || arg === '-f' || arg === '--in');
243
+ const defaultAnchorPath = resolve(this.bundlePath ? (this.bundlePath.includes('/') || this.bundlePath.includes('\\') ? this.bundlePath.replace(/[^/\\]+$/, 'anchor-batch.json') : 'anchor-batch.json') : 'anchor-batch.json');
244
+ const verifyArgs = [...args];
245
+ if (!hasCluster) verifyArgs.push('--cluster', DEFAULT_SOLANA_CLUSTER);
246
+ if (!hasFile && existsSync(defaultAnchorPath)) verifyArgs.push('--file', defaultAnchorPath);
247
+ let output = '';
248
+ const verifyIo = {
249
+ ...this.io,
250
+ solanaFetch: this.fetchFn,
251
+ stdout: { write: (chunk) => { output += String(chunk); } },
252
+ };
253
+ const code = await enigmaMain(['chain', 'verify-solana', ...verifyArgs], verifyIo);
254
+ let report;
255
+ try { report = JSON.parse(output); } catch { report = null; }
256
+ if (report && typeof report === 'object') {
257
+ this.io.stdout.write('\n' + formatSolanaAnchorVerificationReport(report, { color: this.color }) + '\n');
258
+ } else if (output) {
259
+ this.io.stdout.write(output);
260
+ }
261
+ return code;
262
+ } else if (sub === 'stream' || sub === 'pulse' || sub === 'heartbeat' || sub === 'live') {
263
+ let cluster = DEFAULT_SOLANA_CLUSTER;
264
+ let rpcUrl = undefined;
265
+ let samples = undefined;
266
+ for (let i = 2; i < rawArgv.length; i++) {
267
+ if (rawArgv[i] === '--cluster' && rawArgv[i + 1]) cluster = rawArgv[++i];
268
+ else if (rawArgv[i] === '--rpc' && rawArgv[i + 1]) rpcUrl = rawArgv[++i];
269
+ else if ((rawArgv[i] === '--samples' || rawArgv[i] === '-n') && rawArgv[i + 1]) samples = Number(rawArgv[++i]) || 6;
270
+ else if (rawArgv[i] === '--once') samples = 1;
271
+ }
272
+ return await runSolanaHeartbeatStream(this.io, { cluster, rpcUrl, samples, fetchFn: this.fetchFn, color: this.color, bundlePath: this.bundlePath, shouldStop });
273
+ } else if (sub === 'anchor-bundle' || sub === 'anchor-vault') {
274
+ const args = rawArgv.slice(2);
275
+ const hasBundle = args.some((arg) => arg === '--bundle' || arg === '-b' || arg === '--file');
276
+ const hasCluster = args.some((arg) => arg === '--cluster');
277
+ const hasOut = args.some((arg) => arg === '--out' || arg === '-o');
278
+ const defaultOut = resolve(this.bundlePath ? (this.bundlePath.includes('/') || this.bundlePath.includes('\\') ? this.bundlePath.replace(/[^/\\]+$/, 'anchor-batch.json') : 'anchor-batch.json') : 'anchor-batch.json');
279
+ const finalArgs = [...args];
280
+ if (!hasBundle) finalArgs.push('--bundle', this.bundlePath);
281
+ if (!hasCluster) finalArgs.push('--cluster', DEFAULT_SOLANA_CLUSTER);
282
+ if (!hasOut) finalArgs.push('--out', defaultOut);
283
+ return await enigmaMain(['chain', 'anchor-bundle', ...finalArgs], this.io);
284
+ } else if (sub === 'anchor') {
285
+ return await enigmaMain(['chain', 'anchor', ...rawArgv.slice(2)], this.io);
286
+ } else if (sub === 'connect-phantom' || sub === 'connect') {
287
+ return await this.handleWalletConnect();
288
+ } else if (sub === 'auto-anchor' || sub === 'auto') {
289
+ return await this.handleAutoAnchor(rawArgv.slice(2));
290
+ } else if (!sub || sub === 'status' || sub === 'ping' || sub === 'health') {
291
+ // Extract cluster / rpc flag if provided
292
+ let cluster = DEFAULT_SOLANA_CLUSTER;
293
+ let rpcUrl = undefined;
294
+ for (let i = 2; i < rawArgv.length; i++) {
295
+ if (rawArgv[i] === '--cluster' && rawArgv[i + 1]) cluster = rawArgv[++i];
296
+ else if (rawArgv[i] === '--rpc' && rawArgv[i + 1]) rpcUrl = rawArgv[++i];
297
+ }
298
+ const probe = await probeSolanaRpc({ cluster, rpcUrl, fetchFn: this.fetchFn });
299
+ this.io.stdout.write('\n' + formatSolanaStatusReport(probe, { color: this.color }) + '\n');
300
+ return probe.ok === true ? 0 : 1;
301
+ } else {
302
+ this.io.stdout.write(`${c('Unknown solana subcommand:', ANSI.red)} "${sub}". Available: status, ping, health, stream, pulse, anchor, anchor-bundle, submit, verify-anchor, auto-anchor, connect-phantom\n`);
303
+ }
304
+ }
305
+
306
+ case 'wallet':
307
+ case 'phantom': {
308
+ const sub = (rawArgv[1] || 'status').toLowerCase();
309
+ if (sub === 'connect') {
310
+ return await this.handleWalletConnect();
311
+ } else if (sub === 'status') {
312
+ if (this.connectedWallet) {
313
+ this.io.stdout.write(`\n${c('Active Solana Wallet:', ANSI.green)} ${this.connectedWallet.publicKey}\n`);
314
+ this.io.stdout.write(`Cluster: ${this.connectedWallet.cluster || 'mainnet-beta'}\n`);
315
+ this.io.stdout.write(`Balance: ${this.connectedWallet.balance || '0.00'} SOL\n\n`);
316
+ } else {
317
+ this.io.stdout.write(`\n${c('Wallet Status:', ANSI.yellow)} Disconnected\nType "wallet connect" to open the Phantom browser companion.\n\n`);
318
+ }
319
+ return 0;
320
+ } else if (sub === 'disconnect') {
321
+ this.connectedWallet = null;
322
+ this.io.stdout.write(`${c('✔ Wallet disconnected.', ANSI.green)}\n`);
323
+ return 0;
324
+ } else {
325
+ this.io.stdout.write(`Available wallet commands: wallet connect, wallet status, wallet disconnect\n`);
326
+ return 1;
327
+ }
328
+ }
329
+ case 'auto-anchor': {
330
+ return await this.handleAutoAnchor(rawArgv.slice(1));
331
+ }
332
+
333
+ case 'constellation':
334
+ return await runConstellationAnimation(this.io, { color: this.color, shouldStop });
335
+
336
+ case 'matrix':
337
+ return await runMatrixStream(this.io, { color: this.color, shouldStop });
338
+
339
+ case 'stream':
340
+ case 'pulse':
341
+ case 'heartbeat': {
342
+ let cluster = DEFAULT_SOLANA_CLUSTER;
343
+ let rpcUrl = undefined;
344
+ let samples = undefined;
345
+ for (let i = 1; i < rawArgv.length; i++) {
346
+ if (rawArgv[i] === '--cluster' && rawArgv[i + 1]) cluster = rawArgv[++i];
347
+ else if (rawArgv[i] === '--rpc' && rawArgv[i + 1]) rpcUrl = rawArgv[++i];
348
+ else if ((rawArgv[i] === '--samples' || rawArgv[i] === '-n') && rawArgv[i + 1]) samples = Number(rawArgv[++i]) || 6;
349
+ else if (rawArgv[i] === '--once') samples = 1;
350
+ }
351
+ return await runSolanaHeartbeatStream(this.io, { cluster, rpcUrl, samples, fetchFn: this.fetchFn, color: this.color, bundlePath: this.bundlePath, shouldStop });
352
+ }
353
+ case 'bundle': {
354
+ const newPath = rawArgv[1];
355
+ if (!newPath) {
356
+ this.io.stdout.write(`Current bundle: ${this.bundlePath}\n`);
357
+ } else {
358
+ this.bundlePath = newPath;
359
+ this.io.stdout.write(`${c('Switched active bundle:', ANSI.green)} ${this.bundlePath}\n`);
360
+ }
361
+ return 0;
362
+ }
363
+
364
+ case 'clear':
365
+ case 'cls':
366
+ this.io.stdout.write('\x1b[2J\x1b[0;0H');
367
+ return 0;
368
+
369
+ case 'exit':
370
+ case 'quit':
371
+ return 'EXIT';
372
+ }
373
+
374
+ // Normalize REPL arguments (e.g. `remember "text"`, `context "query"`, `enclave verify <path>`)
375
+ const delegatedArgv = normalizeReplArgv(rawArgv, this.bundlePath);
376
+
377
+ // Pass color flag if disabled
378
+ if (!this.color && !delegatedArgv.includes('--no-color')) {
379
+ delegatedArgv.push('--no-color');
380
+ }
381
+
382
+ try {
383
+ return await enigmaMain(delegatedArgv, this.io);
384
+ } catch (err) {
385
+ this.io.stderr.write(`${c('Error:', ANSI.red)} ${err.message}\n`);
386
+ return 1;
387
+ }
388
+ }
389
+ async handleWalletConnect() {
390
+ const c = (text, code) => (this.color ? `${code}${text}${ANSI.reset}` : text);
391
+ this.io.stdout.write(`\n${c('⚡ Launching Phantom Browser Companion...', ANSI.cyan)}\n`);
392
+ try {
393
+ if (!this.phantomBridge) {
394
+ this.phantomBridge = new PhantomBrowserBridge({
395
+ port: 0,
396
+ cluster: 'mainnet-beta',
397
+ onWalletConnected: (wallet) => {
398
+ this.connectedWallet = wallet;
399
+ },
400
+ });
401
+ await this.phantomBridge.startServer();
402
+ } else {
403
+ this.phantomBridge.onWalletConnected = (wallet) => {
404
+ this.connectedWallet = wallet;
405
+ };
406
+ }
407
+ const session = this.phantomBridge.createSession();
408
+ const url = await this.phantomBridge.openInSystemBrowser(session.nonce);
409
+ this.io.stdout.write(`Companion URL opened: ${c(url, ANSI.yellow)}\n`);
410
+ this.io.stdout.write(`Approve and sign the authentication challenge in your Phantom browser extension.\n\n`);
411
+ return 0;
412
+ } catch (err) {
413
+ this.io.stderr.write(`${c('Wallet bridge error:', ANSI.red)} ${err.message}\n`);
414
+ return 1;
415
+ }
416
+ }
417
+
418
+ async handleAutoAnchor(args = []) {
419
+ const sub = (args[0] || 'status').toLowerCase();
420
+ const c = (txt, color) => (this.color ? `${color}${txt}${ANSI.reset}` : txt);
421
+
422
+ if (sub === 'status') {
423
+ const isCfg = this.autoAnchorEngine.isConfigured();
424
+ const signerPubkey = this.autoAnchorEngine.signerStore.getPublicKey();
425
+ const delegation = this.autoAnchorEngine.getDelegation();
426
+ const stats = this.autoAnchorEngine.outbox.getStats();
427
+
428
+ this.io.stdout.write(`\n${c('─── Enigma Auto-Anchor Engine Status ───', ANSI.cyan)}\n`);
429
+ this.io.stdout.write(` Engine State: ${isCfg ? c('CONFIGURED & ACTIVE', ANSI.green) : c('UNCONFIGURED', ANSI.yellow)}\n`);
430
+ this.io.stdout.write(` Cluster: ${DEFAULT_SOLANA_CLUSTER}\n`);
431
+ this.io.stdout.write(` Signer Pubkey: ${signerPubkey ? signerPubkey : c('(none - run auto-anchor setup)', ANSI.dimText)}\n`);
432
+ this.io.stdout.write(` Delegation: ${delegation ? c(`VALID (${delegation.authorization_hash.slice(0, 18)}...)`, ANSI.green) : c('(none)', ANSI.dimText)}\n`);
433
+ this.io.stdout.write(` Outbox Pending: ${stats.pendingCount} proofs\n`);
434
+ this.io.stdout.write(` Anchored History: ${stats.historicalCount} proofs\n\n`);
435
+ return 0;
436
+ } else if (sub === 'setup' || sub === 'enable') {
437
+ const setupResult = this.autoAnchorEngine.setupSigner();
438
+ this.io.stdout.write(`\n${c('✔ Automation Signer Initialized:', ANSI.green)} ${setupResult.publicKeyBase58}\n`);
439
+ this.io.stdout.write(` Key custody secured via OS DPAPI/Keychain vault.\n`);
440
+ this.io.stdout.write(` To activate auto-anchoring, connect your Phantom wallet in Desktop GUI or sign delegation.\n\n`);
441
+ return 0;
442
+ } else if (sub === 'process' || sub === 'sync') {
443
+ this.io.stdout.write(`\nProcessing pending proofs from auto-anchor outbox...\n`);
444
+ const result = await this.autoAnchorEngine.processNextOutboxItem({ force: true });
445
+ if (result && result.ok && result.item) {
446
+ this.io.stdout.write(`${c('✔ Successfully anchored proof:', ANSI.green)} ${result.item.solscanUrl}\n\n`);
447
+ } else if (result && result.skipped) {
448
+ this.io.stdout.write(`Outbox idle: ${result.reason}\n\n`);
449
+ } else {
450
+ const err = result?.error || 'Unknown outbox processing error';
451
+ this.io.stdout.write(`${c('✖ Auto-anchor processing failed:', ANSI.red)} ${err}\n\n`);
452
+ }
453
+ return (result && result.ok) ? 0 : 1;
454
+ } else {
455
+ this.io.stdout.write(`${c('Unknown auto-anchor action:', ANSI.red)} "${sub}". Available: status, setup, process\n`);
456
+ return 1;
457
+ }
458
+ }
459
+ }
@@ -0,0 +1,152 @@
1
+ // Enigma Sovereign AI Memory — Dual-Key Delegation Layer
2
+ // Formats, hashes, and cryptographically verifies one-time owner delegation authorizations.
3
+
4
+ import crypto from 'node:crypto';
5
+ import { decodeBase58 } from './phantom-bridge.mjs';
6
+
7
+ const ED25519_SPKI_PREFIX = Buffer.from('302a300506032b6570032100', 'hex');
8
+ export const MAX_AUTO_ANCHOR_FEE_LAMPORTS = 5000;
9
+ export const DEFAULT_DELEGATION_EXPIRY_DAYS = 30;
10
+ export const MAX_DELEGATION_TTL_DAYS = 90;
11
+ export const DELEGATION_POLICY_MEMO_ONLY = 'spl-memo-proof-anchoring-only';
12
+
13
+ export function normalizeDescriptor(descriptor) {
14
+ return {
15
+ schema: 'enigma.delegated_signer_authorization.v1',
16
+ owner_pubkey: descriptor.owner_pubkey || descriptor.ownerPubkey,
17
+ signer_pubkey: descriptor.signer_pubkey || descriptor.signerPubkey,
18
+ cluster: descriptor.cluster || 'mainnet-beta',
19
+ policy: descriptor.policy || DELEGATION_POLICY_MEMO_ONLY,
20
+ max_fee_lamports: Number(descriptor.max_fee_lamports || descriptor.maxFeeLamports || MAX_AUTO_ANCHOR_FEE_LAMPORTS),
21
+ issued_at: descriptor.issued_at || descriptor.issuedAt,
22
+ expires_at: descriptor.expires_at || descriptor.expiresAt,
23
+ };
24
+ }
25
+
26
+ export function computeAuthorizationHash(descriptor) {
27
+ const canonical = normalizeDescriptor(descriptor);
28
+ return 'sha256:' + crypto.createHash('sha256').update(JSON.stringify(canonical)).digest('hex');
29
+ }
30
+
31
+ export function buildDelegationChallenge(descriptor) {
32
+ const norm = normalizeDescriptor(descriptor);
33
+ const authHash = descriptor.authorization_hash || descriptor.authorizationHash || computeAuthorizationHash(norm);
34
+ return [
35
+ 'Enigma Auto-Anchor Delegation Authorization',
36
+ `Schema: enigma.delegated_signer_authorization.v1`,
37
+ `Owner Address: ${norm.owner_pubkey}`,
38
+ `Automation Signer: ${norm.signer_pubkey}`,
39
+ `Cluster: ${norm.cluster}`,
40
+ `Policy: ${norm.policy}`,
41
+ `Max Fee Cap: ${norm.max_fee_lamports} lamports`,
42
+ `Issued At: ${norm.issued_at}`,
43
+ `Expires At: ${norm.expires_at}`,
44
+ `Authorization Hash: ${authHash}`,
45
+ 'Statement: Authorize this local automation signer to broadcast mathematical Merkle root timestamps to Solana Mainnet on your behalf with zero private data on-chain.',
46
+ ].join('\n');
47
+ }
48
+
49
+ export function createDelegationArtifact({
50
+ ownerPubkey,
51
+ signerPubkey,
52
+ cluster = 'mainnet-beta',
53
+ policy = DELEGATION_POLICY_MEMO_ONLY,
54
+ maxFeeLamports = MAX_AUTO_ANCHOR_FEE_LAMPORTS,
55
+ issuedAt = undefined,
56
+ expiresAt = undefined,
57
+ ownerSignature,
58
+ }) {
59
+ const issued = issuedAt || new Date().toISOString();
60
+ const expiry = expiresAt || new Date(Date.now() + DEFAULT_DELEGATION_EXPIRY_DAYS * 24 * 60 * 60 * 1000).toISOString();
61
+ const descriptor = {
62
+ schema: 'enigma.delegated_signer_authorization.v1',
63
+ owner_pubkey: ownerPubkey,
64
+ signer_pubkey: signerPubkey,
65
+ cluster,
66
+ policy,
67
+ max_fee_lamports: Number(maxFeeLamports),
68
+ issued_at: issued,
69
+ expires_at: expiry,
70
+ };
71
+ const authHash = computeAuthorizationHash(descriptor);
72
+ return {
73
+ ...descriptor,
74
+ owner_signature: ownerSignature,
75
+ authorization_hash: authHash,
76
+ };
77
+ }
78
+
79
+ export function verifyDelegationArtifact(artifact, { expectedCluster = 'mainnet-beta' } = {}) {
80
+ if (!artifact || typeof artifact !== 'object' || artifact.schema !== 'enigma.delegated_signer_authorization.v1') {
81
+ return { ok: false, error: 'Invalid delegation schema' };
82
+ }
83
+ if (!artifact.owner_pubkey || !artifact.signer_pubkey) {
84
+ return { ok: false, error: 'Missing owner or signer public keys' };
85
+ }
86
+ if (artifact.cluster !== expectedCluster) {
87
+ return { ok: false, error: `Cluster mismatch: artifact authorized for ${artifact.cluster}, expected ${expectedCluster}` };
88
+ }
89
+ if (artifact.policy !== DELEGATION_POLICY_MEMO_ONLY) {
90
+ return { ok: false, error: `Unauthorized policy: ${artifact.policy}` };
91
+ }
92
+
93
+ const feeCap = Number(artifact.max_fee_lamports);
94
+ if (!Number.isInteger(feeCap) || feeCap <= 0 || feeCap > MAX_AUTO_ANCHOR_FEE_LAMPORTS) {
95
+ return { ok: false, error: `Invalid fee cap: must be an integer between 1 and ${MAX_AUTO_ANCHOR_FEE_LAMPORTS} lamports` };
96
+ }
97
+
98
+ const issuedTime = Date.parse(artifact.issued_at);
99
+ const expiryTime = Date.parse(artifact.expires_at);
100
+
101
+ if (Number.isNaN(issuedTime) || Number.isNaN(expiryTime)) {
102
+ return { ok: false, error: 'Malformed non-ISO issued_at or expires_at timestamp' };
103
+ }
104
+ if (issuedTime > Date.now() + 60000) {
105
+ return { ok: false, error: 'issued_at is in the future' };
106
+ }
107
+ if (expiryTime <= issuedTime) {
108
+ return { ok: false, error: 'expires_at must be strictly after issued_at' };
109
+ }
110
+ const maxTtlMs = MAX_DELEGATION_TTL_DAYS * 24 * 60 * 60 * 1000;
111
+ if (expiryTime > issuedTime + maxTtlMs) {
112
+ return { ok: false, error: `expires_at exceeds maximum TTL of ${MAX_DELEGATION_TTL_DAYS} days` };
113
+ }
114
+ if (expiryTime < Date.now()) {
115
+ return { ok: false, error: 'Delegation authorization has expired' };
116
+ }
117
+
118
+ const expectedHash = computeAuthorizationHash(artifact);
119
+ if (artifact.authorization_hash !== expectedHash) {
120
+ return { ok: false, error: 'Authorization hash mismatch: descriptor fields were modified' };
121
+ }
122
+
123
+ const ownerBytes = decodeBase58(artifact.owner_pubkey, 32);
124
+ if (!ownerBytes || ownerBytes.length !== 32) {
125
+ return { ok: false, error: 'Invalid owner public key Base58' };
126
+ }
127
+
128
+ const challenge = buildDelegationChallenge(artifact);
129
+ const spki = Buffer.concat([ED25519_SPKI_PREFIX, ownerBytes]);
130
+ const pubKeyObj = crypto.createPublicKey({ key: spki, format: 'der', type: 'spki' });
131
+
132
+ let sigBytes;
133
+ if (Buffer.isBuffer(artifact.owner_signature)) {
134
+ sigBytes = artifact.owner_signature;
135
+ } else if (typeof artifact.owner_signature === 'string') {
136
+ const base58Decoded = decodeBase58(artifact.owner_signature, 64);
137
+ if (base58Decoded && base58Decoded.length === 64) {
138
+ sigBytes = base58Decoded;
139
+ } else {
140
+ sigBytes = Buffer.from(artifact.owner_signature, 'base64');
141
+ }
142
+ } else {
143
+ return { ok: false, error: 'Malformed owner signature format' };
144
+ }
145
+
146
+ if (!sigBytes || sigBytes.length !== 64) {
147
+ return { ok: false, error: 'Invalid 64-byte Ed25519 signature length' };
148
+ }
149
+
150
+ const isValid = crypto.verify(null, Buffer.from(challenge, 'utf8'), pubKeyObj, sigBytes);
151
+ return { ok: isValid, error: isValid ? null : 'Signature verification failed' };
152
+ }
@@ -0,0 +1,5 @@
1
+ export { renderTerminalBanner, renderHelpCatalog, OFFICIAL_TOKEN_CA } from './banner.mjs';
2
+ export { TerminalSession, normalizeReplArgv } from './commands.mjs';
3
+ export { runTerminalConsole, createCompleter } from './repl.mjs';
4
+ export { runConstellationAnimation, runMatrixStream, runSolanaHeartbeatStream } from './animations.mjs';
5
+ export { probeSolanaRpc, formatSolanaStatusReport, formatSolanaAnchorVerificationReport, fetchSolanaStreamMetrics, SOLANA_RPC_CLUSTERS } from './solana-rpc.mjs';