auramaxx 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (418) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +77 -0
  3. package/apps/desktop-electron/main.js +428 -0
  4. package/bin/auramaxx.js +1063 -0
  5. package/docs/ADAPTERS.md +466 -0
  6. package/docs/AGENT_SETUP.md +159 -0
  7. package/docs/API.md +127 -0
  8. package/docs/APPS.md +199 -0
  9. package/docs/ARCHITECTURE.md +235 -0
  10. package/docs/AUTH.md +318 -0
  11. package/docs/BEST-PRACTICES.md +82 -0
  12. package/docs/CLI.md +141 -0
  13. package/docs/DESKTOP_ELECTRON.md +26 -0
  14. package/docs/DEVELOPING-APPS.md +453 -0
  15. package/docs/MCP.md +122 -0
  16. package/docs/PACKAGING_POLICY.md +19 -0
  17. package/docs/PERMISSION.md +137 -0
  18. package/docs/PROTOCOL.md +142 -0
  19. package/docs/README.md +50 -0
  20. package/docs/SKILLS.md +132 -0
  21. package/docs/TROUBLESHOOTING.md +376 -0
  22. package/docs/WORKSPACE.md +673 -0
  23. package/docs/agent-auth.md +14 -0
  24. package/docs/api/authentication.md +79 -0
  25. package/docs/api/secrets/api-keys.md +28 -0
  26. package/docs/api/secrets/credentials.md +80 -0
  27. package/docs/api/secrets/sharing.md +48 -0
  28. package/docs/api/system.md +41 -0
  29. package/docs/api/wallets/apps-strategies.md +66 -0
  30. package/docs/api/wallets/core.md +46 -0
  31. package/docs/api/wallets/data-portfolio.md +42 -0
  32. package/docs/aura-file.md +48 -0
  33. package/docs/core-concepts/FEATURES.md +114 -0
  34. package/docs/credentials.md +120 -0
  35. package/docs/external/HOW_TO_AURAMAXX/GETTING_SECRETS.md +33 -0
  36. package/docs/external/HOW_TO_AURAMAXX/README.md +45 -0
  37. package/docs/external/getting-started.md +10 -0
  38. package/docs/external/overview.md +19 -0
  39. package/docs/external/persona-paths.md +7 -0
  40. package/docs/external/share-secret.md +76 -0
  41. package/docs/external/why-aura.md +7 -0
  42. package/docs/security.md +227 -0
  43. package/docs/templates/RELEASE_NOTES_TEMPLATE.md +22 -0
  44. package/docs/wallet/AI.md +508 -0
  45. package/docs/wallet/DEVELOPING-STRATEGIES.md +713 -0
  46. package/docs/wallet/README.md +47 -0
  47. package/docs/wallet/STRATEGY.md +89 -0
  48. package/next.config.ts +28 -0
  49. package/package.json +167 -0
  50. package/postcss.config.mjs +8 -0
  51. package/prisma/migrations/20260214170000_baseline/migration.sql +511 -0
  52. package/prisma/migrations/20260216214537_add_passkey_model/migration.sql +18 -0
  53. package/prisma/migrations/20260217150500_add_credential_access_audit/migration.sql +31 -0
  54. package/prisma/migrations/20260222090000_update_admin_ttl_default/migration.sql +10 -0
  55. package/prisma/migrations/migration_lock.toml +3 -0
  56. package/prisma/schema.prisma +447 -0
  57. package/public/logo.webp +0 -0
  58. package/scripts/add-app.js +245 -0
  59. package/server/abi/SwapHelper.json +438 -0
  60. package/server/cli/approval.ts +447 -0
  61. package/server/cli/commands/actions.ts +474 -0
  62. package/server/cli/commands/api.ts +220 -0
  63. package/server/cli/commands/apikey.ts +277 -0
  64. package/server/cli/commands/app.ts +204 -0
  65. package/server/cli/commands/auth.ts +464 -0
  66. package/server/cli/commands/cron.ts +24 -0
  67. package/server/cli/commands/diary.ts +274 -0
  68. package/server/cli/commands/doctor.ts +1247 -0
  69. package/server/cli/commands/env.ts +476 -0
  70. package/server/cli/commands/experimental.ts +69 -0
  71. package/server/cli/commands/init.ts +798 -0
  72. package/server/cli/commands/lock.ts +157 -0
  73. package/server/cli/commands/mcp.ts +285 -0
  74. package/server/cli/commands/quickhack.ts +86 -0
  75. package/server/cli/commands/release-check.ts +231 -0
  76. package/server/cli/commands/restore.ts +314 -0
  77. package/server/cli/commands/service.ts +320 -0
  78. package/server/cli/commands/shell-hook.ts +512 -0
  79. package/server/cli/commands/skill.ts +216 -0
  80. package/server/cli/commands/start.ts +139 -0
  81. package/server/cli/commands/status.ts +59 -0
  82. package/server/cli/commands/stop.ts +36 -0
  83. package/server/cli/commands/token.ts +180 -0
  84. package/server/cli/commands/unlock.ts +50 -0
  85. package/server/cli/commands/vault.ts +1323 -0
  86. package/server/cli/commands/wallet.ts +209 -0
  87. package/server/cli/index.ts +280 -0
  88. package/server/cli/lib/approval-poll.ts +94 -0
  89. package/server/cli/lib/aura-parser.ts +64 -0
  90. package/server/cli/lib/credential-create.ts +74 -0
  91. package/server/cli/lib/credential-resolve.ts +280 -0
  92. package/server/cli/lib/dotenv-migrate.ts +116 -0
  93. package/server/cli/lib/dotenv-parser.ts +146 -0
  94. package/server/cli/lib/escalation.ts +57 -0
  95. package/server/cli/lib/http.ts +91 -0
  96. package/server/cli/lib/init-steps.ts +76 -0
  97. package/server/cli/lib/local-agent-trust.ts +45 -0
  98. package/server/cli/lib/lock-unlock-helper.ts +71 -0
  99. package/server/cli/lib/process.ts +162 -0
  100. package/server/cli/lib/prompt.ts +294 -0
  101. package/server/cli/lib/theme.ts +240 -0
  102. package/server/cli/socket.ts +579 -0
  103. package/server/cli/transport-client.ts +50 -0
  104. package/server/cron/index.ts +137 -0
  105. package/server/cron/job.ts +31 -0
  106. package/server/cron/jobs/balance-sync.ts +436 -0
  107. package/server/cron/jobs/incoming-scan.ts +506 -0
  108. package/server/cron/jobs/native-price.ts +70 -0
  109. package/server/cron/jobs/orphan-cleanup.ts +40 -0
  110. package/server/cron/jobs/strategy-runner.ts +175 -0
  111. package/server/cron/scheduler.ts +125 -0
  112. package/server/index.ts +420 -0
  113. package/server/lib/adapters/factory.ts +119 -0
  114. package/server/lib/adapters/index.ts +19 -0
  115. package/server/lib/adapters/router.ts +297 -0
  116. package/server/lib/adapters/telegram.ts +645 -0
  117. package/server/lib/adapters/types.ts +89 -0
  118. package/server/lib/adapters/webhook.ts +95 -0
  119. package/server/lib/address.ts +49 -0
  120. package/server/lib/agent-auth/contracts.ts +1194 -0
  121. package/server/lib/agent-profiles.ts +419 -0
  122. package/server/lib/ai.ts +285 -0
  123. package/server/lib/api-registry/contracts.ts +86 -0
  124. package/server/lib/api-registry/validation.ts +172 -0
  125. package/server/lib/apikey-migration.ts +258 -0
  126. package/server/lib/app-installer.ts +505 -0
  127. package/server/lib/app-tokens.ts +247 -0
  128. package/server/lib/approval-link.ts +27 -0
  129. package/server/lib/auth.ts +314 -0
  130. package/server/lib/auto-execute.ts +160 -0
  131. package/server/lib/batch.ts +242 -0
  132. package/server/lib/cold.ts +1048 -0
  133. package/server/lib/config.ts +408 -0
  134. package/server/lib/credential-access-audit.ts +85 -0
  135. package/server/lib/credential-access-policy.ts +111 -0
  136. package/server/lib/credential-health.ts +343 -0
  137. package/server/lib/credential-import.ts +608 -0
  138. package/server/lib/credential-scope.ts +102 -0
  139. package/server/lib/credential-shares.ts +190 -0
  140. package/server/lib/credential-transport.ts +533 -0
  141. package/server/lib/credential-vault.ts +77 -0
  142. package/server/lib/credentials.ts +422 -0
  143. package/server/lib/crypto.ts +8 -0
  144. package/server/lib/db.ts +58 -0
  145. package/server/lib/defaults.ts +386 -0
  146. package/server/lib/dex/index.ts +80 -0
  147. package/server/lib/dex/relay.ts +235 -0
  148. package/server/lib/dex/types.ts +59 -0
  149. package/server/lib/dex/uniswap.ts +370 -0
  150. package/server/lib/diary.ts +34 -0
  151. package/server/lib/dont-ask-again-policy.ts +41 -0
  152. package/server/lib/e2e-agent/artifacts.ts +36 -0
  153. package/server/lib/e2e-agent/contracts.ts +112 -0
  154. package/server/lib/e2e-agent/validation.ts +135 -0
  155. package/server/lib/encrypt.ts +114 -0
  156. package/server/lib/error.ts +20 -0
  157. package/server/lib/events.ts +217 -0
  158. package/server/lib/feature-flags.ts +93 -0
  159. package/server/lib/hot.ts +357 -0
  160. package/server/lib/human-action-summary.ts +80 -0
  161. package/server/lib/key-fingerprint.ts +28 -0
  162. package/server/lib/logger.ts +340 -0
  163. package/server/lib/network.ts +137 -0
  164. package/server/lib/notifications.ts +230 -0
  165. package/server/lib/oauth2-refresh.ts +241 -0
  166. package/server/lib/oursecret.ts +71 -0
  167. package/server/lib/passkey-credential.ts +360 -0
  168. package/server/lib/passkey.ts +68 -0
  169. package/server/lib/permissions.ts +299 -0
  170. package/server/lib/pino.ts +24 -0
  171. package/server/lib/policy-preview.ts +138 -0
  172. package/server/lib/price.ts +338 -0
  173. package/server/lib/prices.ts +34 -0
  174. package/server/lib/project-scope.ts +297 -0
  175. package/server/lib/resolve-action.ts +328 -0
  176. package/server/lib/resolve.ts +36 -0
  177. package/server/lib/secret-gist-share.ts +296 -0
  178. package/server/lib/sessions.ts +634 -0
  179. package/server/lib/socket-path.ts +56 -0
  180. package/server/lib/solana/connection.ts +26 -0
  181. package/server/lib/solana/jupiter.ts +128 -0
  182. package/server/lib/solana/transfer.ts +108 -0
  183. package/server/lib/solana/wallet.ts +136 -0
  184. package/server/lib/strategy/emits.ts +21 -0
  185. package/server/lib/strategy/engine.ts +1305 -0
  186. package/server/lib/strategy/executor.ts +115 -0
  187. package/server/lib/strategy/hook-context.ts +159 -0
  188. package/server/lib/strategy/hooks.ts +990 -0
  189. package/server/lib/strategy/index.ts +28 -0
  190. package/server/lib/strategy/installer.ts +305 -0
  191. package/server/lib/strategy/loader.ts +256 -0
  192. package/server/lib/strategy/message.ts +237 -0
  193. package/server/lib/strategy/repository.ts +218 -0
  194. package/server/lib/strategy/session-logger.ts +693 -0
  195. package/server/lib/strategy/sources.ts +288 -0
  196. package/server/lib/strategy/state.ts +189 -0
  197. package/server/lib/strategy/templates.ts +403 -0
  198. package/server/lib/strategy/tick.ts +404 -0
  199. package/server/lib/strategy/types.ts +230 -0
  200. package/server/lib/swap.ts +3 -0
  201. package/server/lib/temp.ts +86 -0
  202. package/server/lib/token-metadata.ts +86 -0
  203. package/server/lib/token-safety.ts +200 -0
  204. package/server/lib/token-search.ts +444 -0
  205. package/server/lib/totp.ts +194 -0
  206. package/server/lib/transactions.ts +123 -0
  207. package/server/lib/transport.ts +84 -0
  208. package/server/lib/txhistory/decoder.ts +262 -0
  209. package/server/lib/txhistory/enricher.ts +652 -0
  210. package/server/lib/txhistory/index.ts +391 -0
  211. package/server/lib/txhistory/signatures.ts +59 -0
  212. package/server/lib/update-check.ts +35 -0
  213. package/server/lib/verified-summary.ts +414 -0
  214. package/server/lib/view-registry.ts +80 -0
  215. package/server/mcp/profile-policy.ts +30 -0
  216. package/server/mcp/server.ts +1589 -0
  217. package/server/mcp/tools.ts +276 -0
  218. package/server/middleware/auth.ts +119 -0
  219. package/server/middleware/requestLogger.ts +84 -0
  220. package/server/routes/actions.ts +539 -0
  221. package/server/routes/adapters.ts +711 -0
  222. package/server/routes/addressbook.ts +113 -0
  223. package/server/routes/ai.ts +34 -0
  224. package/server/routes/apikeys.ts +343 -0
  225. package/server/routes/apps.ts +601 -0
  226. package/server/routes/auth.ts +406 -0
  227. package/server/routes/backup.ts +404 -0
  228. package/server/routes/batch.ts +270 -0
  229. package/server/routes/bookmarks.ts +162 -0
  230. package/server/routes/credential-shares.ts +380 -0
  231. package/server/routes/credential-vaults.ts +159 -0
  232. package/server/routes/credentials.ts +1782 -0
  233. package/server/routes/dashboard.ts +97 -0
  234. package/server/routes/defaults.ts +124 -0
  235. package/server/routes/flags.ts +11 -0
  236. package/server/routes/fund.ts +225 -0
  237. package/server/routes/heartbeat.ts +375 -0
  238. package/server/routes/import.ts +364 -0
  239. package/server/routes/launch.ts +665 -0
  240. package/server/routes/lock.ts +54 -0
  241. package/server/routes/logs.ts +68 -0
  242. package/server/routes/nuke.ts +111 -0
  243. package/server/routes/passkey-credentials.ts +99 -0
  244. package/server/routes/passkey.ts +366 -0
  245. package/server/routes/portfolio.ts +217 -0
  246. package/server/routes/price.ts +63 -0
  247. package/server/routes/resolve.ts +31 -0
  248. package/server/routes/security.ts +45 -0
  249. package/server/routes/send-evm.ts +241 -0
  250. package/server/routes/send-solana.ts +281 -0
  251. package/server/routes/send.ts +178 -0
  252. package/server/routes/setup.ts +210 -0
  253. package/server/routes/strategy.ts +894 -0
  254. package/server/routes/swap-evm.ts +352 -0
  255. package/server/routes/swap-solana.ts +176 -0
  256. package/server/routes/swap.ts +356 -0
  257. package/server/routes/token.ts +247 -0
  258. package/server/routes/unlock.ts +467 -0
  259. package/server/routes/views.ts +41 -0
  260. package/server/routes/wallet-assets.ts +361 -0
  261. package/server/routes/wallet-transactions.ts +515 -0
  262. package/server/routes/wallet.ts +709 -0
  263. package/server/types.ts +146 -0
  264. package/shared/credential-field-schema.ts +248 -0
  265. package/skills/auramaxx/HEARTBEAT.md +78 -0
  266. package/skills/auramaxx/SKILL.md +745 -0
  267. package/skills/auramaxx/docs/AGENT_SETUP.md +155 -0
  268. package/skills/auramaxx/docs/API.md +127 -0
  269. package/skills/auramaxx/docs/AUTH.md +318 -0
  270. package/skills/auramaxx/docs/CLI.md +130 -0
  271. package/skills/auramaxx/docs/MCP.md +122 -0
  272. package/skills/auramaxx/docs/TROUBLESHOOTING.md +357 -0
  273. package/skills/auramaxx/docs/WORKSPACE.md +673 -0
  274. package/skills/auramaxx/docs/security.md +227 -0
  275. package/skills/task-lifecycle/SKILL.md +378 -0
  276. package/src/app/api/[...doc]/page.tsx +36 -0
  277. package/src/app/api/agent-requests/route.ts +30 -0
  278. package/src/app/api/apps/install/route.ts +132 -0
  279. package/src/app/api/apps/manifests/route.ts +16 -0
  280. package/src/app/api/apps/static/[...path]/route.ts +57 -0
  281. package/src/app/api/docs/plain/route.ts +74 -0
  282. package/src/app/api/events/route.ts +92 -0
  283. package/src/app/api/page.tsx +290 -0
  284. package/src/app/api/workspace/[id]/apps/[wid]/route.ts +119 -0
  285. package/src/app/api/workspace/[id]/apps/route.ts +81 -0
  286. package/src/app/api/workspace/[id]/export/route.ts +67 -0
  287. package/src/app/api/workspace/[id]/route.ts +168 -0
  288. package/src/app/api/workspace/auth.ts +40 -0
  289. package/src/app/api/workspace/config/route.ts +121 -0
  290. package/src/app/api/workspace/import/route.ts +127 -0
  291. package/src/app/api/workspace/route.ts +116 -0
  292. package/src/app/app-legacy-do-not-use/page.tsx +2245 -0
  293. package/src/app/apple-icon.png +0 -0
  294. package/src/app/approve/[actionId]/page.tsx +409 -0
  295. package/src/app/docs/DocsPageContent.tsx +269 -0
  296. package/src/app/docs/[...doc]/page.tsx +41 -0
  297. package/src/app/docs/page.tsx +38 -0
  298. package/src/app/favicon.ico +0 -0
  299. package/src/app/globals.css +819 -0
  300. package/src/app/health/page.tsx +5 -0
  301. package/src/app/hello/page.tsx +102 -0
  302. package/src/app/icon.png +0 -0
  303. package/src/app/layout.tsx +39 -0
  304. package/src/app/page.tsx +1964 -0
  305. package/src/app/privacy/page.tsx +63 -0
  306. package/src/app/providers.tsx +87 -0
  307. package/src/app/share/[token]/page.tsx +295 -0
  308. package/src/app/terms/page.tsx +80 -0
  309. package/src/components/ChainSelector.tsx +44 -0
  310. package/src/components/HumanActionBar.tsx +697 -0
  311. package/src/components/NotificationDrawer.tsx +387 -0
  312. package/src/components/PasskeyEnrollmentPrompt.tsx +235 -0
  313. package/src/components/apps/AgentKeysApp.tsx +490 -0
  314. package/src/components/apps/App.tsx +153 -0
  315. package/src/components/apps/AppGrid.tsx +15 -0
  316. package/src/components/apps/DetailedAddressDrawer.tsx +325 -0
  317. package/src/components/apps/DraggableApp.tsx +562 -0
  318. package/src/components/apps/IFrameApp.tsx +73 -0
  319. package/src/components/apps/LogsApp.tsx +360 -0
  320. package/src/components/apps/SendApp.tsx +394 -0
  321. package/src/components/apps/SetupWizardApp.tsx +1004 -0
  322. package/src/components/apps/SystemDefaultsApp.tsx +845 -0
  323. package/src/components/apps/ThirdPartyApp.tsx +428 -0
  324. package/src/components/apps/TokenApp.tsx +319 -0
  325. package/src/components/apps/TransactionsApp.tsx +438 -0
  326. package/src/components/apps/WalletDetailApp.tsx +1505 -0
  327. package/src/components/apps/index.ts +13 -0
  328. package/src/components/design-system/Button.tsx +88 -0
  329. package/src/components/design-system/ChainIndicator.tsx +65 -0
  330. package/src/components/design-system/ChainSelector.tsx +147 -0
  331. package/src/components/design-system/ConfirmationModal.tsx +107 -0
  332. package/src/components/design-system/ConfirmationPopover.tsx +81 -0
  333. package/src/components/design-system/DownloadButton.tsx +149 -0
  334. package/src/components/design-system/Drawer.tsx +133 -0
  335. package/src/components/design-system/FilterDropdown.tsx +183 -0
  336. package/src/components/design-system/ItemPicker.tsx +157 -0
  337. package/src/components/design-system/Modal.tsx +296 -0
  338. package/src/components/design-system/Popover.tsx +142 -0
  339. package/src/components/design-system/TextInput.tsx +85 -0
  340. package/src/components/design-system/Toggle.tsx +65 -0
  341. package/src/components/design-system/TyvekCollapsibleSection.tsx +55 -0
  342. package/src/components/design-system/index.ts +14 -0
  343. package/src/components/docs/ClientSideMarkdown.tsx +51 -0
  344. package/src/components/docs/DocsSearchBar.tsx +118 -0
  345. package/src/components/docs/DocsThemeToggle.tsx +38 -0
  346. package/src/components/docs/PersistentDocGroup.tsx +91 -0
  347. package/src/components/docs/ShareUrlButton.tsx +33 -0
  348. package/src/components/docs/SidebarScrollMemory.tsx +56 -0
  349. package/src/components/health/CredentialHealthDashboard.tsx +214 -0
  350. package/src/components/icons/ChainIcons.tsx +72 -0
  351. package/src/components/layout/AppStoreDrawer.tsx +369 -0
  352. package/src/components/layout/ContentArea.tsx +21 -0
  353. package/src/components/layout/CreateViewModal.tsx +88 -0
  354. package/src/components/layout/LeftRail.tsx +114 -0
  355. package/src/components/layout/TabBar.tsx +284 -0
  356. package/src/components/layout/WalletSidebar.tsx +1030 -0
  357. package/src/components/layout/index.ts +6 -0
  358. package/src/components/marketing/AuraMaxxSpecOverlay.tsx +653 -0
  359. package/src/components/marketing/DeviceMorphExperience.tsx +216 -0
  360. package/src/components/vault/ApiKeysConsole.tsx +1272 -0
  361. package/src/components/vault/AuditConsole.tsx +600 -0
  362. package/src/components/vault/CredentialDetail.tsx +625 -0
  363. package/src/components/vault/CredentialEmpty.tsx +55 -0
  364. package/src/components/vault/CredentialField.tsx +583 -0
  365. package/src/components/vault/CredentialForm.tsx +1484 -0
  366. package/src/components/vault/CredentialList.tsx +265 -0
  367. package/src/components/vault/CredentialRow.tsx +130 -0
  368. package/src/components/vault/CredentialShareModal.tsx +273 -0
  369. package/src/components/vault/CredentialVault.tsx +1662 -0
  370. package/src/components/vault/CredentialWalletWidget.tsx +103 -0
  371. package/src/components/vault/DocsConsole.tsx +113 -0
  372. package/src/components/vault/ImportCredentialsModal.tsx +578 -0
  373. package/src/components/vault/LargeTypeModal.tsx +88 -0
  374. package/src/components/vault/PasswordGenerator.tsx +232 -0
  375. package/src/components/vault/TOTPDisplay.tsx +108 -0
  376. package/src/components/vault/TotpSetupPanel.tsx +198 -0
  377. package/src/components/vault/VaultSidebar.tsx +881 -0
  378. package/src/components/vault/credentialFormName.ts +91 -0
  379. package/src/components/vault/hooks/useVaultKeyboardShortcuts.ts +69 -0
  380. package/src/components/vault/types.ts +56 -0
  381. package/src/context/AuthContext.tsx +365 -0
  382. package/src/context/PriceContext.tsx +113 -0
  383. package/src/context/ThemeContext.tsx +164 -0
  384. package/src/context/WebSocketContext.tsx +269 -0
  385. package/src/context/WorkspaceContext.tsx +668 -0
  386. package/src/hooks/index.ts +4 -0
  387. package/src/hooks/useAgentActions.ts +552 -0
  388. package/src/hooks/useBalance.ts +103 -0
  389. package/src/hooks/useBalances.ts +129 -0
  390. package/src/hooks/useTheme.ts +156 -0
  391. package/src/instrumentation.ts +12 -0
  392. package/src/lib/api-docs.ts +154 -0
  393. package/src/lib/api.ts +474 -0
  394. package/src/lib/app-loader.ts +148 -0
  395. package/src/lib/app-registry.ts +178 -0
  396. package/src/lib/app-sdk.ts +157 -0
  397. package/src/lib/audit-console-adapter.ts +151 -0
  398. package/src/lib/auth-client.ts +75 -0
  399. package/src/lib/config.ts +74 -0
  400. package/src/lib/credential-field-schema.ts +11 -0
  401. package/src/lib/crypto.ts +112 -0
  402. package/src/lib/db.ts +21 -0
  403. package/src/lib/docs.ts +544 -0
  404. package/src/lib/events.ts +363 -0
  405. package/src/lib/pino.ts +24 -0
  406. package/src/lib/theme-handlers.ts +168 -0
  407. package/src/lib/theme.ts +351 -0
  408. package/src/lib/tokenData.ts +378 -0
  409. package/src/lib/totp-import.ts +57 -0
  410. package/src/lib/vault-crypto.ts +129 -0
  411. package/src/lib/view-registry.ts +57 -0
  412. package/src/lib/websocket-server.ts +302 -0
  413. package/src/lib/websocket-setup.ts +79 -0
  414. package/src/lib/wordlist.ts +2050 -0
  415. package/src/lib/workspace-handlers.ts +285 -0
  416. package/start.sh +170 -0
  417. package/tailwind.config.ts +99 -0
  418. package/tsconfig.json +42 -0
@@ -0,0 +1,798 @@
1
+ /**
2
+ * auramaxx init — First-time setup
3
+ *
4
+ * 1. Create directories + run migrations + generate Prisma client
5
+ * 2. Start server headless (Express only)
6
+ * 3. If vault exists → start dashboard, print "Already initialized", keep running
7
+ * 4. Prompt: Dashboard or Terminal?
8
+ * a. Dashboard → start dashboard + open browser + poll until vault created
9
+ * b. Terminal → interactive vault creation + optional config
10
+ * 5. Print cold wallet address + funding guidance
11
+ * 6. Keep servers running
12
+ */
13
+
14
+ import * as fs from 'fs';
15
+ import * as path from 'path';
16
+ import * as os from 'os';
17
+ import { exec, spawn, ChildProcess } from 'child_process';
18
+ import { fetchSetupStatus, fetchPublicKey, fetchJson, waitForServer, SetupStatus } from '../lib/http';
19
+ import { startServer, stopServer, findProjectRoot } from '../lib/process';
20
+ import { ensureDirectories, runMigrations, generatePrismaClient } from '../lib/init-steps';
21
+ import { promptPassword, promptInput, promptConfirm, promptSelect } from '../lib/prompt';
22
+ import { encryptPassword, generateAgentKeypair } from '../transport-client';
23
+ import { getErrorMessage } from '../../lib/error';
24
+ import { printBanner, printSection, printSeedPhrase } from '../lib/theme';
25
+ import { migrateDotenv } from '../lib/dotenv-migrate';
26
+ import { parseAuraFile } from '../lib/aura-parser';
27
+ import { bootstrapViaSocket, generateEphemeralKeypair } from '../../lib/credential-transport';
28
+ import { createCredentialViaApi, getPrimaryVaultId } from '../lib/credential-create';
29
+ import { resolveLocalAgentModeChoice, persistLocalAgentTrustDefaults } from '../lib/local-agent-trust';
30
+ import { loadServiceIfNeeded, isServiceInstalled } from './service';
31
+
32
+ let serverChildren: ChildProcess[] = [];
33
+
34
+ // SIGINT handler — if launchd is managing the servers, just detach cleanly.
35
+ // Otherwise kill server processes.
36
+ function cleanup() {
37
+ if (serverChildren.length > 0) {
38
+ if (isServiceInstalled()) {
39
+ // Service is registered — load it so servers keep running after we exit.
40
+ loadServiceIfNeeded();
41
+ console.log('\n\nServers will continue running in the background.');
42
+ console.log('Use `auramaxx stop` to stop.');
43
+ } else {
44
+ console.log('\n\nShutting down...');
45
+ stopServer();
46
+ }
47
+ serverChildren = [];
48
+ }
49
+ process.exit(0);
50
+ }
51
+
52
+ process.on('SIGINT', cleanup);
53
+ process.on('SIGTERM', cleanup);
54
+
55
+ function openBrowser(url: string) {
56
+ const platform = process.platform;
57
+ const cmd =
58
+ platform === 'darwin' ? `open "${url}"` :
59
+ platform === 'win32' ? `start "${url}"` :
60
+ `xdg-open "${url}"`;
61
+
62
+ exec(cmd, (err) => {
63
+ if (err) {
64
+ // Don't fail — just tell the user to open manually
65
+ console.log(` Could not open browser automatically.`);
66
+ console.log(` Open this URL manually: ${url}\n`);
67
+ }
68
+ });
69
+ }
70
+
71
+ const DASHBOARD_PORT = process.env.DASHBOARD_PORT || '4747';
72
+
73
+ function startDashboard(): ChildProcess {
74
+ const root = findProjectRoot();
75
+ const dashboard = spawn('npx', ['next', 'dev', '-p', DASHBOARD_PORT], {
76
+ cwd: root,
77
+ env: { ...process.env, BYPASS_RATE_LIMIT: 'true' },
78
+ stdio: 'ignore',
79
+ detached: true,
80
+ });
81
+ dashboard.unref();
82
+ return dashboard;
83
+ }
84
+
85
+ // ─── Mode selection ──────────────────────────────────────────────
86
+
87
+ async function promptSetupMode(): Promise<'dashboard' | 'terminal'> {
88
+ printSection('Setup Mode', 'Choose how you would like to set up your vault.');
89
+
90
+ const mode = await promptSelect(
91
+ ' How would you like to set up your vault?',
92
+ [
93
+ { value: 'dashboard', label: 'dashboard', aliases: ['1', 'browser'] },
94
+ { value: 'terminal', label: 'terminal', aliases: ['2', 'cli'] },
95
+ ],
96
+ 'dashboard',
97
+ );
98
+ return mode as 'dashboard' | 'terminal';
99
+ }
100
+
101
+ // ─── Dashboard flow ──────────────────────────────────────────────
102
+
103
+ async function dashboardFlow() {
104
+ printSection('Dashboard Setup', 'Browser-guided vault onboarding.');
105
+ const dashboard = startDashboard();
106
+ serverChildren.push(dashboard);
107
+
108
+ const dashboardUrl = `http://localhost:${DASHBOARD_PORT}`;
109
+ console.log(' Waiting for dashboard to start...');
110
+
111
+ // Wait for Next.js dev server to be ready before opening browser
112
+ const dashboardStart = Date.now();
113
+ while (Date.now() - dashboardStart < 30000) {
114
+ try {
115
+ const res = await fetch(dashboardUrl);
116
+ if (res.ok) break;
117
+ } catch {
118
+ // Not ready yet
119
+ }
120
+ await new Promise((r) => setTimeout(r, 1000));
121
+ }
122
+
123
+ console.log(' Opening dashboard in browser...');
124
+ openBrowser(dashboardUrl);
125
+ console.log(` Create your vault at ${dashboardUrl}\n`);
126
+ console.log(' Waiting for vault creation...');
127
+
128
+ // Poll until vault is created
129
+ while (true) {
130
+ await new Promise((r) => setTimeout(r, 2000));
131
+ try {
132
+ const check = await fetchSetupStatus();
133
+ if (check.hasWallet) {
134
+ console.log('');
135
+ console.log(' Vault created!\n');
136
+ // Vault is ready — activate the launchd service so servers survive Ctrl+C
137
+ loadServiceIfNeeded();
138
+ printBanner('TIME TO AURAMAXX');
139
+ // Password-manager focus for now: hide wallet funding guidance in onboarding output.
140
+ // console.log(` Your cold wallet address: ${check.address}`);
141
+ // console.log(' Send ETH on Base to this address to fund your wallet.\n');
142
+ console.log(` Dashboard ready at ${dashboardUrl}`);
143
+ if (isServiceInstalled()) {
144
+ console.log(' Servers are running in the background. Use `auramaxx stop` to stop.\n');
145
+ } else {
146
+ console.log(' Servers are running. Press Ctrl+C to stop.\n');
147
+ }
148
+ break;
149
+ }
150
+ } catch {
151
+ // Server might be briefly unavailable, keep polling
152
+ }
153
+ }
154
+ }
155
+
156
+ // ─── Terminal flow ───────────────────────────────────────────────
157
+
158
+ async function terminalFlow(): Promise<string> {
159
+ // Step 1: Password
160
+ printSection('Terminal Setup', 'Local interactive vault onboarding.');
161
+ const password = await promptPasswordWithConfirmation();
162
+
163
+ // Step 2: Create vault
164
+ console.log('\n Creating vault...');
165
+ const publicKey = await fetchPublicKey();
166
+ const encrypted = encryptPassword(password, publicKey);
167
+ const { publicKey: agentPubkey } = generateAgentKeypair();
168
+
169
+ const vault = await fetchJson<{
170
+ success: boolean;
171
+ address: string;
172
+ mnemonic: string;
173
+ token: string;
174
+ }>('/setup', { body: { encrypted, pubkey: agentPubkey } });
175
+
176
+ console.log(' Vault created!\n');
177
+
178
+ // Step 3: Display seed phrase
179
+ printSeedPhrase(vault.mnemonic);
180
+
181
+ let confirmed = await promptConfirm(' Have you saved your seed phrase?');
182
+ while (!confirmed) {
183
+ console.log('\n Please save the phrase above, then confirm to continue.');
184
+ confirmed = await promptConfirm(' Have you saved your seed phrase?');
185
+ }
186
+
187
+ const token = vault.token;
188
+
189
+ await configureLocalSocketTrust(token);
190
+
191
+ // Optional configuration is intentionally disabled for now.
192
+ /*
193
+ ── Optional Configuration ──
194
+
195
+ Press Enter to skip any step.
196
+
197
+ Anthropic API key (sk-ant-...):
198
+ Alchemy API key:
199
+ Telegram bot token:
200
+ */
201
+ // await configureApiKey(token, 'anthropic', 'Anthropic API key', 'sk-ant-...');
202
+ // await configureApiKey(token, 'alchemy', 'Alchemy API key', '');
203
+ // await configureTelegram(token);
204
+
205
+ // Step 4: Summary
206
+ loadServiceIfNeeded();
207
+ printBanner('TIME TO AURAMAXX');
208
+ // Password-manager focus for now: hide wallet funding/config summary in onboarding.
209
+ // console.log(` Cold wallet address: ${vault.address}`);
210
+ // console.log(' Send ETH on Base to this address to fund your wallet.\n');
211
+ // const status = await fetchSetupStatus();
212
+ // printConfigSummary(status);
213
+
214
+ if (isServiceInstalled()) {
215
+ console.log(' Servers are running in the background. Use `auramaxx stop` to stop.\n');
216
+ } else {
217
+ console.log(' Servers are running. Press Ctrl+C to stop.\n');
218
+ }
219
+ return token;
220
+ }
221
+
222
+ async function promptPasswordWithConfirmation(): Promise<string> {
223
+ while (true) {
224
+ const password = await promptPassword(' Enter vault password');
225
+ if (password.length < 8) {
226
+ console.log(' Password must be at least 8 characters. Try again.\n');
227
+ continue;
228
+ }
229
+
230
+ const confirm = await promptPassword(' Confirm password');
231
+ if (password !== confirm) {
232
+ console.log(' Passwords do not match. Try again.\n');
233
+ continue;
234
+ }
235
+
236
+ return password;
237
+ }
238
+ }
239
+
240
+ async function configureLocalSocketTrust(token: string): Promise<void> {
241
+ printSection('Local Agent Trust', 'Choose default local agent mode.');
242
+
243
+ const profile = resolveLocalAgentModeChoice(
244
+ await promptSelect(
245
+ ' Local agent mode',
246
+ [
247
+ { value: 'dev', label: 'dev', aliases: ['1', 'recommended'] },
248
+ { value: 'strict', label: 'strict', aliases: ['2'] },
249
+ { value: 'admin', label: 'admin', aliases: ['3', 'dangerous'] },
250
+ ],
251
+ 'dev',
252
+ ),
253
+ );
254
+ await persistLocalAgentTrustDefaults(token, profile);
255
+
256
+ if (profile === 'strict') {
257
+ console.log(' ✓ Strict mode enabled. Local auto-approve is OFF; agent requests require manual approval.\n');
258
+ return;
259
+ }
260
+ if (profile === 'admin') {
261
+ console.log(' ✓ Admin mode enabled. WARNING: local agents get broad access.\n');
262
+ return;
263
+ }
264
+ console.log(' ✓ Dev mode enabled. Local auto-approve remains ON with scoped profile.\n');
265
+ }
266
+
267
+ async function configureApiKey(
268
+ token: string,
269
+ service: string,
270
+ label: string,
271
+ placeholder: string,
272
+ ): Promise<boolean> {
273
+ const prompt = placeholder ? ` ${label} (${placeholder})` : ` ${label}`;
274
+ const key = await promptInput(prompt);
275
+
276
+ if (!key) return false;
277
+
278
+ // Validate
279
+ try {
280
+ const result = await fetchJson<{ valid?: boolean; error?: string }>(
281
+ '/apikeys/validate',
282
+ { body: { service, key }, token },
283
+ );
284
+
285
+ if (result.valid) {
286
+ console.log(` ✓ Valid\n`);
287
+ } else {
288
+ console.log(` ✗ Invalid: ${result.error || 'unknown error'}`);
289
+ const retry = await promptConfirm(' Try again?');
290
+ if (retry) return configureApiKey(token, service, label, placeholder);
291
+ const saveAnyway = await promptConfirm(' Save anyway?');
292
+ if (!saveAnyway) {
293
+ console.log(' Skipped.\n');
294
+ return false;
295
+ }
296
+ }
297
+ } catch (err) {
298
+ const msg = getErrorMessage(err);
299
+ console.log(` ⚠ Could not validate: ${msg}`);
300
+ const saveAnyway = await promptConfirm(' Save anyway?');
301
+ if (!saveAnyway) {
302
+ console.log(' Skipped.\n');
303
+ return false;
304
+ }
305
+ }
306
+
307
+ // Save
308
+ await fetchJson('/apikeys', {
309
+ body: { service, name: 'default', key },
310
+ token,
311
+ });
312
+ console.log(` Saved.\n`);
313
+ return true;
314
+ }
315
+
316
+ async function configureTelegram(token: string): Promise<boolean> {
317
+ const botToken = await promptInput(' Telegram bot token');
318
+ if (!botToken) return false;
319
+
320
+ // Validate bot token
321
+ try {
322
+ const result = await fetchJson<{ valid?: boolean; error?: string; info?: { botUsername?: string } }>(
323
+ '/apikeys/validate',
324
+ { body: { service: 'adapter:telegram', key: botToken }, token },
325
+ );
326
+
327
+ if (result.valid) {
328
+ const username = result.info?.botUsername || 'unknown';
329
+ console.log(` ✓ Bot: @${username}\n`);
330
+ } else {
331
+ console.log(` ✗ Invalid bot token: ${result.error || 'unknown error'}`);
332
+ const retry = await promptConfirm(' Try again?');
333
+ if (retry) return configureTelegram(token);
334
+ console.log(' Skipped.\n');
335
+ return false;
336
+ }
337
+ } catch (err) {
338
+ const msg = getErrorMessage(err);
339
+ console.log(` ⚠ Could not validate bot token: ${msg}`);
340
+ const skip = await promptConfirm(' Skip Telegram setup?');
341
+ if (skip) {
342
+ console.log(' Skipped.\n');
343
+ return false;
344
+ }
345
+ }
346
+
347
+ // Auto-detect chat ID via deep link
348
+ let chatId = '';
349
+ try {
350
+ const linkResult = await fetchJson<{ success?: boolean; link?: string; setupToken?: string; botUsername?: string; error?: string }>(
351
+ '/adapters/telegram/setup-link',
352
+ { body: { botToken }, token },
353
+ );
354
+
355
+ if (linkResult.success && linkResult.link && linkResult.setupToken) {
356
+ console.log(` Open this link and press Start: ${linkResult.link}\n`);
357
+ process.stdout.write(' Waiting for /start...');
358
+
359
+ // Poll detect-chat (up to 2 attempts ~50s)
360
+ for (let attempt = 0; attempt < 2; attempt++) {
361
+ try {
362
+ const detectResult = await fetchJson<{ chatId?: string | null; firstName?: string; username?: string; verified?: boolean; timeout?: boolean }>(
363
+ '/adapters/telegram/detect-chat',
364
+ { body: { setupToken: linkResult.setupToken }, token },
365
+ );
366
+
367
+ if (detectResult.chatId) {
368
+ chatId = detectResult.chatId;
369
+ const name = detectResult.username ? `@${detectResult.username}` : detectResult.firstName || '';
370
+ console.log('');
371
+ console.log(` ✓ Detected chat ID: ${chatId}${name ? ` (${name})` : ''}\n`);
372
+ break;
373
+ }
374
+ // timeout — try again
375
+ } catch {
376
+ break;
377
+ }
378
+ }
379
+
380
+ if (!chatId) {
381
+ console.log(' timed out.');
382
+ }
383
+ }
384
+ } catch {
385
+ // setup-link failed, fall through to manual
386
+ }
387
+
388
+ // Fall back to manual input if auto-detection didn't work
389
+ if (!chatId) {
390
+ chatId = await promptInput(' Telegram chat ID');
391
+ if (!chatId) {
392
+ console.log(' Skipped (no chat ID).\n');
393
+ return false;
394
+ }
395
+ }
396
+
397
+ // Save bot token
398
+ await fetchJson('/apikeys', {
399
+ body: { service: 'adapter:telegram', name: 'botToken', key: botToken },
400
+ token,
401
+ });
402
+
403
+ // Save adapter config
404
+ await fetchJson('/adapters', {
405
+ body: { type: 'telegram', enabled: true, config: { chatId } },
406
+ token,
407
+ });
408
+
409
+ // Restart adapters
410
+ try {
411
+ await fetchJson('/adapters/restart', { method: 'POST', token });
412
+ } catch {
413
+ // Non-fatal
414
+ }
415
+
416
+ // Test
417
+ try {
418
+ const testResult = await fetchJson<{ success?: boolean; error?: string }>(
419
+ '/adapters/test',
420
+ { body: { type: 'telegram' }, token },
421
+ );
422
+ if (testResult.success) {
423
+ console.log(' ✓ Test message sent to Telegram.\n');
424
+ } else {
425
+ console.log(` ⚠ Test failed: ${testResult.error || 'unknown'}. Telegram saved but may need configuration.\n`);
426
+ }
427
+ } catch {
428
+ console.log(' ⚠ Could not send test message. Telegram saved but may need configuration.\n');
429
+ }
430
+
431
+ return true;
432
+ }
433
+
434
+ function printConfigSummary(status: SetupStatus) {
435
+ const check = (val: boolean | undefined) => val ? '✓' : '–';
436
+ console.log(' Configuration:');
437
+ console.log(` Vault: ✓`);
438
+ console.log(` Anthropic: ${check(status.apiKeys?.anthropic)}`);
439
+ console.log(` Alchemy: ${check(status.apiKeys?.alchemy)}`);
440
+ console.log(` Telegram: ${check(status.adapters?.telegram)}`);
441
+ console.log('');
442
+ }
443
+
444
+ function maybeInstallShellHook(): void {
445
+ if (!process.stdout.isTTY || process.env.CI === 'true') {
446
+ return;
447
+ }
448
+
449
+ const shell = path.basename(process.env.SHELL || 'bash');
450
+ let rcFile: string;
451
+ let hookCmd: string;
452
+
453
+ switch (shell) {
454
+ case 'zsh':
455
+ rcFile = path.join(os.homedir(), '.zshrc');
456
+ hookCmd = 'eval "$(aura shell-hook zsh)"';
457
+ break;
458
+ case 'bash':
459
+ rcFile = path.join(os.homedir(), '.bashrc');
460
+ hookCmd = 'eval "$(aura shell-hook bash)"';
461
+ break;
462
+ default:
463
+ return;
464
+ }
465
+
466
+ try {
467
+ if (fs.existsSync(rcFile)) {
468
+ const content = fs.readFileSync(rcFile, 'utf-8');
469
+ if (content.includes('aura shell-hook')) {
470
+ return;
471
+ }
472
+ }
473
+
474
+ fs.appendFileSync(rcFile, `\n# Aura shell hook — auto-load .aura env vars\n${hookCmd}\n`);
475
+ console.log(` ✓ Installed shell hook in ${rcFile}`);
476
+ console.log(` Restart your shell or run: source ${rcFile}\n`);
477
+ } catch {
478
+ // Non-fatal: init should succeed even if shell hook install fails.
479
+ }
480
+ }
481
+
482
+ // ─── Post-setup: detect .aura file and offer credential entry ───
483
+
484
+ async function postSetupAuraDetection(): Promise<void> {
485
+ const auraPath = path.join(process.cwd(), '.aura');
486
+ if (!fs.existsSync(auraPath)) return;
487
+
488
+ let mappings;
489
+ try {
490
+ mappings = parseAuraFile(auraPath);
491
+ } catch {
492
+ return; // Invalid .aura file, skip
493
+ }
494
+
495
+ if (mappings.length === 0) return;
496
+
497
+ console.log(`\n Found .aura file with ${mappings.length} credential(s) needed:\n`);
498
+ for (const m of mappings) {
499
+ const ref = m.vault ? `@${m.vault}/${m.credentialName}/${m.field}` : `${m.credentialName}/${m.field}`;
500
+ console.log(` ${m.envVar} → ${ref}`);
501
+ }
502
+ console.log('');
503
+
504
+ const answer = await promptInput(' Ask your team for access, or enter values manually? (team/manual) [team]');
505
+ const choice = answer?.trim().toLowerCase() || 'team';
506
+
507
+ if (choice === 'manual') {
508
+ // Get auth token via socket
509
+ const kp = generateEphemeralKeypair();
510
+ const token = await bootstrapViaSocket('cli-init', kp);
511
+ const vaultId = await getPrimaryVaultId(token);
512
+
513
+ // Group by credential name
514
+ const byCredential = new Map<string, typeof mappings>();
515
+ for (const m of mappings) {
516
+ const list = byCredential.get(m.credentialName) || [];
517
+ list.push(m);
518
+ byCredential.set(m.credentialName, list);
519
+ }
520
+
521
+ for (const [credName, fields] of byCredential) {
522
+ const fieldValues: Array<{ key: string; value: string }> = [];
523
+
524
+ for (const m of fields) {
525
+ const value = await promptInput(` Enter value for ${m.envVar} (→ ${credName}/${m.field})`);
526
+ if (value) {
527
+ fieldValues.push({ key: m.field, value });
528
+ } else {
529
+ console.log(` Skipped ${m.envVar}`);
530
+ }
531
+ }
532
+
533
+ if (fieldValues.length > 0) {
534
+ const result = await createCredentialViaApi({
535
+ token,
536
+ vaultId,
537
+ name: credName,
538
+ fields: fieldValues,
539
+ });
540
+ if (result.success) {
541
+ console.log(` ✓ Created credential: ${credName}`);
542
+ } else {
543
+ console.error(` ✗ Failed to create ${credName}: ${result.error}`);
544
+ }
545
+ }
546
+ }
547
+ console.log('');
548
+ } else {
549
+ console.log(' Ask your team admin to share these credentials.');
550
+ console.log(' Once they\'re in your vault, run: aura env -- <your-command>\n');
551
+ }
552
+ }
553
+
554
+ // ─── Post-setup: --from-dotenv migration ────────────────────────
555
+
556
+ async function resolveDotenvMigrationToken(existingToken?: string): Promise<string> {
557
+ if (existingToken) return existingToken;
558
+
559
+ const envToken = process.env.AURA_TOKEN?.trim();
560
+ if (envToken) return envToken;
561
+
562
+ const kp = generateEphemeralKeypair();
563
+ try {
564
+ return await bootstrapViaSocket('cli-init', kp);
565
+ } catch (socketErr) {
566
+ if (!process.stdin.isTTY) {
567
+ throw new Error(
568
+ `${getErrorMessage(socketErr)}\n` +
569
+ 'Set AURA_TOKEN or run `aura unlock` in another terminal, then retry `aura init --from-dotenv`.',
570
+ );
571
+ }
572
+
573
+ console.log(' Socket auth unavailable. Unlocking vault to continue .env migration...');
574
+ const password = await promptPassword(' Vault password');
575
+ const publicKey = await fetchPublicKey();
576
+ const encrypted = encryptPassword(password, publicKey);
577
+ const { publicKey: agentPubkey } = generateAgentKeypair();
578
+ const unlock = await fetchJson<{ token: string }>('/unlock', {
579
+ body: { encrypted, pubkey: agentPubkey },
580
+ });
581
+ return unlock.token;
582
+ }
583
+ }
584
+
585
+ async function postSetupDotenvMigration(existingToken?: string): Promise<void> {
586
+ const args = process.argv.slice(2);
587
+ const fromIdx = args.indexOf('--from');
588
+ const fromPath = fromIdx >= 0 && fromIdx + 1 < args.length ? args[fromIdx + 1] : undefined;
589
+ const dryRun = args.includes('--dry-run');
590
+ const noGroup = args.includes('--no-group');
591
+
592
+ const envPath = fromPath || path.join(process.cwd(), '.env');
593
+
594
+ const token = await resolveDotenvMigrationToken(existingToken);
595
+
596
+ await migrateDotenv({
597
+ token,
598
+ envPath,
599
+ noGroup,
600
+ dryRun,
601
+ });
602
+ }
603
+
604
+ // ─── Headless password flow ─────────────────────────────────────
605
+
606
+ async function passwordFlow(password: string): Promise<string> {
607
+ if (password.length < 8) {
608
+ console.log(' Error: Password must be at least 8 characters.');
609
+ process.exit(1);
610
+ }
611
+
612
+ console.log(' Creating vault...');
613
+ const publicKey = await fetchPublicKey();
614
+ const encrypted = encryptPassword(password, publicKey);
615
+ const { publicKey: agentPubkey } = generateAgentKeypair();
616
+
617
+ const vault = await fetchJson<{
618
+ success: boolean;
619
+ address: string;
620
+ mnemonic: string;
621
+ token: string;
622
+ }>('/setup', { body: { encrypted, pubkey: agentPubkey } });
623
+
624
+ console.log(' Vault created!\n');
625
+
626
+ printSeedPhrase(vault.mnemonic);
627
+ loadServiceIfNeeded();
628
+
629
+ printBanner('TIME TO AURAMAXX');
630
+ console.log(` Cold wallet address: ${vault.address}`);
631
+ console.log(` Admin token: ${vault.token}\n`);
632
+ console.log(' IMPORTANT: Save the seed phrase above. It cannot be recovered.\n');
633
+ if (isServiceInstalled()) {
634
+ console.log(' Servers are running in the background. Use `auramaxx stop` to stop.\n');
635
+ } else {
636
+ console.log(' Servers are running. Press Ctrl+C to stop.\n');
637
+ }
638
+ return vault.token;
639
+ }
640
+
641
+ // ─── Main ────────────────────────────────────────────────────────
642
+
643
+ async function main() {
644
+ printBanner('AURAMAXX.SH BOOTING');
645
+
646
+ const root = findProjectRoot();
647
+ const debugMode = process.argv.includes('--debug');
648
+
649
+ // Keep boot output concise before runtime startup.
650
+ ensureDirectories();
651
+
652
+ // Step 1: Migrations
653
+ try {
654
+ runMigrations(root);
655
+ if (debugMode) console.log(' Migrating... complete');
656
+ } catch (error) {
657
+ const msg = getErrorMessage(error);
658
+ console.error(` Migration failed: ${msg}`);
659
+ console.error(' Try running: npx prisma migrate deploy');
660
+ process.exit(1);
661
+ }
662
+
663
+ // Step 2: Prisma client
664
+ try {
665
+ generatePrismaClient(root);
666
+ if (debugMode) console.log(' Database... complete');
667
+ } catch (error) {
668
+ const msg = getErrorMessage(error);
669
+ console.error(` Prisma generate failed: ${msg}`);
670
+ process.exit(1);
671
+ }
672
+
673
+ // Step 3: Start server headless (dashboard started later if needed)
674
+ if (debugMode) console.log(' Starting...');
675
+ stopServer();
676
+ serverChildren = startServer({ headless: true, debug: debugMode });
677
+
678
+ try {
679
+ await waitForServer(15000);
680
+ if (debugMode) console.log(' Starting... complete\n');
681
+ } catch {
682
+ console.error(' Server failed to start within 15 seconds.');
683
+ console.error(` Check for port conflicts on :${process.env.WALLET_SERVER_PORT || '4242'}`);
684
+ stopServer();
685
+ process.exit(1);
686
+ }
687
+
688
+ // Step 5: Check if vault already exists
689
+ const status = await fetchSetupStatus();
690
+
691
+ const args = process.argv.slice(2);
692
+ const fromDotenv = args.includes('--from-dotenv');
693
+ const backgroundAfterSetup = args.includes('--background') || args.includes('--daemon') || args.includes('-d');
694
+ let setupToken: string | undefined;
695
+
696
+ if (status.hasWallet) {
697
+ if (fromDotenv) {
698
+ printSection('Existing Vault', 'Vault already initialized. Running dotenv migration.');
699
+ // Vault exists, just do the dotenv migration
700
+ console.log(' Vault already exists. Running .env migration...\n');
701
+ await postSetupDotenvMigration();
702
+ } else {
703
+ printSection('Already Initialized', 'Vault already exists. Starting dashboard.');
704
+ const dashboard = startDashboard();
705
+ serverChildren.push(dashboard);
706
+
707
+ console.log(' Vault already exists — already initialized.\n');
708
+ console.log(` Cold wallet: ${status.address}`);
709
+ console.log(` Dashboard: http://localhost:${DASHBOARD_PORT}\n`);
710
+
711
+ // TODO(v2): .env-to-vault migration
712
+ // const envPath = path.join(process.cwd(), '.env');
713
+ // if (fs.existsSync(envPath)) {
714
+ // console.log(' 💡 Found .env file. Run `aura init --from-dotenv` to migrate secrets to the vault.\n');
715
+ // }
716
+ }
717
+
718
+ if (fromDotenv) {
719
+ await postSetupAuraDetection();
720
+ }
721
+
722
+ maybeInstallShellHook();
723
+ // Activate launchd service if plist was written during bootstrap
724
+ loadServiceIfNeeded();
725
+ if (backgroundAfterSetup || isServiceInstalled()) {
726
+ console.log(' Servers are running in the background.');
727
+ console.log(' Use `auramaxx stop` to stop.\n');
728
+ return;
729
+ }
730
+ console.log(' Servers are running. Press Ctrl+C to stop.\n');
731
+ // Keep event loop alive (detached children don't keep it running)
732
+ setInterval(() => {}, 60_000);
733
+ return;
734
+ }
735
+
736
+ // Step 6: Choose setup mode
737
+ const dashboardFlag = args.includes('--dashboard');
738
+ const passwordIdx = args.indexOf('--password');
739
+ const passwordValue = passwordIdx >= 0 && passwordIdx + 1 < args.length
740
+ ? args[passwordIdx + 1]
741
+ : undefined;
742
+
743
+ if (passwordValue) {
744
+ if (fromDotenv) {
745
+ setupToken = await passwordFlow(passwordValue);
746
+ } else {
747
+ await passwordFlow(passwordValue);
748
+ }
749
+ } else if (dashboardFlag) {
750
+ await dashboardFlow();
751
+ } else {
752
+ const mode = await promptSetupMode();
753
+ if (mode === 'dashboard') {
754
+ await dashboardFlow();
755
+ } else {
756
+ if (fromDotenv) {
757
+ setupToken = await terminalFlow();
758
+ } else {
759
+ await terminalFlow();
760
+ }
761
+ }
762
+ }
763
+
764
+ // Step 7: Post-setup — handle --from-dotenv or detect .aura
765
+ if (fromDotenv) {
766
+ try {
767
+ await postSetupDotenvMigration(setupToken);
768
+ } finally {
769
+ setupToken = undefined;
770
+ }
771
+ } else {
772
+ // Suggest --from-dotenv if .env exists but no .aura
773
+ // TODO(v2): .env-to-vault migration
774
+ // const envPath = path.join(process.cwd(), '.env');
775
+ // const auraPath = path.join(process.cwd(), '.aura');
776
+ // if (fs.existsSync(envPath) && !fs.existsSync(auraPath)) {
777
+ // console.log(' 💡 Found .env file. Run `aura init --from-dotenv` to migrate secrets to the vault.\n');
778
+ // }
779
+
780
+ // Detect .aura file and offer credential entry
781
+ await postSetupAuraDetection();
782
+ }
783
+
784
+ maybeInstallShellHook();
785
+ if (backgroundAfterSetup) {
786
+ console.log(' Aura services are running in background mode.');
787
+ console.log(' Use `npx auramaxx status` to check health and `npx auramaxx stop` to stop.\n');
788
+ return;
789
+ }
790
+ // Keep event loop alive (detached children don't keep it running)
791
+ setInterval(() => {}, 60_000);
792
+ }
793
+
794
+ main().catch((error) => {
795
+ console.error('\nError:', getErrorMessage(error));
796
+ stopServer();
797
+ process.exit(1);
798
+ });