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,41 @@
1
+ const DEFAULT_ON_ALLOWLIST = new Set([
2
+ 'password',
3
+ 'cvv',
4
+ 'refresh_token',
5
+ ]);
6
+
7
+ const HARD_DENYLIST = new Set([
8
+ 'privatekey',
9
+ 'private_key',
10
+ 'seedphrase',
11
+ 'seed_phrase',
12
+ 'mnemonic',
13
+ 'recovery_phrase',
14
+ ]);
15
+
16
+ function norm(field: string): string {
17
+ return field.trim().toLowerCase().replace(/[^a-z0-9_]/g, '');
18
+ }
19
+
20
+ export interface DontAskAgainDecision {
21
+ defaultOn: boolean;
22
+ reason: 'ALLOWLIST_EXCLUDED_FIELD' | 'DENYLIST_SENSITIVE_FIELD' | 'MIXED_OR_UNKNOWN';
23
+ }
24
+
25
+ export function resolveDontAskAgainDefault(excludedFields: string[]): DontAskAgainDecision {
26
+ const normalized = excludedFields.map(norm).filter(Boolean);
27
+ if (!normalized.length) {
28
+ return { defaultOn: false, reason: 'MIXED_OR_UNKNOWN' };
29
+ }
30
+
31
+ if (normalized.some((f) => HARD_DENYLIST.has(f))) {
32
+ return { defaultOn: false, reason: 'DENYLIST_SENSITIVE_FIELD' };
33
+ }
34
+
35
+ const allAllowlisted = normalized.every((f) => DEFAULT_ON_ALLOWLIST.has(f));
36
+ if (allAllowlisted) {
37
+ return { defaultOn: true, reason: 'ALLOWLIST_EXCLUDED_FIELD' };
38
+ }
39
+
40
+ return { defaultOn: false, reason: 'MIXED_OR_UNKNOWN' };
41
+ }
@@ -0,0 +1,36 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { RunFingerprint } from './contracts';
4
+
5
+ export interface SummaryArtifact {
6
+ runId: string;
7
+ status: 'passed' | 'failed';
8
+ scenarioId: string;
9
+ runFingerprint: RunFingerprint;
10
+ }
11
+
12
+ export interface ReplayManifest {
13
+ runId: string;
14
+ scenarioId: string;
15
+ runFingerprint: RunFingerprint;
16
+ replayCommand: string;
17
+ }
18
+
19
+ export function writeArtifacts(baseDir: string, summary: SummaryArtifact): { summaryPath: string; manifestPath: string } {
20
+ fs.mkdirSync(baseDir, { recursive: true });
21
+
22
+ const summaryPath = path.join(baseDir, 'summary.json');
23
+ fs.writeFileSync(summaryPath, JSON.stringify(summary, null, 2));
24
+
25
+ const manifest: ReplayManifest = {
26
+ runId: summary.runId,
27
+ scenarioId: summary.scenarioId,
28
+ runFingerprint: summary.runFingerprint,
29
+ replayCommand: `npx tsx server/tests/e2e-agent/runner.ts replay --run ${summary.runId}`,
30
+ };
31
+
32
+ const manifestPath = path.join(baseDir, 'replay.manifest.json');
33
+ fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
34
+
35
+ return { summaryPath, manifestPath };
36
+ }
@@ -0,0 +1,112 @@
1
+ import { z } from 'zod';
2
+
3
+ export const E2E_AGENT_ERROR_CODES = {
4
+ schemaAssertion: 'E_SCHEMA_ASSERTION',
5
+ egressPolicy: 'E_EGRESS_POLICY',
6
+ clockDrift: 'E_CLOCK_DRIFT',
7
+ budgetDuration: 'E_BUDGET_DURATION',
8
+ budgetSteps: 'E_BUDGET_STEPS',
9
+ budgetToolCalls: 'E_BUDGET_TOOL_CALLS',
10
+ budgetTokens: 'E_BUDGET_TOKENS',
11
+ } as const;
12
+
13
+ const assertionBaseSchema = z.object({
14
+ id: z.string().min(1),
15
+ type: z.enum(['ui', 'api', 'db']),
16
+ op: z.enum(['equals', 'contains', 'exists', 'not_exists', 'gt', 'gte', 'lt', 'lte']),
17
+ });
18
+
19
+ const uiAssertionSchema = assertionBaseSchema.extend({
20
+ type: z.literal('ui'),
21
+ selector: z.string().min(1),
22
+ expected: z.union([z.string(), z.number(), z.boolean()]).optional(),
23
+ });
24
+
25
+ const apiAssertionSchema = assertionBaseSchema.extend({
26
+ type: z.literal('api'),
27
+ endpoint: z.string().min(1),
28
+ path: z.string().min(1),
29
+ expected: z.union([z.string(), z.number(), z.boolean()]).optional(),
30
+ });
31
+
32
+ const dbAssertionSchema = assertionBaseSchema.extend({
33
+ type: z.literal('db'),
34
+ query: z.string().min(1),
35
+ expected: z.union([z.string(), z.number(), z.boolean()]).optional(),
36
+ });
37
+
38
+ export const assertionSchema = z.discriminatedUnion('type', [
39
+ uiAssertionSchema,
40
+ apiAssertionSchema,
41
+ dbAssertionSchema,
42
+ ]);
43
+
44
+ export const budgetSchema = z.object({
45
+ maxDurationSec: z.number().int().positive(),
46
+ maxSteps: z.number().int().positive(),
47
+ maxToolCalls: z.number().int().positive(),
48
+ maxTokens: z.number().int().positive(),
49
+ });
50
+
51
+ export const scenarioSchema = z.object({
52
+ id: z.string().min(1),
53
+ title: z.string().min(1),
54
+ mode: z.enum(['agent-hybrid', 'scripted']),
55
+ clock: z.object({
56
+ baseTimeIso: z.string().datetime(),
57
+ }),
58
+ budget: budgetSchema.partial().optional(),
59
+ assertions: z.array(assertionSchema).min(1),
60
+ });
61
+
62
+ export type Assertion = z.infer<typeof assertionSchema>;
63
+ export type Budget = z.infer<typeof budgetSchema>;
64
+ export type Scenario = z.infer<typeof scenarioSchema>;
65
+
66
+ export type Lane = 'pr-smoke' | 'nightly';
67
+
68
+ export interface LaneBudgetCaps {
69
+ maxDurationSec: number;
70
+ maxSteps: number;
71
+ maxToolCalls: number;
72
+ maxTokens: number;
73
+ }
74
+
75
+ export const REPO_DEFAULT_BUDGET: Budget = {
76
+ maxDurationSec: 90,
77
+ maxSteps: 15,
78
+ maxToolCalls: 12,
79
+ maxTokens: 12000,
80
+ };
81
+
82
+ export const LANE_BUDGET_CAPS: Record<Lane, LaneBudgetCaps> = {
83
+ 'pr-smoke': {
84
+ maxDurationSec: 120,
85
+ maxSteps: 20,
86
+ maxToolCalls: 16,
87
+ maxTokens: 16000,
88
+ },
89
+ nightly: {
90
+ maxDurationSec: 240,
91
+ maxSteps: 40,
92
+ maxToolCalls: 30,
93
+ maxTokens: 40000,
94
+ },
95
+ };
96
+
97
+ export interface ClockProbe {
98
+ runnerMs: number;
99
+ serverMs: number;
100
+ browserMs: number;
101
+ fixtureMs: number;
102
+ }
103
+
104
+ export interface RunFingerprint {
105
+ scenarioId: string;
106
+ lane: Lane;
107
+ mode: Scenario['mode'];
108
+ clockBaseTimeIso: string;
109
+ schemaVersion: string;
110
+ runnerVersion: string;
111
+ gitCommit: string;
112
+ }
@@ -0,0 +1,135 @@
1
+ import { parse as parseYaml } from 'yaml';
2
+ import {
3
+ Budget,
4
+ ClockProbe,
5
+ E2E_AGENT_ERROR_CODES,
6
+ LANE_BUDGET_CAPS,
7
+ Lane,
8
+ REPO_DEFAULT_BUDGET,
9
+ Scenario,
10
+ scenarioSchema,
11
+ } from './contracts';
12
+
13
+ export class E2EAgentValidationError extends Error {
14
+ constructor(public readonly code: string, message: string) {
15
+ super(message);
16
+ this.name = 'E2EAgentValidationError';
17
+ }
18
+ }
19
+
20
+ export function parseScenarioDocument(input: string): unknown {
21
+ try {
22
+ return JSON.parse(input);
23
+ } catch {
24
+ return parseYaml(input);
25
+ }
26
+ }
27
+
28
+ export function validateScenario(raw: unknown): Scenario {
29
+ const parsed = scenarioSchema.safeParse(raw);
30
+ if (!parsed.success) {
31
+ throw new E2EAgentValidationError(
32
+ E2E_AGENT_ERROR_CODES.schemaAssertion,
33
+ parsed.error.issues.map((issue) => issue.message).join('; ')
34
+ );
35
+ }
36
+
37
+ return parsed.data;
38
+ }
39
+
40
+ export function applyBudgetPolicy(scenarioBudget: Partial<Budget> | undefined, lane: Lane): Budget {
41
+ const merged: Budget = {
42
+ ...REPO_DEFAULT_BUDGET,
43
+ ...(scenarioBudget ?? {}),
44
+ };
45
+
46
+ const laneCaps = LANE_BUDGET_CAPS[lane];
47
+
48
+ if (merged.maxDurationSec > laneCaps.maxDurationSec) {
49
+ throw new E2EAgentValidationError(
50
+ E2E_AGENT_ERROR_CODES.budgetDuration,
51
+ `maxDurationSec (${merged.maxDurationSec}) exceeds lane cap (${laneCaps.maxDurationSec})`
52
+ );
53
+ }
54
+
55
+ if (merged.maxSteps > laneCaps.maxSteps) {
56
+ throw new E2EAgentValidationError(
57
+ E2E_AGENT_ERROR_CODES.budgetSteps,
58
+ `maxSteps (${merged.maxSteps}) exceeds lane cap (${laneCaps.maxSteps})`
59
+ );
60
+ }
61
+
62
+ if (merged.maxToolCalls > laneCaps.maxToolCalls) {
63
+ throw new E2EAgentValidationError(
64
+ E2E_AGENT_ERROR_CODES.budgetToolCalls,
65
+ `maxToolCalls (${merged.maxToolCalls}) exceeds lane cap (${laneCaps.maxToolCalls})`
66
+ );
67
+ }
68
+
69
+ if (merged.maxTokens > laneCaps.maxTokens) {
70
+ throw new E2EAgentValidationError(
71
+ E2E_AGENT_ERROR_CODES.budgetTokens,
72
+ `maxTokens (${merged.maxTokens}) exceeds lane cap (${laneCaps.maxTokens})`
73
+ );
74
+ }
75
+
76
+ return merged;
77
+ }
78
+
79
+ export function enforceClockDrift(probe: ClockProbe): void {
80
+ const values = [probe.runnerMs, probe.serverMs, probe.browserMs, probe.fixtureMs];
81
+ const drift = Math.max(...values) - Math.min(...values);
82
+
83
+ if (drift > 50) {
84
+ throw new E2EAgentValidationError(
85
+ E2E_AGENT_ERROR_CODES.clockDrift,
86
+ `Clock drift ${drift}ms exceeded tolerance`
87
+ );
88
+ }
89
+ }
90
+
91
+ export function enforceEgressPolicy(hostname: string, allowedHosts: readonly string[]): void {
92
+ if (!allowedHosts.includes(hostname)) {
93
+ throw new E2EAgentValidationError(
94
+ E2E_AGENT_ERROR_CODES.egressPolicy,
95
+ `Blocked outbound host: ${hostname}`
96
+ );
97
+ }
98
+ }
99
+
100
+ export interface RuntimeUsage {
101
+ durationSec: number;
102
+ steps: number;
103
+ toolCalls: number;
104
+ tokens: number;
105
+ }
106
+
107
+ export function enforceRuntimeBudget(usage: RuntimeUsage, budget: Budget): void {
108
+ if (usage.durationSec > budget.maxDurationSec) {
109
+ throw new E2EAgentValidationError(
110
+ E2E_AGENT_ERROR_CODES.budgetDuration,
111
+ `durationSec ${usage.durationSec} exceeded ${budget.maxDurationSec}`
112
+ );
113
+ }
114
+
115
+ if (usage.steps > budget.maxSteps) {
116
+ throw new E2EAgentValidationError(
117
+ E2E_AGENT_ERROR_CODES.budgetSteps,
118
+ `steps ${usage.steps} exceeded ${budget.maxSteps}`
119
+ );
120
+ }
121
+
122
+ if (usage.toolCalls > budget.maxToolCalls) {
123
+ throw new E2EAgentValidationError(
124
+ E2E_AGENT_ERROR_CODES.budgetToolCalls,
125
+ `toolCalls ${usage.toolCalls} exceeded ${budget.maxToolCalls}`
126
+ );
127
+ }
128
+
129
+ if (usage.tokens > budget.maxTokens) {
130
+ throw new E2EAgentValidationError(
131
+ E2E_AGENT_ERROR_CODES.budgetTokens,
132
+ `tokens ${usage.tokens} exceeded ${budget.maxTokens}`
133
+ );
134
+ }
135
+ }
@@ -0,0 +1,114 @@
1
+ import { randomBytes, scryptSync, createCipheriv, createDecipheriv, createHash } from 'crypto';
2
+ import { EncryptedData } from '../types';
3
+
4
+ const ALGORITHM = 'aes-256-gcm';
5
+ const SCRYPT_COST = 131072; // 2^17
6
+ const SCRYPT_BLOCK_SIZE = 8;
7
+ const SCRYPT_PARALLELIZATION = 1;
8
+ const SCRYPT_MAXMEM = 512 * 1024 * 1024; // 512 MiB
9
+ const DKLEN = 32;
10
+ const GCM_IV_BYTES = 12;
11
+
12
+ function derivePasswordKey(password: string, salt: Buffer): Buffer {
13
+ return scryptSync(password, salt, DKLEN, {
14
+ cost: SCRYPT_COST,
15
+ blockSize: SCRYPT_BLOCK_SIZE,
16
+ parallelization: SCRYPT_PARALLELIZATION,
17
+ maxmem: SCRYPT_MAXMEM,
18
+ });
19
+ }
20
+
21
+ function deriveSeedKey(seed: string): Buffer {
22
+ return createHash('sha256').update(seed, 'utf8').digest();
23
+ }
24
+
25
+ export function encryptPrivateKey(privateKey: string, password: string): EncryptedData {
26
+ const salt = randomBytes(32);
27
+ const iv = randomBytes(GCM_IV_BYTES);
28
+ const derivedKey = derivePasswordKey(password, salt);
29
+
30
+ const cipher = createCipheriv(ALGORITHM, derivedKey, iv);
31
+ const ciphertext = Buffer.concat([
32
+ cipher.update(privateKey, 'utf8'),
33
+ cipher.final()
34
+ ]);
35
+ const mac = cipher.getAuthTag().toString('hex');
36
+
37
+ return {
38
+ ciphertext: ciphertext.toString('hex'),
39
+ iv: iv.toString('hex'),
40
+ salt: salt.toString('hex'),
41
+ mac
42
+ };
43
+ }
44
+
45
+ export function decryptPrivateKey(encrypted: EncryptedData, password: string): string {
46
+ const salt = Buffer.from(encrypted.salt, 'hex');
47
+ const iv = Buffer.from(encrypted.iv, 'hex');
48
+ const ciphertext = Buffer.from(encrypted.ciphertext, 'hex');
49
+ const mac = Buffer.from(encrypted.mac, 'hex');
50
+
51
+ const derivedKey = derivePasswordKey(password, salt);
52
+
53
+ const decipher = createDecipheriv(ALGORITHM, derivedKey, iv);
54
+ decipher.setAuthTag(mac);
55
+ let decrypted: Buffer;
56
+ try {
57
+ decrypted = Buffer.concat([
58
+ decipher.update(ciphertext),
59
+ decipher.final()
60
+ ]);
61
+ } catch {
62
+ throw new Error('Invalid password or corrupted data');
63
+ }
64
+
65
+ return decrypted.toString('utf8');
66
+ }
67
+
68
+ /**
69
+ * Encrypt data using a seed phrase (mnemonic) as the key.
70
+ * Uses faster key derivation since mnemonic has high entropy.
71
+ */
72
+ export function encryptWithSeed(data: string, seed: string): EncryptedData {
73
+ const iv = randomBytes(GCM_IV_BYTES);
74
+ // Use SHA-256 of seed as key (mnemonic has enough entropy, no need for slow scrypt)
75
+ const derivedKey = deriveSeedKey(seed);
76
+
77
+ const cipher = createCipheriv(ALGORITHM, derivedKey, iv);
78
+ const ciphertext = Buffer.concat([
79
+ cipher.update(data, 'utf8'),
80
+ cipher.final()
81
+ ]);
82
+ const mac = cipher.getAuthTag().toString('hex');
83
+
84
+ return {
85
+ ciphertext: ciphertext.toString('hex'),
86
+ iv: iv.toString('hex'),
87
+ salt: '', // Not needed for seed-based encryption
88
+ mac
89
+ };
90
+ }
91
+
92
+ /**
93
+ * Decrypt data using a seed phrase (mnemonic) as the key.
94
+ */
95
+ export function decryptWithSeed(encrypted: EncryptedData, seed: string): string {
96
+ const iv = Buffer.from(encrypted.iv, 'hex');
97
+ const ciphertext = Buffer.from(encrypted.ciphertext, 'hex');
98
+ const mac = Buffer.from(encrypted.mac, 'hex');
99
+ const derivedKey = deriveSeedKey(seed);
100
+
101
+ const decipher = createDecipheriv(ALGORITHM, derivedKey, iv);
102
+ decipher.setAuthTag(mac);
103
+ let decrypted: Buffer;
104
+ try {
105
+ decrypted = Buffer.concat([
106
+ decipher.update(ciphertext),
107
+ decipher.final()
108
+ ]);
109
+ } catch {
110
+ throw new Error('Invalid seed or corrupted data');
111
+ }
112
+
113
+ return decrypted.toString('utf8');
114
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Shared error helpers used across routes and lib modules.
3
+ */
4
+
5
+ /**
6
+ * Extract a human-readable message from an unknown catch value.
7
+ */
8
+ export function getErrorMessage(error: unknown): string {
9
+ return error instanceof Error ? error.message : 'Unknown error';
10
+ }
11
+
12
+ /**
13
+ * An error with an HTTP status code, thrown by validation helpers
14
+ * so callers can respond with the correct status.
15
+ */
16
+ export class HttpError extends Error {
17
+ constructor(public status: number, message: string) {
18
+ super(message);
19
+ }
20
+ }
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Webhook emitter for notifying Next.js of wallet events
3
+ * Posts events to Next.js API which broadcasts to WebSocket clients
4
+ * Also stores all events in database for debugging/audit trail
5
+ */
6
+
7
+ import { prisma } from './db';
8
+ import { log } from './pino';
9
+
10
+ // Event types (mirrored from src/lib/events.ts)
11
+ export const WALLET_EVENTS = {
12
+ TOKEN_CREATED: 'token:created',
13
+ TOKEN_REVOKED: 'token:revoked',
14
+ TOKEN_SPENT: 'token:spent',
15
+ WALLET_CREATED: 'wallet:created',
16
+ WALLET_CHANGED: 'wallet:changed',
17
+ ASSET_CHANGED: 'asset:changed',
18
+ TX_CREATED: 'tx:created',
19
+ ACTION_CREATED: 'action:created',
20
+ ACTION_RESOLVED: 'action:resolved',
21
+ VAULT_UNLOCKED: 'vault:unlocked',
22
+ CREDENTIAL_CHANGED: 'credential:changed',
23
+ CREDENTIAL_ACCESSED: 'credential:accessed',
24
+ SECRET_ACCESSED: 'secret:accessed',
25
+ } as const;
26
+
27
+ export type WalletEventType = (typeof WALLET_EVENTS)[keyof typeof WALLET_EVENTS];
28
+
29
+ interface WalletEvent<T = unknown> {
30
+ type: WalletEventType | string;
31
+ timestamp: number;
32
+ source: 'express' | 'nextjs';
33
+ data: T;
34
+ }
35
+
36
+ // WebSocket server broadcast endpoint (runs on port 4748)
37
+ const WS_BROADCAST_URL = process.env.WS_BROADCAST_URL ?? 'http://localhost:4748/broadcast';
38
+
39
+ /**
40
+ * Store event in database (non-blocking)
41
+ * Automatically stores all events for debugging and audit purposes
42
+ */
43
+ function storeEvent<T>(event: WalletEvent<T>): void {
44
+ prisma.event.create({
45
+ data: {
46
+ type: event.type,
47
+ source: event.source,
48
+ data: JSON.stringify(event.data),
49
+ timestamp: new Date(event.timestamp),
50
+ },
51
+ })
52
+ .then(() => {
53
+ // Stored successfully
54
+ })
55
+ .catch((err) => {
56
+ log.error({ err: err.message }, 'failed to store event in DB');
57
+ });
58
+ }
59
+
60
+ /**
61
+ * Emit a wallet event to Next.js webhook
62
+ * Non-blocking - failures are logged but don't affect the calling code
63
+ * Events are automatically stored in the database
64
+ */
65
+ export function emitWalletEvent<T>(type: WalletEventType | string, data: T): void {
66
+ const event: WalletEvent<T> = {
67
+ type,
68
+ timestamp: Date.now(),
69
+ source: 'express',
70
+ data,
71
+ };
72
+
73
+ // Store in database (non-blocking)
74
+ storeEvent(event);
75
+
76
+ // Fire and forget broadcast to WebSocket server - don't block the request
77
+ // Skip when WS_BROADCAST_URL is empty (e.g. in tests)
78
+ if (!WS_BROADCAST_URL) return;
79
+
80
+ fetch(WS_BROADCAST_URL, {
81
+ method: 'POST',
82
+ headers: { 'Content-Type': 'application/json' },
83
+ body: JSON.stringify(event),
84
+ })
85
+ .then((res) => {
86
+ if (!res.ok) {
87
+ log.warn({ status: res.status, type }, 'WebSocket broadcast failed');
88
+ }
89
+ })
90
+ .catch((err) => {
91
+ // Log but don't throw - this is non-critical
92
+ log.warn({ err: err.message, type }, 'failed to broadcast to WebSocket');
93
+ });
94
+ }
95
+
96
+ // Type-safe event emitters for each event type
97
+ export const events = {
98
+ tokenCreated: (data: {
99
+ tokenHash: string;
100
+ agentId: string;
101
+ limit: number;
102
+ permissions: string[];
103
+ expiresAt: number;
104
+ }) => emitWalletEvent(WALLET_EVENTS.TOKEN_CREATED, data),
105
+
106
+ tokenRevoked: (data: { tokenHash: string }) =>
107
+ emitWalletEvent(WALLET_EVENTS.TOKEN_REVOKED, data),
108
+
109
+ tokenSpent: (data: {
110
+ tokenHash: string;
111
+ amount: number;
112
+ newSpent: number;
113
+ remaining: number;
114
+ limitType?: 'fund' | 'send' | 'swap';
115
+ }) => emitWalletEvent(WALLET_EVENTS.TOKEN_SPENT, data),
116
+
117
+ walletCreated: (data: {
118
+ address: string;
119
+ tier: 'hot' | 'temp';
120
+ chain: string;
121
+ name?: string;
122
+ tokenHash?: string;
123
+ }) => emitWalletEvent(WALLET_EVENTS.WALLET_CREATED, data),
124
+
125
+ walletChanged: (data: {
126
+ address: string;
127
+ reason: 'created' | 'updated';
128
+ }) => emitWalletEvent(WALLET_EVENTS.WALLET_CHANGED, data),
129
+
130
+ assetChanged: (data: {
131
+ walletAddress: string;
132
+ tokenAddress: string;
133
+ symbol?: string;
134
+ name?: string;
135
+ poolAddress?: string;
136
+ poolVersion?: string;
137
+ icon?: string;
138
+ removed?: boolean;
139
+ }) => emitWalletEvent(WALLET_EVENTS.ASSET_CHANGED, data),
140
+
141
+ txCreated: (data: {
142
+ walletAddress: string;
143
+ id: string;
144
+ type: string;
145
+ txHash?: string;
146
+ amount?: string;
147
+ tokenAddress?: string;
148
+ tokenAmount?: string;
149
+ description?: string;
150
+ }) => emitWalletEvent(WALLET_EVENTS.TX_CREATED, data),
151
+
152
+ actionCreated: (data: {
153
+ id: string;
154
+ type: string;
155
+ source: string;
156
+ summary: string;
157
+ expiresAt: number | null;
158
+ metadata?: Record<string, unknown>;
159
+ }) => emitWalletEvent(WALLET_EVENTS.ACTION_CREATED, data),
160
+
161
+ actionResolved: (data: {
162
+ id: string;
163
+ type: string;
164
+ approved: boolean;
165
+ resolvedBy: string;
166
+ }) => emitWalletEvent(WALLET_EVENTS.ACTION_RESOLVED, data),
167
+
168
+ vaultUnlocked: (data: { address: string; vaultId: string }) =>
169
+ emitWalletEvent(WALLET_EVENTS.VAULT_UNLOCKED, data),
170
+
171
+ credentialChanged: (data: {
172
+ credentialId: string;
173
+ vaultId: string;
174
+ change:
175
+ | 'created'
176
+ | 'updated'
177
+ | 'archived'
178
+ | 'moved_to_recently_deleted'
179
+ | 'restored_to_active'
180
+ | 'restored_to_archive'
181
+ | 'purged'
182
+ | 'duplicated';
183
+ actorType: 'admin' | 'agent';
184
+ agentId?: string;
185
+ tokenHash?: string;
186
+ fromLocation?: 'active' | 'archive' | 'recently_deleted';
187
+ toLocation?: 'active' | 'archive' | 'recently_deleted';
188
+ }) => emitWalletEvent(WALLET_EVENTS.CREDENTIAL_CHANGED, data),
189
+
190
+ credentialAccessed: (data: {
191
+ credentialId: string;
192
+ vaultId: string;
193
+ action: 'credentials.read' | 'credentials.totp';
194
+ allowed: boolean;
195
+ reasonCode: string;
196
+ httpStatus: number;
197
+ actorType: 'admin' | 'agent';
198
+ agentId?: string;
199
+ tokenHash?: string;
200
+ }) => emitWalletEvent(WALLET_EVENTS.CREDENTIAL_ACCESSED, data),
201
+
202
+ secretAccessed: (data: {
203
+ credentialId: string;
204
+ credentialName: string;
205
+ vaultId: string;
206
+ surface: 'inject_secret' | 'get_secret';
207
+ envVar?: string;
208
+ agentId?: string;
209
+ tokenHash?: string;
210
+ }) => emitWalletEvent(WALLET_EVENTS.SECRET_ACCESSED, data),
211
+
212
+ /**
213
+ * Generic event emitter for custom/new event types
214
+ * Events are automatically stored in the database
215
+ */
216
+ custom: <T>(type: string, data: T) => emitWalletEvent(type, data),
217
+ };