auramaxx 1.0.0-alpha.4

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 (363) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +112 -0
  3. package/bin/aurawallet.js +121 -0
  4. package/docs/ADAPTERS.md +467 -0
  5. package/docs/API.md +2679 -0
  6. package/docs/APPS.md +198 -0
  7. package/docs/ARCHITECTURE.md +350 -0
  8. package/docs/AUTH.md +698 -0
  9. package/docs/BEST-PRACTICES.md +121 -0
  10. package/docs/CLI.md +61 -0
  11. package/docs/DEVELOPING-APPS.md +452 -0
  12. package/docs/EXTENSION.md +97 -0
  13. package/docs/JOBS.md +33 -0
  14. package/docs/MCP.md +76 -0
  15. package/docs/PROTOCOL.md +142 -0
  16. package/docs/SETUP.md +219 -0
  17. package/docs/WORKSPACE.md +672 -0
  18. package/docs/agent-auth.md +63 -0
  19. package/docs/aura-file.md +48 -0
  20. package/docs/credentials.md +53 -0
  21. package/docs/external/getting-started.md +65 -0
  22. package/docs/external/overview.md +45 -0
  23. package/docs/external/use-cases.md +48 -0
  24. package/docs/external/why-aura.md +35 -0
  25. package/docs/jobs/connect-agent.md +77 -0
  26. package/docs/jobs/migrate-from-dotenv.md +79 -0
  27. package/docs/jobs/recover-from-lockout.md +72 -0
  28. package/docs/jobs/secure-ci.md +63 -0
  29. package/docs/oauth2.md +42 -0
  30. package/docs/passkeys.md +60 -0
  31. package/docs/security.md +540 -0
  32. package/docs/specs/aura-open-protocol.md +61 -0
  33. package/docs/specs/aura-provider-plugin.md +24 -0
  34. package/docs/specs/aura-registry-model.md +31 -0
  35. package/docs/specs/fixtures/invalid-bad-key.aura +1 -0
  36. package/docs/specs/fixtures/invalid-bad-unicode-escape.aura +1 -0
  37. package/docs/specs/fixtures/invalid-duplicate-key.aura +2 -0
  38. package/docs/specs/fixtures/valid-basic.aura +4 -0
  39. package/docs/specs/fixtures/valid-provider-ref.aura +1 -0
  40. package/docs/specs/fixtures/valid-quoted-escapes.aura +2 -0
  41. package/docs/templates/RELEASE_NOTES_TEMPLATE.md +22 -0
  42. package/docs/totp.md +40 -0
  43. package/docs/wallet/AI.md +508 -0
  44. package/docs/wallet/DEVELOPING-STRATEGIES.md +713 -0
  45. package/docs/wallet/README.md +47 -0
  46. package/docs/wallet/STRATEGY.md +89 -0
  47. package/next.config.ts +21 -0
  48. package/package.json +151 -0
  49. package/postcss.config.mjs +8 -0
  50. package/prisma/migrations/20260214170000_baseline/migration.sql +511 -0
  51. package/prisma/migrations/20260216214537_add_passkey_model/migration.sql +18 -0
  52. package/prisma/migrations/20260217150500_add_credential_access_audit/migration.sql +31 -0
  53. package/prisma/migrations/migration_lock.toml +3 -0
  54. package/prisma/schema.prisma +447 -0
  55. package/public/logo-chevron.svg +31 -0
  56. package/public/logo-concentric.svg +31 -0
  57. package/public/logo-crosshatch.svg +39 -0
  58. package/public/logo-dashed.svg +39 -0
  59. package/public/logo-horizontal.svg +31 -0
  60. package/public/logo-m56.svg +64 -0
  61. package/public/logo.webp +0 -0
  62. package/scripts/add-app.js +245 -0
  63. package/scripts/init.sh +57 -0
  64. package/scripts/migrate-apikeys-to-credentials.ts +35 -0
  65. package/scripts/sandbox-agent-flow.sh +235 -0
  66. package/scripts/sandbox.sh +175 -0
  67. package/scripts/validate-job-docs.mjs +125 -0
  68. package/server/abi/SwapHelper.json +438 -0
  69. package/server/cli/approval.ts +447 -0
  70. package/server/cli/commands/app.ts +204 -0
  71. package/server/cli/commands/cron.ts +24 -0
  72. package/server/cli/commands/doctor.ts +1007 -0
  73. package/server/cli/commands/env.ts +456 -0
  74. package/server/cli/commands/init.ts +752 -0
  75. package/server/cli/commands/mcp.ts +125 -0
  76. package/server/cli/commands/restore.ts +314 -0
  77. package/server/cli/commands/shell-hook.ts +468 -0
  78. package/server/cli/commands/start.ts +62 -0
  79. package/server/cli/commands/status.ts +59 -0
  80. package/server/cli/commands/stop.ts +14 -0
  81. package/server/cli/commands/token.ts +180 -0
  82. package/server/cli/commands/unlock.ts +49 -0
  83. package/server/cli/commands/vault.ts +417 -0
  84. package/server/cli/index.ts +328 -0
  85. package/server/cli/lib/aura-parser.ts +64 -0
  86. package/server/cli/lib/credential-create.ts +74 -0
  87. package/server/cli/lib/credential-resolve.ts +254 -0
  88. package/server/cli/lib/dotenv-migrate.ts +116 -0
  89. package/server/cli/lib/dotenv-parser.ts +146 -0
  90. package/server/cli/lib/http.ts +91 -0
  91. package/server/cli/lib/init-steps.ts +76 -0
  92. package/server/cli/lib/local-agent-trust.ts +45 -0
  93. package/server/cli/lib/process.ts +136 -0
  94. package/server/cli/lib/prompt.ts +85 -0
  95. package/server/cli/lib/theme.ts +240 -0
  96. package/server/cli/socket.ts +570 -0
  97. package/server/cli/transport-client.ts +50 -0
  98. package/server/cron/index.ts +137 -0
  99. package/server/cron/job.ts +31 -0
  100. package/server/cron/jobs/balance-sync.ts +436 -0
  101. package/server/cron/jobs/incoming-scan.ts +506 -0
  102. package/server/cron/jobs/native-price.ts +70 -0
  103. package/server/cron/jobs/orphan-cleanup.ts +40 -0
  104. package/server/cron/jobs/strategy-runner.ts +175 -0
  105. package/server/cron/scheduler.ts +125 -0
  106. package/server/index.ts +406 -0
  107. package/server/lib/adapters/factory.ts +110 -0
  108. package/server/lib/adapters/index.ts +19 -0
  109. package/server/lib/adapters/router.ts +297 -0
  110. package/server/lib/adapters/telegram.ts +645 -0
  111. package/server/lib/adapters/types.ts +89 -0
  112. package/server/lib/adapters/webhook.ts +95 -0
  113. package/server/lib/address.ts +49 -0
  114. package/server/lib/agent-auth/contracts.ts +1194 -0
  115. package/server/lib/agent-profiles.ts +328 -0
  116. package/server/lib/ai.ts +285 -0
  117. package/server/lib/api-registry/contracts.ts +86 -0
  118. package/server/lib/api-registry/validation.ts +172 -0
  119. package/server/lib/apikey-migration.ts +189 -0
  120. package/server/lib/app-installer.ts +505 -0
  121. package/server/lib/app-tokens.ts +247 -0
  122. package/server/lib/auth.ts +314 -0
  123. package/server/lib/batch.ts +242 -0
  124. package/server/lib/cold.ts +874 -0
  125. package/server/lib/config.ts +381 -0
  126. package/server/lib/credential-access-audit.ts +85 -0
  127. package/server/lib/credential-access-policy.ts +110 -0
  128. package/server/lib/credential-health.ts +343 -0
  129. package/server/lib/credential-import.ts +487 -0
  130. package/server/lib/credential-scope.ts +87 -0
  131. package/server/lib/credential-shares.ts +190 -0
  132. package/server/lib/credential-transport.ts +342 -0
  133. package/server/lib/credential-vault.ts +77 -0
  134. package/server/lib/credentials.ts +333 -0
  135. package/server/lib/crypto.ts +8 -0
  136. package/server/lib/db.ts +15 -0
  137. package/server/lib/defaults.ts +366 -0
  138. package/server/lib/dex/index.ts +80 -0
  139. package/server/lib/dex/relay.ts +235 -0
  140. package/server/lib/dex/types.ts +59 -0
  141. package/server/lib/dex/uniswap.ts +370 -0
  142. package/server/lib/e2e-agent/artifacts.ts +36 -0
  143. package/server/lib/e2e-agent/contracts.ts +112 -0
  144. package/server/lib/e2e-agent/validation.ts +135 -0
  145. package/server/lib/encrypt.ts +128 -0
  146. package/server/lib/error.ts +20 -0
  147. package/server/lib/events.ts +205 -0
  148. package/server/lib/hot.ts +357 -0
  149. package/server/lib/key-fingerprint.ts +28 -0
  150. package/server/lib/logger.ts +331 -0
  151. package/server/lib/network.ts +137 -0
  152. package/server/lib/notifications.ts +219 -0
  153. package/server/lib/oauth2-refresh.ts +241 -0
  154. package/server/lib/oursecret.ts +54 -0
  155. package/server/lib/passkey-credential.ts +360 -0
  156. package/server/lib/passkey.ts +68 -0
  157. package/server/lib/permissions.ts +248 -0
  158. package/server/lib/pino.ts +24 -0
  159. package/server/lib/policy-preview.ts +138 -0
  160. package/server/lib/price.ts +338 -0
  161. package/server/lib/prices.ts +34 -0
  162. package/server/lib/project-scope.ts +239 -0
  163. package/server/lib/resolve-action.ts +427 -0
  164. package/server/lib/resolve.ts +36 -0
  165. package/server/lib/sessions.ts +632 -0
  166. package/server/lib/solana/connection.ts +26 -0
  167. package/server/lib/solana/jupiter.ts +128 -0
  168. package/server/lib/solana/transfer.ts +108 -0
  169. package/server/lib/solana/wallet.ts +136 -0
  170. package/server/lib/strategy/emits.ts +21 -0
  171. package/server/lib/strategy/engine.ts +1305 -0
  172. package/server/lib/strategy/executor.ts +115 -0
  173. package/server/lib/strategy/hook-context.ts +158 -0
  174. package/server/lib/strategy/hooks.ts +990 -0
  175. package/server/lib/strategy/index.ts +28 -0
  176. package/server/lib/strategy/installer.ts +305 -0
  177. package/server/lib/strategy/loader.ts +256 -0
  178. package/server/lib/strategy/message.ts +235 -0
  179. package/server/lib/strategy/repository.ts +218 -0
  180. package/server/lib/strategy/session-logger.ts +693 -0
  181. package/server/lib/strategy/sources.ts +288 -0
  182. package/server/lib/strategy/state.ts +189 -0
  183. package/server/lib/strategy/templates.ts +403 -0
  184. package/server/lib/strategy/tick.ts +404 -0
  185. package/server/lib/strategy/types.ts +230 -0
  186. package/server/lib/swap.ts +3 -0
  187. package/server/lib/temp.ts +86 -0
  188. package/server/lib/token-metadata.ts +86 -0
  189. package/server/lib/token-safety.ts +200 -0
  190. package/server/lib/token-search.ts +444 -0
  191. package/server/lib/totp.ts +194 -0
  192. package/server/lib/transactions.ts +123 -0
  193. package/server/lib/transport.ts +75 -0
  194. package/server/lib/txhistory/decoder.ts +262 -0
  195. package/server/lib/txhistory/enricher.ts +652 -0
  196. package/server/lib/txhistory/index.ts +391 -0
  197. package/server/lib/txhistory/signatures.ts +59 -0
  198. package/server/lib/verified-summary.ts +421 -0
  199. package/server/mcp/profile-policy.ts +30 -0
  200. package/server/mcp/server.ts +619 -0
  201. package/server/mcp/tools.ts +523 -0
  202. package/server/middleware/auth.ts +119 -0
  203. package/server/middleware/requestLogger.ts +84 -0
  204. package/server/routes/actions.ts +459 -0
  205. package/server/routes/adapters.ts +703 -0
  206. package/server/routes/addressbook.ts +113 -0
  207. package/server/routes/ai.ts +34 -0
  208. package/server/routes/apikeys.ts +295 -0
  209. package/server/routes/apps.ts +601 -0
  210. package/server/routes/auth.ts +457 -0
  211. package/server/routes/backup.ts +340 -0
  212. package/server/routes/batch.ts +270 -0
  213. package/server/routes/bookmarks.ts +162 -0
  214. package/server/routes/credential-shares.ts +198 -0
  215. package/server/routes/credential-vaults.ts +154 -0
  216. package/server/routes/credentials.ts +1290 -0
  217. package/server/routes/dashboard.ts +71 -0
  218. package/server/routes/defaults.ts +124 -0
  219. package/server/routes/fund.ts +229 -0
  220. package/server/routes/import.ts +352 -0
  221. package/server/routes/launch.ts +665 -0
  222. package/server/routes/lock.ts +54 -0
  223. package/server/routes/logs.ts +68 -0
  224. package/server/routes/nuke.ts +111 -0
  225. package/server/routes/passkey-credentials.ts +99 -0
  226. package/server/routes/passkey.ts +346 -0
  227. package/server/routes/portfolio.ts +217 -0
  228. package/server/routes/price.ts +63 -0
  229. package/server/routes/resolve.ts +31 -0
  230. package/server/routes/security.ts +45 -0
  231. package/server/routes/send-evm.ts +241 -0
  232. package/server/routes/send-solana.ts +281 -0
  233. package/server/routes/send.ts +178 -0
  234. package/server/routes/setup.ts +210 -0
  235. package/server/routes/strategy.ts +894 -0
  236. package/server/routes/swap-evm.ts +353 -0
  237. package/server/routes/swap-solana.ts +177 -0
  238. package/server/routes/swap.ts +356 -0
  239. package/server/routes/token.ts +247 -0
  240. package/server/routes/unlock.ts +403 -0
  241. package/server/routes/wallet-assets.ts +361 -0
  242. package/server/routes/wallet-transactions.ts +515 -0
  243. package/server/routes/wallet.ts +710 -0
  244. package/server/types.ts +146 -0
  245. package/skills/aurawallet/SKILL.md +739 -0
  246. package/skills/aurawallet-setup/SKILL.md +74 -0
  247. package/skills/security-review/SKILL.md +148 -0
  248. package/src/app/api/agent-requests/route.ts +30 -0
  249. package/src/app/api/apps/install/route.ts +126 -0
  250. package/src/app/api/apps/manifests/route.ts +16 -0
  251. package/src/app/api/apps/static/[...path]/route.ts +57 -0
  252. package/src/app/api/events/route.ts +92 -0
  253. package/src/app/api/page.tsx +212 -0
  254. package/src/app/api/workspace/[id]/apps/[wid]/route.ts +119 -0
  255. package/src/app/api/workspace/[id]/apps/route.ts +81 -0
  256. package/src/app/api/workspace/[id]/export/route.ts +67 -0
  257. package/src/app/api/workspace/[id]/route.ts +168 -0
  258. package/src/app/api/workspace/auth.ts +34 -0
  259. package/src/app/api/workspace/config/route.ts +106 -0
  260. package/src/app/api/workspace/import/route.ts +127 -0
  261. package/src/app/api/workspace/route.ts +116 -0
  262. package/src/app/app/page.tsx +2122 -0
  263. package/src/app/apple-icon.png +0 -0
  264. package/src/app/docs/page.tsx +178 -0
  265. package/src/app/favicon.ico +0 -0
  266. package/src/app/globals.css +572 -0
  267. package/src/app/health/page.tsx +5 -0
  268. package/src/app/hello/page.tsx +15 -0
  269. package/src/app/icon.png +0 -0
  270. package/src/app/layout.tsx +34 -0
  271. package/src/app/page.tsx +986 -0
  272. package/src/app/providers.tsx +90 -0
  273. package/src/app/share/[token]/page.tsx +295 -0
  274. package/src/components/ChainSelector.tsx +144 -0
  275. package/src/components/HumanActionBar.tsx +695 -0
  276. package/src/components/NotificationDrawer.tsx +129 -0
  277. package/src/components/apps/AgentKeysApp.tsx +490 -0
  278. package/src/components/apps/App.tsx +153 -0
  279. package/src/components/apps/AppGrid.tsx +15 -0
  280. package/src/components/apps/DetailedAddressDrawer.tsx +325 -0
  281. package/src/components/apps/DraggableApp.tsx +562 -0
  282. package/src/components/apps/IFrameApp.tsx +73 -0
  283. package/src/components/apps/LogsApp.tsx +360 -0
  284. package/src/components/apps/SendApp.tsx +394 -0
  285. package/src/components/apps/SetupWizardApp.tsx +1004 -0
  286. package/src/components/apps/SystemDefaultsApp.tsx +845 -0
  287. package/src/components/apps/ThirdPartyApp.tsx +428 -0
  288. package/src/components/apps/TokenApp.tsx +319 -0
  289. package/src/components/apps/TransactionsApp.tsx +438 -0
  290. package/src/components/apps/WalletDetailApp.tsx +1505 -0
  291. package/src/components/apps/index.ts +13 -0
  292. package/src/components/design-system/Button.tsx +53 -0
  293. package/src/components/design-system/ChainIndicator.tsx +65 -0
  294. package/src/components/design-system/ChainSelector.tsx +137 -0
  295. package/src/components/design-system/ConfirmationModal.tsx +106 -0
  296. package/src/components/design-system/ConfirmationPopover.tsx +81 -0
  297. package/src/components/design-system/Drawer.tsx +123 -0
  298. package/src/components/design-system/FilterDropdown.tsx +72 -0
  299. package/src/components/design-system/Modal.tsx +206 -0
  300. package/src/components/design-system/Popover.tsx +142 -0
  301. package/src/components/design-system/TextInput.tsx +85 -0
  302. package/src/components/design-system/Toggle.tsx +58 -0
  303. package/src/components/design-system/index.ts +11 -0
  304. package/src/components/docs/DocsThemeToggle.tsx +49 -0
  305. package/src/components/health/CredentialHealthDashboard.tsx +214 -0
  306. package/src/components/icons/ChainIcons.tsx +72 -0
  307. package/src/components/layout/AppStoreDrawer.tsx +369 -0
  308. package/src/components/layout/ContentArea.tsx +21 -0
  309. package/src/components/layout/TabBar.tsx +278 -0
  310. package/src/components/layout/WalletSidebar.tsx +1033 -0
  311. package/src/components/layout/index.ts +4 -0
  312. package/src/components/marketing/AuraWalletSpecOverlay.tsx +635 -0
  313. package/src/components/marketing/DeviceMorphExperience.tsx +216 -0
  314. package/src/components/vault/ApiKeysConsole.tsx +1080 -0
  315. package/src/components/vault/AuditConsole.tsx +584 -0
  316. package/src/components/vault/CredentialDetail.tsx +455 -0
  317. package/src/components/vault/CredentialEmpty.tsx +55 -0
  318. package/src/components/vault/CredentialField.tsx +361 -0
  319. package/src/components/vault/CredentialForm.tsx +1212 -0
  320. package/src/components/vault/CredentialList.tsx +165 -0
  321. package/src/components/vault/CredentialRow.tsx +97 -0
  322. package/src/components/vault/CredentialShareModal.tsx +178 -0
  323. package/src/components/vault/CredentialVault.tsx +754 -0
  324. package/src/components/vault/CredentialWalletWidget.tsx +103 -0
  325. package/src/components/vault/ImportCredentialsModal.tsx +515 -0
  326. package/src/components/vault/LargeTypeModal.tsx +64 -0
  327. package/src/components/vault/PasswordGenerator.tsx +224 -0
  328. package/src/components/vault/TOTPDisplay.tsx +123 -0
  329. package/src/components/vault/VaultSidebar.tsx +413 -0
  330. package/src/components/vault/types.ts +54 -0
  331. package/src/context/AuthContext.tsx +337 -0
  332. package/src/context/PriceContext.tsx +113 -0
  333. package/src/context/ThemeContext.tsx +164 -0
  334. package/src/context/WebSocketContext.tsx +269 -0
  335. package/src/context/WorkspaceContext.tsx +668 -0
  336. package/src/hooks/index.ts +3 -0
  337. package/src/hooks/useAgentActions.ts +368 -0
  338. package/src/hooks/useBalance.ts +103 -0
  339. package/src/hooks/useBalances.ts +129 -0
  340. package/src/instrumentation.ts +12 -0
  341. package/src/lib/api.ts +449 -0
  342. package/src/lib/app-loader.ts +148 -0
  343. package/src/lib/app-registry.ts +178 -0
  344. package/src/lib/app-sdk.ts +157 -0
  345. package/src/lib/audit-console-adapter.ts +151 -0
  346. package/src/lib/auth-client.ts +75 -0
  347. package/src/lib/config.ts +74 -0
  348. package/src/lib/crypto.ts +112 -0
  349. package/src/lib/db.ts +21 -0
  350. package/src/lib/docs.ts +390 -0
  351. package/src/lib/events.ts +361 -0
  352. package/src/lib/pino.ts +24 -0
  353. package/src/lib/theme-handlers.ts +168 -0
  354. package/src/lib/theme.ts +351 -0
  355. package/src/lib/tokenData.ts +378 -0
  356. package/src/lib/vault-crypto.ts +129 -0
  357. package/src/lib/websocket-server.ts +302 -0
  358. package/src/lib/websocket-setup.ts +79 -0
  359. package/src/lib/wordlist.ts +2050 -0
  360. package/src/lib/workspace-handlers.ts +285 -0
  361. package/start.sh +80 -0
  362. package/tailwind.config.ts +99 -0
  363. package/tsconfig.json +42 -0
@@ -0,0 +1,328 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Aura Wallet CLI - Headless mode for programmatic wallet control
4
+ *
5
+ * Security Design:
6
+ * - Admin token stored in-process memory only (never touches disk)
7
+ * - Main wallet server hosts Unix socket IPC for local agent connections
8
+ * - Crash = re-auth required (aligns with server restart security model)
9
+ *
10
+ * Usage:
11
+ * npm run cli # Interactive password prompt
12
+ * npm run cli --password-stdin # Read password from stdin (CI/automation)
13
+ * npm run cli --auto-approve # Auto-approve all requests (DANGEROUS)
14
+ */
15
+
16
+ import * as readline from 'readline';
17
+ import { encryptPassword, generateAgentKeypair } from './transport-client';
18
+ import { ApprovalManager } from './approval';
19
+ import * as fs from 'fs';
20
+ import { getErrorMessage } from '../lib/error';
21
+ import { printBanner, printBox, printStatus } from './lib/theme';
22
+
23
+ const SERVER_URL = process.env.WALLET_SERVER_URL || 'http://localhost:4242';
24
+ const LOCK_FILE = `/tmp/aura-cli-${process.getuid?.() ?? 'unknown'}.lock`;
25
+
26
+ // In-process memory only - never persisted
27
+ let adminToken: string | null = null;
28
+ let coldWalletAddress: string | null = null;
29
+
30
+ // Parse command line arguments
31
+ const args = process.argv.slice(2);
32
+ const passwordStdin = args.includes('--password-stdin');
33
+ const autoApprove = args.includes('--auto-approve');
34
+
35
+ /**
36
+ * Check if another CLI instance is running
37
+ */
38
+ function checkLockFile(): boolean {
39
+ try {
40
+ if (fs.existsSync(LOCK_FILE)) {
41
+ const pid = parseInt(fs.readFileSync(LOCK_FILE, 'utf8'), 10);
42
+ // Check if process is still running
43
+ try {
44
+ process.kill(pid, 0); // Signal 0 tests if process exists
45
+ return true; // Process exists, lock is valid
46
+ } catch {
47
+ // Process doesn't exist, stale lock file
48
+ fs.unlinkSync(LOCK_FILE);
49
+ return false;
50
+ }
51
+ }
52
+ return false;
53
+ } catch {
54
+ return false;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Create lock file with our PID
60
+ */
61
+ function createLockFile(): void {
62
+ fs.writeFileSync(LOCK_FILE, process.pid.toString(), { mode: 0o600 });
63
+ }
64
+
65
+ /**
66
+ * Remove lock file on exit
67
+ */
68
+ function removeLockFile(): void {
69
+ try {
70
+ if (fs.existsSync(LOCK_FILE)) {
71
+ const pid = parseInt(fs.readFileSync(LOCK_FILE, 'utf8'), 10);
72
+ if (pid === process.pid) {
73
+ fs.unlinkSync(LOCK_FILE);
74
+ }
75
+ }
76
+ } catch {
77
+ // Ignore cleanup errors
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Fetch the server's RSA public key for password encryption
83
+ */
84
+ async function fetchPublicKey(): Promise<string> {
85
+ const response = await fetch(`${SERVER_URL}/auth/connect`);
86
+ if (!response.ok) {
87
+ throw new Error(`Failed to connect to wallet server: ${response.status}`);
88
+ }
89
+ const data = await response.json() as { publicKey: string };
90
+ return data.publicKey;
91
+ }
92
+
93
+ /**
94
+ * Unlock the wallet with encrypted password
95
+ */
96
+ async function unlockWallet(encryptedPassword: string, pubkey: string): Promise<{ token: string; address: string }> {
97
+ const response = await fetch(`${SERVER_URL}/unlock`, {
98
+ method: 'POST',
99
+ headers: { 'Content-Type': 'application/json' },
100
+ body: JSON.stringify({ encrypted: encryptedPassword, pubkey })
101
+ });
102
+
103
+ const data = await response.json() as { success?: boolean; token?: string; address?: string; error?: string };
104
+
105
+ if (!response.ok || !data.success) {
106
+ throw new Error(data.error || 'Failed to unlock wallet');
107
+ }
108
+
109
+ return { token: data.token!, address: data.address! };
110
+ }
111
+
112
+ /**
113
+ * Prompt for password (hidden input)
114
+ */
115
+ async function promptPassword(): Promise<string> {
116
+ return new Promise((resolve) => {
117
+ const rl = readline.createInterface({
118
+ input: process.stdin,
119
+ output: process.stdout
120
+ });
121
+
122
+ // Hide input by writing to stderr and using raw mode
123
+ process.stdout.write('Password: ');
124
+
125
+ // For hidden input, we need to handle it manually
126
+ const stdin = process.stdin;
127
+ const wasRaw = stdin.isRaw;
128
+
129
+ if (stdin.isTTY) {
130
+ stdin.setRawMode(true);
131
+ }
132
+
133
+ let password = '';
134
+
135
+ const onData = (char: Buffer) => {
136
+ const c = char.toString();
137
+
138
+ if (c === '\n' || c === '\r') {
139
+ // Enter pressed
140
+ stdin.removeListener('data', onData);
141
+ if (stdin.isTTY) {
142
+ stdin.setRawMode(wasRaw ?? false);
143
+ }
144
+ process.stdout.write('\n');
145
+ rl.close();
146
+ resolve(password);
147
+ } else if (c === '\u0003') {
148
+ // Ctrl+C
149
+ process.stdout.write('\n');
150
+ process.exit(1);
151
+ } else if (c === '\u007f' || c === '\b') {
152
+ // Backspace
153
+ if (password.length > 0) {
154
+ password = password.slice(0, -1);
155
+ }
156
+ } else {
157
+ password += c;
158
+ }
159
+ };
160
+
161
+ stdin.on('data', onData);
162
+ });
163
+ }
164
+
165
+ /**
166
+ * Read password from stdin (for automation)
167
+ */
168
+ async function readPasswordFromStdin(): Promise<string> {
169
+ return new Promise((resolve, reject) => {
170
+ let data = '';
171
+
172
+ process.stdin.setEncoding('utf8');
173
+ process.stdin.on('data', (chunk) => {
174
+ data += chunk;
175
+ });
176
+ process.stdin.on('end', () => {
177
+ const password = data.trim();
178
+ if (!password) {
179
+ reject(new Error('No password provided on stdin'));
180
+ } else {
181
+ resolve(password);
182
+ }
183
+ });
184
+ process.stdin.on('error', reject);
185
+
186
+ // Set a timeout for stdin read
187
+ setTimeout(() => {
188
+ if (!data) {
189
+ reject(new Error('Timeout waiting for password on stdin'));
190
+ }
191
+ }, 5000);
192
+ });
193
+ }
194
+
195
+ /**
196
+ * Get the admin token (for use by other modules)
197
+ */
198
+ export function getAdminToken(): string | null {
199
+ return adminToken;
200
+ }
201
+
202
+ /**
203
+ * Get the cold wallet address
204
+ */
205
+ export function getColdWalletAddress(): string | null {
206
+ return coldWalletAddress;
207
+ }
208
+
209
+ /**
210
+ * Get the server URL
211
+ */
212
+ export function getServerUrl(): string {
213
+ return SERVER_URL;
214
+ }
215
+
216
+ /**
217
+ * Main entry point
218
+ */
219
+ async function main() {
220
+ printBanner('CLI MODE');
221
+
222
+ // Check for existing instance
223
+ if (checkLockFile()) {
224
+ console.error('ERROR: Another CLI instance is already running.');
225
+ console.error('If this is incorrect, remove the lock file:', LOCK_FILE);
226
+ process.exit(1);
227
+ }
228
+
229
+ // Auto-approve warning
230
+ if (autoApprove) {
231
+ console.log('⚠️ WARNING: --auto-approve is enabled!');
232
+ console.log(' All agent requests will be automatically approved.');
233
+ console.log(' This is DANGEROUS in production environments.\n');
234
+ }
235
+
236
+ try {
237
+ // 1. Fetch server's public key
238
+ console.log('Connecting to wallet server...');
239
+ const publicKey = await fetchPublicKey();
240
+ console.log('Connected. Server RSA key received.\n');
241
+
242
+ // 2. Get password
243
+ let password: string;
244
+ if (passwordStdin) {
245
+ console.log('Reading password from stdin...');
246
+ password = await readPasswordFromStdin();
247
+ } else {
248
+ password = await promptPassword();
249
+ }
250
+
251
+ // 3. Encrypt and unlock
252
+ console.log('Unlocking wallet...');
253
+ const encryptedPassword = encryptPassword(password, publicKey);
254
+ const { publicKey: agentPubkey } = generateAgentKeypair();
255
+ const { token, address } = await unlockWallet(encryptedPassword, agentPubkey);
256
+
257
+ // Clear password from memory
258
+ password = '';
259
+
260
+ // Store token in memory only
261
+ adminToken = token;
262
+ coldWalletAddress = address;
263
+
264
+ console.log(`\n✓ Wallet unlocked successfully`);
265
+ console.log(` Address: ${address}`);
266
+ console.log(` Token: ${token.substring(0, 20)}...`);
267
+
268
+ // Create lock file
269
+ createLockFile();
270
+
271
+ // 4. Start approval manager (WebSocket listener)
272
+ console.log('\nStarting approval listener...');
273
+ const approvalManager = new ApprovalManager({
274
+ serverUrl: SERVER_URL,
275
+ getToken: () => adminToken,
276
+ autoApprove,
277
+ headless: passwordStdin // Skip terminal interface when using stdin
278
+ });
279
+ await approvalManager.start();
280
+
281
+ // 5. Socket broker now runs in the main wallet server process.
282
+ const socketPath = `/tmp/aura-cli-${process.getuid?.() ?? 'unknown'}.sock`;
283
+
284
+ console.log('');
285
+ printBox([
286
+ 'CLI Ready — Listening for agent requests',
287
+ '',
288
+ `Socket: ${socketPath}`,
289
+ 'Press Ctrl+C to exit',
290
+ ]);
291
+
292
+ // Handle graceful shutdown
293
+ const shutdown = async () => {
294
+ console.log('\n\nShutting down...');
295
+ approvalManager.stop();
296
+ removeLockFile();
297
+
298
+ // Clear sensitive data
299
+ adminToken = null;
300
+ coldWalletAddress = null;
301
+
302
+ console.log('Goodbye.');
303
+ process.exit(0);
304
+ };
305
+
306
+ process.on('SIGINT', shutdown);
307
+ process.on('SIGTERM', shutdown);
308
+ process.on('exit', removeLockFile);
309
+
310
+ // Keep process alive
311
+ await new Promise(() => {
312
+ // Never resolves - keeps CLI running
313
+ });
314
+
315
+ } catch (error) {
316
+ const message = getErrorMessage(error);
317
+ console.error(`\nERROR: ${message}`);
318
+ removeLockFile();
319
+ process.exit(1);
320
+ }
321
+ }
322
+
323
+ // Run main
324
+ main().catch((error) => {
325
+ console.error('Fatal error:', error);
326
+ removeLockFile();
327
+ process.exit(1);
328
+ });
@@ -0,0 +1,64 @@
1
+ /**
2
+ * .aura file parser — shared between env.ts and init.ts
3
+ */
4
+
5
+ import * as fs from 'fs';
6
+ import {
7
+ type AuraMapping,
8
+ validateEnvVarName,
9
+ } from './credential-resolve';
10
+
11
+ export { type AuraMapping } from './credential-resolve';
12
+
13
+ /**
14
+ * Parse a .aura file into an array of env-var → credential mappings.
15
+ */
16
+ export function parseAuraFile(filePath: string): AuraMapping[] {
17
+ const content = fs.readFileSync(filePath, 'utf-8');
18
+ const mappings: AuraMapping[] = [];
19
+
20
+ for (const rawLine of content.split('\n')) {
21
+ const line = rawLine.trim();
22
+ if (!line || line.startsWith('#')) continue;
23
+
24
+ const eqIdx = line.indexOf('=');
25
+ if (eqIdx === -1) {
26
+ throw new Error(`Invalid line in .aura (missing '='): ${line}`);
27
+ }
28
+
29
+ const envVar = line.substring(0, eqIdx).trim();
30
+ const ref = line.substring(eqIdx + 1).trim();
31
+
32
+ if (!envVar || !ref) {
33
+ throw new Error(`Invalid line in .aura: ${line}`);
34
+ }
35
+
36
+ // Validate env var name (audit finding #6)
37
+ validateEnvVarName(envVar);
38
+
39
+ let vault: string | null = null;
40
+ let credentialName: string;
41
+ let field: string;
42
+
43
+ if (ref.startsWith('@')) {
44
+ const parts = ref.substring(1).split('/');
45
+ if (parts.length < 3) {
46
+ throw new Error(`Invalid vault reference (expected @vault/credential/field): ${ref}`);
47
+ }
48
+ vault = parts[0];
49
+ credentialName = parts[1];
50
+ field = parts.slice(2).join('/');
51
+ } else {
52
+ const parts = ref.split('/');
53
+ if (parts.length < 2) {
54
+ throw new Error(`Invalid reference (expected credential/field): ${ref}`);
55
+ }
56
+ credentialName = parts[0];
57
+ field = parts.slice(1).join('/');
58
+ }
59
+
60
+ mappings.push({ envVar, vault, credentialName, field });
61
+ }
62
+
63
+ return mappings;
64
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * CLI helper for creating credentials via the server API.
3
+ */
4
+
5
+ import { serverUrl } from './http';
6
+
7
+ interface CreateCredentialOpts {
8
+ token: string;
9
+ vaultId: string;
10
+ name: string;
11
+ type?: string;
12
+ fields: Array<{ key: string; value: string }>;
13
+ }
14
+
15
+ interface CreateResult {
16
+ success: boolean;
17
+ credential?: { id: string; name: string };
18
+ error?: string;
19
+ }
20
+
21
+ /**
22
+ * Create a credential via POST /credentials.
23
+ * Fields are sent as sensitiveFields (server encrypts them).
24
+ */
25
+ export async function createCredentialViaApi(opts: CreateCredentialOpts): Promise<CreateResult> {
26
+ const base = serverUrl();
27
+ const body = {
28
+ vaultId: opts.vaultId,
29
+ type: opts.type || 'api',
30
+ name: opts.name,
31
+ sensitiveFields: opts.fields.map(f => ({
32
+ key: f.key,
33
+ value: f.value,
34
+ sensitive: true,
35
+ })),
36
+ };
37
+
38
+ const res = await fetch(`${base}/credentials`, {
39
+ method: 'POST',
40
+ headers: {
41
+ 'Content-Type': 'application/json',
42
+ 'Authorization': `Bearer ${opts.token}`,
43
+ },
44
+ body: JSON.stringify(body),
45
+ signal: AbortSignal.timeout(10000),
46
+ });
47
+
48
+ const data = await res.json() as CreateResult;
49
+ if (!res.ok) {
50
+ return { success: false, error: data.error || `HTTP ${res.status}` };
51
+ }
52
+ return data;
53
+ }
54
+
55
+ /**
56
+ * Get the primary vault ID.
57
+ */
58
+ export async function getPrimaryVaultId(token: string): Promise<string> {
59
+ const base = serverUrl();
60
+ const res = await fetch(`${base}/vaults/credential`, {
61
+ headers: { 'Authorization': `Bearer ${token}` },
62
+ signal: AbortSignal.timeout(5000),
63
+ });
64
+
65
+ if (!res.ok) throw new Error(`Failed to list vaults: HTTP ${res.status}`);
66
+
67
+ const data = await res.json() as { vaults: Array<{ id: string; name: string; isPrimary: boolean }> };
68
+ const primary = data.vaults?.find(v => v.isPrimary);
69
+ if (!primary) {
70
+ if (data.vaults?.length > 0) return data.vaults[0].id;
71
+ throw new Error('No vaults found. Run `aura init` first.');
72
+ }
73
+ return primary.id;
74
+ }