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,152 @@
1
+ import AVKit
2
+ import EnigmaCore
3
+ import SwiftUI
4
+
5
+ private enum CreationMode: String, CaseIterable, Identifiable {
6
+ case image = "Images"
7
+ case video = "Video"
8
+ case code = "Code"
9
+ var id: String { rawValue }
10
+ }
11
+
12
+ struct CreateView: View {
13
+ @EnvironmentObject private var model: AppModel
14
+ @State private var mode: CreationMode = .image
15
+
16
+ var body: some View {
17
+ ScrollView {
18
+ VStack(alignment: .leading, spacing: 20) {
19
+ Picker("Mode", selection: $mode) {
20
+ ForEach(CreationMode.allCases) { option in Text(option.rawValue).tag(option) }
21
+ }
22
+ .pickerStyle(.segmented)
23
+ switch mode {
24
+ case .image: ImageToolView()
25
+ case .video: VideoToolView()
26
+ case .code: CodeToolView()
27
+ }
28
+ }
29
+ .padding(20)
30
+ .padding(.bottom, 32)
31
+ }
32
+ .navigationTitle("Create")
33
+ .navigationBarTitleDisplayMode(.inline)
34
+ .enigmaCanvas()
35
+ }
36
+ }
37
+
38
+ private struct ImageToolView: View {
39
+ @EnvironmentObject private var model: AppModel
40
+ @State private var prompt = ""
41
+ @State private var selectedModel = ""
42
+
43
+ var body: some View {
44
+ VStack(alignment: .leading, spacing: 18) {
45
+ intro("ENIGMA IMAGE", "Generate without building a prompt archive.", "Prompts are minimized on-device. Returned assets remain caller-controlled.")
46
+ Picker("Image model", selection: $selectedModel) {
47
+ Text("Choose image model").tag("")
48
+ ForEach(model.imageModels) { route in Text(route.id).tag(route.id) }
49
+ }
50
+ .pickerStyle(.menu)
51
+ TextField("Describe the image…", text: $prompt, axis: .vertical)
52
+ .lineLimit(5...10)
53
+ .padding(12)
54
+ .background(.white)
55
+ .overlay(RoundedRectangle(cornerRadius: 10).stroke(EnigmaTheme.line))
56
+ Button("Generate image") { Task { await model.generateImage(prompt: prompt, model: selectedModel) } }
57
+ .buttonStyle(PrimaryButtonStyle())
58
+ .disabled(prompt.isEmpty || selectedModel.isEmpty || model.isBusy)
59
+ ForEach(Array(model.generatedImages.enumerated()), id: \.offset) { _, asset in
60
+ image(asset)
61
+ .frame(maxWidth: .infinity)
62
+ .aspectRatio(1, contentMode: .fit)
63
+ .background(Color.black.opacity(0.04))
64
+ .clipShape(RoundedRectangle(cornerRadius: 12))
65
+ }
66
+ }
67
+ .onAppear { if selectedModel.isEmpty { selectedModel = model.imageModels.first?.id ?? "" } }
68
+ }
69
+
70
+ @ViewBuilder private func image(_ asset: GeneratedImageAsset) -> some View {
71
+ if let raw = asset.base64, let data = Data(base64Encoded: raw), let uiImage = UIImage(data: data) {
72
+ Image(uiImage: uiImage).resizable().scaledToFit()
73
+ } else if let value = asset.url, let url = URL(string: value) {
74
+ AsyncImage(url: url) { phase in
75
+ if let image = phase.image { image.resizable().scaledToFit() }
76
+ else if phase.error != nil { ContentUnavailableView("Image unavailable", systemImage: "photo") }
77
+ else { ProgressView() }
78
+ }
79
+ } else { ContentUnavailableView("Image unavailable", systemImage: "photo") }
80
+ }
81
+ }
82
+
83
+ private struct VideoToolView: View {
84
+ @EnvironmentObject private var model: AppModel
85
+ @State private var prompt = ""
86
+ @State private var selectedModel = ""
87
+
88
+ var body: some View {
89
+ VStack(alignment: .leading, spacing: 18) {
90
+ intro("ENIGMA VIDEO", "Queue private motion generation.", "Progress is bounded job metadata. The final artifact belongs to you.")
91
+ Picker("Video model", selection: $selectedModel) {
92
+ Text("Choose video model").tag("")
93
+ ForEach(model.videoModels) { route in Text(route.id).tag(route.id) }
94
+ }
95
+ TextField("Describe motion, scene, and camera…", text: $prompt, axis: .vertical)
96
+ .lineLimit(5...10)
97
+ .padding(12)
98
+ .background(.white)
99
+ .overlay(RoundedRectangle(cornerRadius: 10).stroke(EnigmaTheme.line))
100
+ Button("Queue video") { Task { await model.queueVideo(prompt: prompt, model: selectedModel) } }
101
+ .buttonStyle(PrimaryButtonStyle())
102
+ .disabled(prompt.isEmpty || selectedModel.isEmpty || model.isBusy)
103
+ if let job = model.videoJob {
104
+ VStack(alignment: .leading, spacing: 9) {
105
+ HStack { Text(job.status.capitalized).font(.subheadline.weight(.semibold)); Spacer(); Text("\(Int(job.progress))%") }
106
+ ProgressView(value: job.progress, total: 100).tint(EnigmaTheme.ember)
107
+ if let error = job.error { Text(error).foregroundStyle(.red).font(.footnote) }
108
+ }
109
+ .enigmaSurface()
110
+ }
111
+ if let value = model.videoAsset?.url, let url = URL(string: value) {
112
+ VideoPlayer(player: AVPlayer(url: url)).frame(height: 230).clipShape(RoundedRectangle(cornerRadius: 12))
113
+ }
114
+ }
115
+ .onAppear { if selectedModel.isEmpty { selectedModel = model.videoModels.first?.id ?? "" } }
116
+ }
117
+ }
118
+
119
+ private struct CodeToolView: View {
120
+ @EnvironmentObject private var model: AppModel
121
+ @State private var source = "console.log('Enigma sandbox ready')"
122
+
123
+ var body: some View {
124
+ VStack(alignment: .leading, spacing: 18) {
125
+ intro("ENIGMA CODE", "Run below an OCI boundary.", "No network. Read-only root. No Linux capabilities. The session is burned after every run.")
126
+ TextEditor(text: $source)
127
+ .font(.system(.body, design: .monospaced))
128
+ .frame(minHeight: 240)
129
+ .padding(10)
130
+ .scrollContentBackground(.hidden)
131
+ .background(Color(red: 0.07, green: 0.065, blue: 0.06))
132
+ .foregroundStyle(Color(red: 0.93, green: 0.91, blue: 0.86))
133
+ .clipShape(RoundedRectangle(cornerRadius: 10))
134
+ Button("Create, run, and burn") { Task { await model.executeCode(source) } }
135
+ .buttonStyle(PrimaryButtonStyle())
136
+ .disabled(source.isEmpty || model.isBusy)
137
+ Text(model.codeOutput.isEmpty ? "No sandbox output." : model.codeOutput)
138
+ .font(.system(.footnote, design: .monospaced))
139
+ .textSelection(.enabled)
140
+ .frame(maxWidth: .infinity, minHeight: 120, alignment: .topLeading)
141
+ .enigmaSurface()
142
+ }
143
+ }
144
+ }
145
+
146
+ @ViewBuilder private func intro(_ eyebrow: String, _ title: String, _ description: String) -> some View {
147
+ VStack(alignment: .leading, spacing: 8) {
148
+ SectionEyebrow(text: eyebrow)
149
+ Text(title).font(EnigmaTheme.title)
150
+ Text(description).font(.subheadline).foregroundStyle(EnigmaTheme.secondary)
151
+ }
152
+ }
@@ -0,0 +1,52 @@
1
+ import SwiftUI
2
+
3
+ @main
4
+ struct EnigmaApp: App {
5
+ @StateObject private var model = AppModel()
6
+
7
+ var body: some Scene {
8
+ WindowGroup {
9
+ RootView()
10
+ .environmentObject(model)
11
+ .preferredColorScheme(.light)
12
+ }
13
+ }
14
+ }
15
+
16
+ struct RootView: View {
17
+ @EnvironmentObject private var model: AppModel
18
+
19
+ var body: some View {
20
+ Group {
21
+ if model.isConnected {
22
+ TabView {
23
+ NavigationStack { ChatView() }
24
+ .tabItem { Label("Chat", systemImage: "bubble.left") }
25
+ NavigationStack { CouncilView() }
26
+ .tabItem { Label("Council", systemImage: "point.3.connected.trianglepath.dotted") }
27
+ NavigationStack { CreateView() }
28
+ .tabItem { Label("Create", systemImage: "sparkles.rectangle.stack") }
29
+ NavigationStack { PrivateVaultView() }
30
+ .tabItem { Label("Private", systemImage: "lock.square") }
31
+ }
32
+ .tint(EnigmaTheme.ember)
33
+ } else {
34
+ OnboardingView()
35
+ }
36
+ }
37
+ .enigmaCanvas()
38
+ .overlay(alignment: .top) {
39
+ if model.isBusy {
40
+ ProgressView().tint(EnigmaTheme.ember).padding(.top, 8)
41
+ }
42
+ }
43
+ .alert("Enigma", isPresented: Binding(
44
+ get: { model.errorMessage != nil },
45
+ set: { if !$0 { model.errorMessage = nil } }
46
+ )) {
47
+ Button("Dismiss", role: .cancel) { model.errorMessage = nil }
48
+ } message: {
49
+ Text(model.errorMessage ?? "")
50
+ }
51
+ }
52
+ }
@@ -0,0 +1,52 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDisplayName</key>
6
+ <string>Enigma</string>
7
+ <key>CFBundleIdentifier</key>
8
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
9
+ <key>CFBundleInfoDictionaryVersion</key>
10
+ <string>6.0</string>
11
+ <key>CFBundleName</key>
12
+ <string>$(PRODUCT_NAME)</string>
13
+ <key>CFBundlePackageType</key>
14
+ <string>APPL</string>
15
+ <key>CFBundleShortVersionString</key>
16
+ <string>1.0</string>
17
+ <key>CFBundleVersion</key>
18
+ <string>1</string>
19
+ <key>CFBundleURLTypes</key>
20
+ <array>
21
+ <dict>
22
+ <key>CFBundleTypeRole</key>
23
+ <string>Editor</string>
24
+ <key>CFBundleURLName</key>
25
+ <string>com.enigmamemory.ios.oauth</string>
26
+ <key>CFBundleURLSchemes</key>
27
+ <array><string>enigma-ios</string></array>
28
+ </dict>
29
+ </array>
30
+ <key>LSRequiresIPhoneOS</key>
31
+ <true/>
32
+ <key>NSAppTransportSecurity</key>
33
+ <dict>
34
+ <key>NSAllowsLocalNetworking</key>
35
+ <true/>
36
+ </dict>
37
+ <key>UIApplicationSceneManifest</key>
38
+ <dict>
39
+ <key>UIApplicationSupportsMultipleScenes</key>
40
+ <false/>
41
+ </dict>
42
+ <key>UILaunchScreen</key>
43
+ <dict>
44
+ <key>UIColorName</key>
45
+ <string>LaunchBackground</string>
46
+ </dict>
47
+ <key>UISupportedInterfaceOrientations</key>
48
+ <array>
49
+ <string>UIInterfaceOrientationPortrait</string>
50
+ </array>
51
+ </dict>
52
+ </plist>
@@ -0,0 +1,26 @@
1
+ import EnigmaCore
2
+ import Foundation
3
+ import NaturalLanguage
4
+
5
+ struct NaturalLanguagePrivacyTagger: SemanticPrivacyTagging {
6
+ private let fallback = HeuristicSemanticPrivacyTagger()
7
+
8
+ func findings(in text: String) -> [SemanticPrivacyFinding] {
9
+ var output = fallback.findings(in: text)
10
+ let tagger = NLTagger(tagSchemes: [.nameType])
11
+ tagger.string = text
12
+ let options: NLTagger.Options = [.omitWhitespace, .omitPunctuation, .joinNames]
13
+ tagger.enumerateTags(in: text.startIndex..<text.endIndex, unit: .word, scheme: .nameType, options: options) { tag, range in
14
+ let category: PrivacyCategory?
15
+ switch tag {
16
+ case .personalName: category = .person
17
+ case .placeName: category = .location
18
+ case .organizationName: category = .organization
19
+ default: category = nil
20
+ }
21
+ if let category { output.append(.init(range: range, category: category)) }
22
+ return true
23
+ }
24
+ return output
25
+ }
26
+ }
@@ -0,0 +1,321 @@
1
+ import AuthenticationServices
2
+ import EnigmaCore
3
+ import Foundation
4
+ import UIKit
5
+
6
+ private final class WebAuthenticationAnchor: NSObject, ASWebAuthenticationPresentationContextProviding {
7
+ func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
8
+ let scenes = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }
9
+ return scenes.flatMap(\.windows).first(where: \.isKeyWindow) ?? ASPresentationAnchor()
10
+ }
11
+ }
12
+
13
+
14
+ @MainActor
15
+ private final class WebAuthenticationRunner {
16
+ private let anchor = WebAuthenticationAnchor()
17
+ private var session: ASWebAuthenticationSession?
18
+
19
+ func run(url: URL) async throws -> URL {
20
+ try await withCheckedThrowingContinuation { continuation in
21
+ session = ASWebAuthenticationSession(url: url, callbackURLScheme: "enigma-ios") { [weak self] url, error in
22
+ self?.session = nil
23
+ if let error { continuation.resume(throwing: error) }
24
+ else if let url { continuation.resume(returning: url) }
25
+ else { continuation.resume(throwing: OAuthClientError.invalidCallback) }
26
+ }
27
+ session?.presentationContextProvider = anchor
28
+ session?.prefersEphemeralWebBrowserSession = true
29
+ if session?.start() != true {
30
+ session = nil
31
+ continuation.resume(throwing: OAuthClientError.invalidCallback)
32
+ }
33
+ }
34
+ }
35
+ }
36
+ enum OAuthClientError: LocalizedError {
37
+ case invalidIssuer
38
+ case invalidResource
39
+ case invalidMetadata
40
+ case invalidCallback
41
+ case stateMismatch
42
+ case unsupportedScopes([String])
43
+ case registrationUnavailable
44
+ case registrationFailed(String)
45
+ case authorizationDenied(String)
46
+ case tokenExchangeFailed(String)
47
+
48
+ var errorDescription: String? {
49
+ switch self {
50
+ case .invalidIssuer: return "The OAuth issuer must use HTTPS, or loopback HTTP for local development."
51
+ case .invalidResource: return "The protected resource must be a canonical HTTPS URL, or loopback HTTP URL for local development."
52
+ case .invalidMetadata: return "The authorization server metadata is invalid."
53
+ case .invalidCallback: return "The OAuth callback was invalid."
54
+ case .stateMismatch: return "OAuth state verification failed."
55
+ case let .unsupportedScopes(scopes): return "The authorization server does not support: \(scopes.joined(separator: ", "))."
56
+ case .registrationUnavailable: return "Enter a registered public client ID; this authorization server does not offer approved dynamic registration."
57
+ case let .registrationFailed(reason): return reason
58
+ case let .authorizationDenied(reason): return reason
59
+ case let .tokenExchangeFailed(reason): return reason
60
+ }
61
+ }
62
+ }
63
+
64
+ private struct OAuthPublicClientRegistrationRequest: Encodable {
65
+ let clientName: String
66
+ let redirectURIs: [String]
67
+ let grantTypes: [String]
68
+ let responseTypes: [String]
69
+ let tokenEndpointAuthMethod: String
70
+ let scope: String
71
+
72
+ enum CodingKeys: String, CodingKey {
73
+ case clientName = "client_name"
74
+ case redirectURIs = "redirect_uris"
75
+ case grantTypes = "grant_types"
76
+ case responseTypes = "response_types"
77
+ case tokenEndpointAuthMethod = "token_endpoint_auth_method"
78
+ case scope
79
+ }
80
+ }
81
+
82
+ private struct OAuthPublicClientRegistrationResponse: Decodable {
83
+ let clientID: String
84
+ let redirectURIs: [String]
85
+ let tokenEndpointAuthMethod: String
86
+ let scope: String
87
+
88
+ enum CodingKeys: String, CodingKey {
89
+ case clientID = "client_id"
90
+ case redirectURIs = "redirect_uris"
91
+ case tokenEndpointAuthMethod = "token_endpoint_auth_method"
92
+ case scope
93
+ }
94
+ }
95
+
96
+ struct OAuthClient {
97
+ static let redirectURI = "enigma-ios://oauth/callback"
98
+ static let platformScopes = EnigmaOAuthScopes.iOSPlatform
99
+
100
+ @MainActor
101
+ func authorize(issuer: URL, clientID: String?, resource: URL, scopes: [String] = platformScopes) async throws -> OAuthCredential {
102
+ guard let protectedResource = Self.canonicalResource(resource) else { throw OAuthClientError.invalidResource }
103
+ let metadata = try await Self.metadata(issuer: issuer)
104
+ let requestedScopes = Array(Set(scopes)).sorted()
105
+ if let supportedScopes = metadata.scopesSupported {
106
+ let missing = requestedScopes.filter { !supportedScopes.contains($0) }
107
+ if !missing.isEmpty { throw OAuthClientError.unsupportedScopes(missing) }
108
+ }
109
+ let suppliedClientID = clientID?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
110
+ let resolvedClientID: String
111
+ if suppliedClientID.isEmpty {
112
+ resolvedClientID = try await Self.registerPublicClient(metadata: metadata, scopes: requestedScopes)
113
+ } else {
114
+ resolvedClientID = suppliedClientID
115
+ }
116
+ let pkce = PKCE.create()
117
+ let state = UUID().uuidString
118
+ guard let endpoint = Self.secureEndpoint(metadata.authorizationEndpoint),
119
+ var components = URLComponents(url: endpoint, resolvingAgainstBaseURL: false) else {
120
+ throw OAuthClientError.invalidMetadata
121
+ }
122
+ components.queryItems = [
123
+ URLQueryItem(name: "response_type", value: "code"),
124
+ URLQueryItem(name: "client_id", value: resolvedClientID),
125
+ URLQueryItem(name: "redirect_uri", value: Self.redirectURI),
126
+ URLQueryItem(name: "scope", value: requestedScopes.joined(separator: " ")),
127
+ URLQueryItem(name: "state", value: state),
128
+ URLQueryItem(name: "code_challenge", value: pkce.challenge),
129
+ URLQueryItem(name: "code_challenge_method", value: "S256"),
130
+ URLQueryItem(name: "resource", value: protectedResource.absoluteString),
131
+ ]
132
+ guard let authorizationURL = components.url else { throw OAuthClientError.invalidMetadata }
133
+ let callback = try await WebAuthenticationRunner().run(url: authorizationURL)
134
+ guard let callbackComponents = URLComponents(url: callback, resolvingAgainstBaseURL: false) else { throw OAuthClientError.invalidCallback }
135
+ let values = Dictionary(uniqueKeysWithValues: callbackComponents.queryItems?.map { ($0.name, $0.value ?? "") } ?? [])
136
+ if let error = values["error"] { throw OAuthClientError.authorizationDenied(values["error_description"] ?? error) }
137
+ guard values["state"] == state else { throw OAuthClientError.stateMismatch }
138
+ guard let code = values["code"], !code.isEmpty else { throw OAuthClientError.invalidCallback }
139
+ if let responseIssuer = values["iss"], responseIssuer != metadata.issuer { throw OAuthClientError.invalidCallback }
140
+ let tokens = try await Self.tokenRequest(
141
+ endpoint: metadata.tokenEndpoint,
142
+ fields: [
143
+ "grant_type": "authorization_code",
144
+ "client_id": resolvedClientID,
145
+ "code": code,
146
+ "redirect_uri": Self.redirectURI,
147
+ "code_verifier": pkce.verifier,
148
+ "resource": protectedResource.absoluteString,
149
+ ]
150
+ )
151
+ return OAuthCredential(
152
+ accessToken: tokens.accessToken,
153
+ refreshToken: tokens.refreshToken,
154
+ expiresAt: Date().addingTimeInterval(TimeInterval(tokens.expiresIn)),
155
+ clientID: resolvedClientID,
156
+ issuer: issuer,
157
+ resource: protectedResource
158
+ )
159
+ }
160
+
161
+ private static func registerPublicClient(metadata: OAuthAuthorizationServerMetadata, scopes: [String]) async throws -> String {
162
+ guard let value = metadata.registrationEndpoint, let endpoint = secureEndpoint(value) else {
163
+ throw OAuthClientError.registrationUnavailable
164
+ }
165
+ var request = URLRequest(url: endpoint, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 30)
166
+ request.httpMethod = "POST"
167
+ request.setValue("application/json", forHTTPHeaderField: "Content-Type")
168
+ request.setValue("application/json", forHTTPHeaderField: "Accept")
169
+ request.httpBody = try JSONEncoder().encode(OAuthPublicClientRegistrationRequest(
170
+ clientName: "Enigma for iOS",
171
+ redirectURIs: [redirectURI],
172
+ grantTypes: ["authorization_code", "refresh_token"],
173
+ responseTypes: ["code"],
174
+ tokenEndpointAuthMethod: "none",
175
+ scope: scopes.joined(separator: " ")
176
+ ))
177
+ let (data, response) = try await URLSession.shared.data(for: request)
178
+ guard let http = response as? HTTPURLResponse else { throw OAuthClientError.invalidMetadata }
179
+ guard (200..<300).contains(http.statusCode),
180
+ let registration = try? JSONDecoder().decode(OAuthPublicClientRegistrationResponse.self, from: data) else {
181
+ let reason = (try? JSONSerialization.jsonObject(with: data) as? [String: Any])?["error_description"] as? String
182
+ throw OAuthClientError.registrationFailed(reason ?? "OAuth public-client registration failed.")
183
+ }
184
+ let registeredScopes = Set(registration.scope.split(separator: " ").map(String.init))
185
+ guard !registration.clientID.isEmpty,
186
+ registration.redirectURIs.contains(redirectURI),
187
+ registration.tokenEndpointAuthMethod == "none",
188
+ Set(scopes).isSubset(of: registeredScopes) else {
189
+ throw OAuthClientError.registrationFailed("OAuth server returned an unsafe or incomplete public-client registration.")
190
+ }
191
+ return registration.clientID
192
+ }
193
+
194
+ private static func secureEndpoint(_ value: String) -> URL? {
195
+ guard let url = URL(string: value),
196
+ let scheme = url.scheme?.lowercased(),
197
+ let host = url.host?.lowercased(),
198
+ url.user == nil,
199
+ url.password == nil,
200
+ url.fragment == nil else { return nil }
201
+ let loopback = ["localhost", "127.0.0.1", "::1"].contains(host)
202
+ return scheme == "https" || (scheme == "http" && loopback) ? url : nil
203
+ }
204
+
205
+ private static func canonicalResource(_ value: URL) -> URL? {
206
+ guard let secured = secureEndpoint(value.absoluteString),
207
+ var components = URLComponents(url: secured, resolvingAgainstBaseURL: false),
208
+ components.query == nil else { return nil }
209
+ if components.path == "/" { components.path = "" }
210
+ return components.url
211
+ }
212
+
213
+ static func refresh(_ credential: OAuthCredential) async throws -> OAuthCredential {
214
+ guard let refreshToken = credential.refreshToken else { throw EnigmaAPIError.unauthenticated }
215
+ guard let protectedResource = canonicalResource(credential.resource) else { throw OAuthClientError.invalidResource }
216
+ let metadata = try await metadata(issuer: credential.issuer)
217
+ let tokens = try await tokenRequest(
218
+ endpoint: metadata.tokenEndpoint,
219
+ fields: [
220
+ "grant_type": "refresh_token",
221
+ "client_id": credential.clientID,
222
+ "refresh_token": refreshToken,
223
+ "resource": protectedResource.absoluteString,
224
+ ]
225
+ )
226
+ return OAuthCredential(
227
+ accessToken: tokens.accessToken,
228
+ refreshToken: tokens.refreshToken ?? refreshToken,
229
+ expiresAt: Date().addingTimeInterval(TimeInterval(tokens.expiresIn)),
230
+ clientID: credential.clientID,
231
+ issuer: credential.issuer,
232
+ resource: protectedResource
233
+ )
234
+ }
235
+
236
+ static func metadata(issuer: URL) async throws -> OAuthAuthorizationServerMetadata {
237
+ guard let securedIssuer = secureEndpoint(issuer.absoluteString),
238
+ var components = URLComponents(url: securedIssuer, resolvingAgainstBaseURL: false),
239
+ components.query == nil,
240
+ components.path.isEmpty || components.path == "/" else {
241
+ throw OAuthClientError.invalidIssuer
242
+ }
243
+ components.path = ""
244
+ guard let canonicalIssuer = components.url else { throw OAuthClientError.invalidIssuer }
245
+ let url = canonicalIssuer.appending(path: ".well-known/oauth-authorization-server")
246
+ var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 20)
247
+ request.setValue("application/json", forHTTPHeaderField: "Accept")
248
+ let (data, response) = try await URLSession.shared.data(for: request)
249
+ guard let http = response as? HTTPURLResponse, http.statusCode == 200,
250
+ let metadata = try? JSONDecoder().decode(OAuthAuthorizationServerMetadata.self, from: data),
251
+ metadata.issuer == canonicalIssuer.absoluteString.trimmingCharacters(in: CharacterSet(charactersIn: "/")) else {
252
+ throw OAuthClientError.invalidMetadata
253
+ }
254
+ return metadata
255
+ }
256
+
257
+ private static func tokenRequest(endpoint: String, fields: [String: String]) async throws -> OAuthTokenResponse {
258
+ guard let url = secureEndpoint(endpoint) else { throw OAuthClientError.invalidMetadata }
259
+ var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 30)
260
+ request.httpMethod = "POST"
261
+ request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
262
+ request.setValue("application/json", forHTTPHeaderField: "Accept")
263
+ var form = URLComponents()
264
+ form.queryItems = fields.sorted { $0.key < $1.key }.map { URLQueryItem(name: $0.key, value: $0.value) }
265
+ request.httpBody = form.percentEncodedQuery?.data(using: .utf8)
266
+ let (data, response) = try await URLSession.shared.data(for: request)
267
+ guard let http = response as? HTTPURLResponse else { throw OAuthClientError.invalidMetadata }
268
+ guard (200..<300).contains(http.statusCode), let tokens = try? JSONDecoder().decode(OAuthTokenResponse.self, from: data) else {
269
+ let reason = (try? JSONSerialization.jsonObject(with: data) as? [String: Any])?["error_description"] as? String
270
+ throw OAuthClientError.tokenExchangeFailed(reason ?? "OAuth token exchange failed.")
271
+ }
272
+ guard tokens.tokenType.lowercased() == "bearer" else { throw OAuthClientError.tokenExchangeFailed("OAuth server returned an unsupported token type.") }
273
+ return tokens
274
+ }
275
+ }
276
+
277
+ actor CredentialBroker {
278
+ private let store = SecureStore()
279
+ private let account = "oauth-credential"
280
+ private var credential: OAuthCredential?
281
+ private var directToken: String?
282
+
283
+ init() {
284
+ if let data = try? store.data(account: account) {
285
+ credential = try? JSONDecoder().decode(OAuthCredential.self, from: data)
286
+ }
287
+ directToken = try? store.string(account: "direct-token")
288
+ }
289
+
290
+ func accessToken() async throws -> String? {
291
+ if let directToken { return directToken }
292
+ guard var credential else { return nil }
293
+ if credential.expiresAt.timeIntervalSinceNow < 60 {
294
+ credential = try await OAuthClient.refresh(credential)
295
+ self.credential = credential
296
+ try store.set(JSONEncoder().encode(credential), account: account)
297
+ }
298
+ return credential.accessToken
299
+ }
300
+
301
+ func save(_ credential: OAuthCredential) throws {
302
+ self.credential = credential
303
+ directToken = nil
304
+ try store.remove(account: "direct-token")
305
+ try store.set(JSONEncoder().encode(credential), account: account)
306
+ }
307
+
308
+ func saveDirectToken(_ value: String) throws {
309
+ credential = nil
310
+ directToken = value
311
+ try store.remove(account: account)
312
+ try store.setString(value, account: "direct-token")
313
+ }
314
+
315
+ func clear() throws {
316
+ credential = nil
317
+ directToken = nil
318
+ try store.remove(account: account)
319
+ try store.remove(account: "direct-token")
320
+ }
321
+ }