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,539 @@
1
+ import { Router, Request, Response } from 'express';
2
+ import { randomBytes } from 'crypto';
3
+ import { prisma } from '../lib/db';
4
+ import { events } from '../lib/events';
5
+ import { requireWalletAuth } from '../middleware/auth';
6
+ import { requireAdmin, isAdmin, requirePermission } from '../lib/permissions';
7
+ import { createToken, getTokenHash, type AgentTokenPayload } from '../lib/auth';
8
+ import { isValidAgentPubkey, normalizeAgentPubkey, encryptToAgentPubkey } from '../lib/credential-transport';
9
+ import { hashSecret } from '../lib/crypto';
10
+ import { isUnlocked } from '../lib/cold';
11
+ import { normalizeAddress } from '../lib/address';
12
+ import { generateVerifiedSummary } from '../lib/verified-summary';
13
+ import { listTokensFromDb, revokeToken } from '../lib/sessions';
14
+ import { createHumanActionNotification, createNotification } from '../lib/notifications';
15
+ import { getDefault } from '../lib/defaults';
16
+ import { logger } from '../lib/logger';
17
+ import { getErrorMessage } from '../lib/error';
18
+ import { buildApproveUrl } from '../lib/approval-link';
19
+ import { resolveAction } from '../lib/resolve-action';
20
+ import { AgentProfileError, resolveProfileToEffectivePolicy } from '../lib/agent-profiles';
21
+ import { buildPolicyPreviewV1, mapPreviewError } from '../lib/policy-preview';
22
+
23
+ const router = Router();
24
+
25
+ // ============================================================================
26
+ // INTERNAL ENDPOINTS — Used by the dashboard, strategy engine, and admin tools.
27
+ // External agents should use POST /auth for token requests (with optional
28
+ // `action` field for auto-execute on approval). These routes are NOT exposed
29
+ // in agent-facing documentation (SKILL.md, CLI.md, etc.).
30
+ // ============================================================================
31
+
32
+ // GET /actions/pending — List all pending human actions
33
+ router.get('/pending', requireWalletAuth, requirePermission('action:read'), async (_req: Request, res: Response) => {
34
+ try {
35
+ const actions = await prisma.humanAction.findMany({
36
+ where: {
37
+ status: 'pending',
38
+ NOT: { type: 'strategy:message' },
39
+ },
40
+ orderBy: { createdAt: 'desc' },
41
+ });
42
+ res.json({ success: true, actions });
43
+ } catch (error) {
44
+ const message = getErrorMessage(error);
45
+ res.status(500).json({ success: false, error: message });
46
+ }
47
+ });
48
+
49
+ // GET /actions/:id/summary — Public sanitized action details for the approval page
50
+ router.get('/:id/summary', async (req: Request<{ id: string }>, res: Response) => {
51
+ try {
52
+ const action = await prisma.humanAction.findUnique({ where: { id: req.params.id } });
53
+ if (!action) { res.status(404).json({ error: 'Action not found' }); return; }
54
+
55
+ const metadata = action.metadata ? JSON.parse(action.metadata) : {};
56
+
57
+ // Derive display fields from stored metadata
58
+ const summary: Record<string, unknown> = {
59
+ id: action.id,
60
+ type: action.type,
61
+ status: action.status,
62
+ createdAt: action.createdAt,
63
+ action: metadata.summary || `${action.type} request`,
64
+ profile: typeof metadata.profile === 'object' ? metadata.profile.displayName || metadata.profile.id : metadata.profile,
65
+ };
66
+
67
+ // Permissions → scope
68
+ if (Array.isArray(metadata.permissions) && metadata.permissions.length > 0) {
69
+ summary.scope = metadata.permissions;
70
+ }
71
+
72
+ // Risk based on permissions
73
+ const perms = metadata.permissions || [];
74
+ const highRisk = perms.some((p: string) => ['admin:*', 'fund', 'send:hot', 'launch'].includes(p));
75
+ const medRisk = perms.some((p: string) => ['swap', 'trade:all', 'wallet:create:hot'].includes(p));
76
+ summary.risk = highRisk ? 'high' : medRisk ? 'medium' : 'low';
77
+
78
+ // Impact descriptions (skip zero-value limits)
79
+ const impact: string[] = [];
80
+ if (metadata.limit && metadata.limit > 0) impact.push(`Fund limit: ${metadata.limit} ETH`);
81
+ if (metadata.limits?.send && metadata.limits.send > 0) impact.push(`Send limit: ${metadata.limits.send} ETH`);
82
+ if (metadata.limits?.swap && metadata.limits.swap > 0) impact.push(`Swap limit: ${metadata.limits.swap} ETH`);
83
+ if (metadata.ttl) impact.push(`Token TTL: ${Math.round(metadata.ttl / 60)} minutes`);
84
+ if (impact.length > 0) summary.impact = impact;
85
+
86
+ // Never expose: secretHash, pubkey, token data
87
+ res.json({ success: true, ...summary });
88
+ } catch (error) {
89
+ const message = getErrorMessage(error);
90
+ res.status(500).json({ success: false, error: message });
91
+ }
92
+ });
93
+
94
+ // POST /actions — Create a human action request (app proposes an action for approval)
95
+ // Requires Bearer token with action:create permission
96
+ router.post('/', requireWalletAuth, requirePermission('action:create'), async (req: Request, res: Response) => {
97
+ try {
98
+ const { summary, permissions, limits, walletAccess, ttl, type, metadata, notify, pubkey, credentialAccess } = req.body;
99
+
100
+ // Validate summary (required for all types)
101
+ if (!summary || typeof summary !== 'string' || summary.trim().length === 0) {
102
+ res.status(400).json({ success: false, error: 'summary is required and must be a non-empty string' });
103
+ return;
104
+ }
105
+
106
+ const MAX_SUMMARY_LENGTH = 500;
107
+ if (summary.length > MAX_SUMMARY_LENGTH) {
108
+ res.status(400).json({ success: false, error: `summary must be ${MAX_SUMMARY_LENGTH} characters or fewer` });
109
+ return;
110
+ }
111
+
112
+ const callerAgentId = req.auth!.token.agentId;
113
+
114
+ // === Notification-only branch: no permissions/limits needed ===
115
+ if (type === 'notify') {
116
+ const request = await prisma.humanAction.create({
117
+ data: {
118
+ type: 'notify',
119
+ fromTier: 'system',
120
+ toAddress: null,
121
+ amount: null,
122
+ chain: 'base',
123
+ status: 'acknowledged',
124
+ resolvedAt: new Date(),
125
+ metadata: JSON.stringify({ agentId: callerAgentId, summary, ...(metadata || {}) }),
126
+ },
127
+ });
128
+
129
+ // Info notification (dismiss only, no approve/reject)
130
+ await createNotification({
131
+ type: 'info',
132
+ category: 'general',
133
+ title: 'Notification',
134
+ message: summary,
135
+ actions: [{ id: 'dismiss', label: 'DISMISS', type: 'secondary', action: 'dismiss' }],
136
+ metadata: { ...(metadata || {}), agentId: callerAgentId },
137
+ source: 'agent',
138
+ agentId: callerAgentId,
139
+ });
140
+
141
+ // Emit to WebSocket for dashboard; adapters check type themselves
142
+ if (notify !== false) {
143
+ events.actionCreated({
144
+ id: request.id,
145
+ type: 'notify',
146
+ source: `agent:${callerAgentId}`,
147
+ summary,
148
+ expiresAt: null,
149
+ metadata: { agentId: callerAgentId, ...(metadata || {}) },
150
+ });
151
+ }
152
+
153
+ logger.actionCreated(callerAgentId, request.id, 'notify', summary);
154
+
155
+ res.json({ success: true, id: request.id });
156
+ return;
157
+ }
158
+
159
+ // === Standard approval flow: permissions required ===
160
+
161
+ // Validate permissions
162
+ if (!permissions || !Array.isArray(permissions) || permissions.length === 0) {
163
+ res.status(400).json({ success: false, error: 'permissions must be a non-empty array' });
164
+ return;
165
+ }
166
+
167
+ // Block privilege escalation — cannot request admin:* or action:create
168
+ const blocked = permissions.filter((p: string) => p === 'admin:*' || p === 'action:create');
169
+ if (blocked.length > 0) {
170
+ res.status(400).json({ success: false, error: `Cannot request privileged permissions: ${blocked.join(', ')}` });
171
+ return;
172
+ }
173
+
174
+ const requestedCredentialAccess = credentialAccess && typeof credentialAccess === 'object' && !Array.isArray(credentialAccess)
175
+ ? credentialAccess as AgentTokenPayload['credentialAccess']
176
+ : undefined;
177
+ if (typeof pubkey !== 'string' || !pubkey.trim()) {
178
+ res.status(400).json({ success: false, error: 'pubkey is required' });
179
+ return;
180
+ }
181
+ if (!isValidAgentPubkey(pubkey)) {
182
+ res.status(400).json({ success: false, error: 'pubkey must be a valid RSA public key (PEM or base64)' });
183
+ return;
184
+ }
185
+ const normalizedPubkey = normalizeAgentPubkey(pubkey);
186
+
187
+ const defaultActionTtl = await getDefault<number>('ttl.action', 60);
188
+ const actionTtl = typeof ttl === 'number' && ttl > 0 ? ttl : defaultActionTtl;
189
+
190
+ // Generate secret for polling (same pattern as POST /auth)
191
+ const secret = randomBytes(32).toString('hex');
192
+ const secretHash = hashSecret(secret);
193
+
194
+ // Preserve pre-computed action from metadata if provided (for auto-execute on approval)
195
+ const precomputedAction = metadata?.action || undefined;
196
+
197
+ // Generate server-verified summary from actual action parameters
198
+ const verifiedSummary = generateVerifiedSummary({
199
+ agentId: callerAgentId,
200
+ summary,
201
+ permissions,
202
+ limits: limits || undefined,
203
+ walletAccess: walletAccess || undefined,
204
+ ttl: actionTtl,
205
+ action: precomputedAction,
206
+ });
207
+
208
+ const request = await prisma.humanAction.create({
209
+ data: {
210
+ type: 'action',
211
+ fromTier: 'system',
212
+ toAddress: null,
213
+ amount: null,
214
+ chain: 'base',
215
+ status: 'pending',
216
+ metadata: JSON.stringify({
217
+ agentId: callerAgentId,
218
+ permissions,
219
+ limits: limits || undefined,
220
+ walletAccess: walletAccess || undefined,
221
+ credentialAccess: requestedCredentialAccess,
222
+ pubkey: normalizedPubkey,
223
+ ttl: actionTtl,
224
+ secretHash,
225
+ summary,
226
+ action: precomputedAction,
227
+ verifiedSummary,
228
+ }),
229
+ },
230
+ });
231
+
232
+ // Create notification for human approval
233
+ await createHumanActionNotification(request);
234
+
235
+ // Emit WebSocket event
236
+ events.actionCreated({
237
+ id: request.id,
238
+ type: 'action',
239
+ source: `agent:${callerAgentId}`,
240
+ summary,
241
+ expiresAt: null,
242
+ metadata: { agentId: callerAgentId, permissions, limits, summary, verifiedSummary },
243
+ });
244
+
245
+ logger.actionCreated(callerAgentId, request.id, 'action', summary);
246
+
247
+ const dashboardBase = `http://localhost:${process.env.DASHBOARD_PORT || '4747'}`;
248
+ res.json({
249
+ success: true,
250
+ requestId: request.id,
251
+ secret,
252
+ approveUrl: buildApproveUrl(dashboardBase, request.id),
253
+ message: 'Action escalated — waiting for human approval',
254
+ });
255
+ } catch (error) {
256
+ const message = getErrorMessage(error);
257
+ res.status(500).json({ success: false, error: message });
258
+ }
259
+ });
260
+
261
+ // POST /actions/:id/resolve — Approve or reject a human action
262
+ router.post('/:id/resolve', requireWalletAuth, requirePermission('action:resolve'), async (req: Request<{ id: string }>, res: Response) => {
263
+ try {
264
+ const { approved, walletAccess, limits } = req.body;
265
+ const result = await resolveAction(req.params.id, approved, { walletAccess, limits });
266
+ res.status(result.statusCode).json(result.data);
267
+ } catch (error) {
268
+ const message = getErrorMessage(error);
269
+ res.status(500).json({ success: false, error: message });
270
+ }
271
+ });
272
+
273
+ // POST /actions/token/preview - Preview effective token policy without issuing token (requires admin)
274
+ router.post('/token/preview', requireWalletAuth, requireAdmin, async (req: Request, res: Response) => {
275
+ try {
276
+ const { profile, profileVersion, profileOverrides } = req.body;
277
+
278
+ if (typeof profile !== 'string' || profile.trim().length === 0) {
279
+ res.status(422).json({ version: 'v1', code: 'ERR_OVERRIDE_INVALID', error: 'profile is required' });
280
+ return;
281
+ }
282
+
283
+ const previewInput = {
284
+ profileId: profile,
285
+ profileVersion: typeof profileVersion === 'string' ? profileVersion : undefined,
286
+ overrides: profileOverrides,
287
+ };
288
+
289
+ const resolved = resolveProfileToEffectivePolicy(previewInput);
290
+ const preview = buildPolicyPreviewV1(previewInput, resolved);
291
+
292
+ res.json(preview);
293
+ } catch (error) {
294
+ if (error instanceof AgentProfileError) {
295
+ const mapped = mapPreviewError(error.code);
296
+ res.status(mapped.status).json(mapped.error);
297
+ return;
298
+ }
299
+ const mapped = mapPreviewError('ERR_RESOLUTION_FAILED');
300
+ res.status(mapped.status).json(mapped.error);
301
+ }
302
+ });
303
+
304
+ // POST /actions/token - Create signed token for agent (requires admin)
305
+ router.post('/token', requireWalletAuth, requireAdmin, async (req: Request, res: Response) => {
306
+ try {
307
+ const {
308
+ agentId,
309
+ limit,
310
+ permissions,
311
+ ttl,
312
+ limits, // Per-permission limits
313
+ walletAccess, // Wallet access grants
314
+ credentialAccess,
315
+ pubkey,
316
+ profile,
317
+ profileVersion,
318
+ profileOverrides,
319
+ } = req.body;
320
+
321
+ if (!agentId || typeof agentId !== 'string') {
322
+ res.status(400).json({ error: 'agentId is required' });
323
+ return;
324
+ }
325
+
326
+ // Legacy limit or new limits.fund
327
+ const fundLimit = typeof limit === 'number' ? limit : (limits?.fund ?? 0);
328
+ if (fundLimit < 0) {
329
+ res.status(400).json({ error: 'limit must be a non-negative number (in ETH)' });
330
+ return;
331
+ }
332
+
333
+ // Wallet must be unlocked
334
+ if (!isUnlocked()) {
335
+ res.status(401).json({ error: 'Wallet is locked. Unlock first.' });
336
+ return;
337
+ }
338
+
339
+ const defaultSendLimit = await getDefault<number>('limits.send', 0.1);
340
+ const defaultSwapLimit = await getDefault<number>('limits.swap', 0.1);
341
+ const defaultTtl = await getDefault<number>('ttl.agent', 3600);
342
+
343
+ const hasProfile = typeof profile === 'string' && profile.trim().length > 0;
344
+ const hasPermissions = permissions !== undefined;
345
+ if (hasProfile === hasPermissions) {
346
+ res.status(400).json({
347
+ error: 'Provide exactly one issuance mode: profile OR permissions.',
348
+ code: 'ISSUANCE_XOR_REQUIRED',
349
+ });
350
+ return;
351
+ }
352
+
353
+ if (!hasProfile && (profileVersion !== undefined || profileOverrides !== undefined)) {
354
+ res.status(400).json({
355
+ error: 'profileVersion/profileOverrides require profile.',
356
+ code: 'PROFILE_FIELDS_WITHOUT_PROFILE',
357
+ });
358
+ return;
359
+ }
360
+
361
+ if (hasPermissions && (!Array.isArray(permissions) || permissions.length === 0)) {
362
+ res.status(400).json({
363
+ error: 'permissions must be a non-empty array when using permissions mode.',
364
+ code: 'PERMISSIONS_REQUIRED',
365
+ });
366
+ return;
367
+ }
368
+
369
+ const resolvedProfile = hasProfile
370
+ ? resolveProfileToEffectivePolicy({
371
+ profileId: profile.trim(),
372
+ profileVersion: typeof profileVersion === 'string' ? profileVersion : undefined,
373
+ overrides: profileOverrides,
374
+ })
375
+ : null;
376
+
377
+ const validPermissions = resolvedProfile
378
+ ? [...resolvedProfile.permissions]
379
+ : [...permissions];
380
+
381
+ if (typeof pubkey !== 'string' || !pubkey.trim()) {
382
+ res.status(400).json({ error: 'pubkey is required' });
383
+ return;
384
+ }
385
+ if (!isValidAgentPubkey(pubkey)) {
386
+ res.status(400).json({ error: 'pubkey must be a valid RSA public key (PEM or base64)' });
387
+ return;
388
+ }
389
+ const normalizedPubkey = normalizeAgentPubkey(pubkey);
390
+
391
+ const ttlSeconds = resolvedProfile
392
+ ? resolvedProfile.ttlSeconds
393
+ : (typeof ttl === 'number' ? ttl : defaultTtl);
394
+
395
+ // Normalize wallet access addresses
396
+ const normalizedWalletAccess = walletAccess && Array.isArray(walletAccess)
397
+ ? walletAccess.map((addr: string) => normalizeAddress(addr))
398
+ : undefined;
399
+
400
+ // Build limits: per-token overrides > system defaults
401
+ const baseLimits = { fund: fundLimit, send: defaultSendLimit, swap: defaultSwapLimit };
402
+ const tokenLimits = limits ? { ...baseLimits, ...limits } : baseLimits;
403
+
404
+ const effectiveCredentialAccess = resolvedProfile
405
+ ? resolvedProfile.credentialAccess
406
+ : credentialAccess;
407
+
408
+ const token = await createToken(agentId, fundLimit, validPermissions, ttlSeconds, {
409
+ limits: tokenLimits,
410
+ walletAccess: normalizedWalletAccess,
411
+ credentialAccess: effectiveCredentialAccess,
412
+ agentPubkey: normalizedPubkey,
413
+ });
414
+
415
+ const tokenHash = getTokenHash(token);
416
+
417
+ // Emit WebSocket event for direct token creation
418
+ events.tokenCreated({
419
+ tokenHash,
420
+ agentId,
421
+ limit: fundLimit,
422
+ permissions: validPermissions,
423
+ expiresAt: Date.now() + ttlSeconds * 1000,
424
+ });
425
+
426
+ if (resolvedProfile) {
427
+ events.custom('agent_profile:issued', {
428
+ eventSchemaVersion: 1,
429
+ eventType: 'agent_profile.issued',
430
+ profile: resolvedProfile.profile,
431
+ effectivePolicyHash: resolvedProfile.effectivePolicyHash,
432
+ overrideDelta: resolvedProfile.overrideDelta,
433
+ actor: 'admin',
434
+ agentId,
435
+ tokenHash,
436
+ timestamp: Date.now(),
437
+ });
438
+ }
439
+
440
+ // Encrypt token to agent pubkey if provided (prevents model provider from seeing it)
441
+ const responseToken = normalizedPubkey
442
+ ? { encryptedToken: encryptToAgentPubkey(token, normalizedPubkey) }
443
+ : { token };
444
+
445
+ res.json({
446
+ success: true,
447
+ ...responseToken,
448
+ agentId,
449
+ limit: fundLimit,
450
+ limits: tokenLimits,
451
+ permissions: validPermissions,
452
+ walletAccess: normalizedWalletAccess,
453
+ credentialAccess: effectiveCredentialAccess,
454
+ profile: resolvedProfile ? resolvedProfile.profile : undefined,
455
+ effectivePolicyHash: resolvedProfile ? resolvedProfile.effectivePolicyHash : undefined,
456
+ overrideDelta: resolvedProfile ? resolvedProfile.overrideDelta : undefined,
457
+ warnings: resolvedProfile ? resolvedProfile.warnings : undefined,
458
+ hasPubkey: !!normalizedPubkey,
459
+ expiresIn: ttlSeconds
460
+ });
461
+ } catch (error) {
462
+ if (error instanceof AgentProfileError) {
463
+ res.status(400).json({ error: error.message, code: error.code });
464
+ return;
465
+ }
466
+ const message = getErrorMessage(error);
467
+ res.status(400).json({ error: message });
468
+ }
469
+ });
470
+
471
+ // GET /actions/tokens - List all agent tokens (requires admin)
472
+ router.get('/tokens', requireWalletAuth, requireAdmin, async (_req: Request, res: Response) => {
473
+ try {
474
+ const tokens = await listTokensFromDb();
475
+
476
+ const active = tokens.filter(t => t.isActive && !t.isExpired && !t.isRevoked && t.remaining > 0);
477
+ const inactive = tokens.filter(t => !t.isActive && !t.isExpired && !t.isRevoked);
478
+ const expired = tokens.filter(t => t.isExpired);
479
+ const revoked = tokens.filter(t => t.isRevoked);
480
+ const depleted = tokens.filter(t => !t.isExpired && !t.isRevoked && t.remaining <= 0);
481
+
482
+ res.json({
483
+ success: true,
484
+ tokens: {
485
+ active,
486
+ inactive,
487
+ expired,
488
+ revoked,
489
+ depleted
490
+ },
491
+ total: tokens.length
492
+ });
493
+ } catch (error) {
494
+ const message = getErrorMessage(error);
495
+ res.status(400).json({ error: message });
496
+ }
497
+ });
498
+
499
+ // POST /actions/tokens/revoke - Revoke a token (admin or agent with own token)
500
+ router.post('/tokens/revoke', requireWalletAuth, async (req: Request, res: Response) => {
501
+ try {
502
+ const { tokenHash } = req.body;
503
+ const auth = req.auth!;
504
+
505
+ // Agent can only revoke their own token
506
+ if (!isAdmin(auth)) {
507
+ if (tokenHash && tokenHash !== auth.tokenHash) {
508
+ res.status(403).json({ error: 'Agents can only revoke their own token' });
509
+ return;
510
+ }
511
+ const success = await revokeToken(auth.tokenHash);
512
+ if (success) {
513
+ logger.tokenRevoked(auth.tokenHash, auth.token.agentId);
514
+ }
515
+ res.json({ success, message: success ? 'Token revoked' : 'Token not found' });
516
+ return;
517
+ }
518
+
519
+ // Admin revoking any token
520
+ if (!tokenHash || typeof tokenHash !== 'string') {
521
+ res.status(400).json({ error: 'tokenHash is required' });
522
+ return;
523
+ }
524
+
525
+ const success = await revokeToken(tokenHash);
526
+
527
+ if (success) {
528
+ events.tokenRevoked({ tokenHash });
529
+ logger.tokenRevoked(tokenHash, 'admin');
530
+ }
531
+
532
+ res.json({ success, message: success ? 'Token revoked' : 'Token not found' });
533
+ } catch (error) {
534
+ const message = getErrorMessage(error);
535
+ res.status(400).json({ error: message });
536
+ }
537
+ });
538
+
539
+ export default router;