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,74 @@
1
+ ---
2
+ name: aurawallet-setup
3
+ description: |
4
+ Setup-only AuraWallet skill for MCP agents. Use this when the user needs onboarding,
5
+ vault initialization, unlock, and first scoped API key issuance.
6
+ compatibility: Requires Node.js 18+ and local AuraWallet server/dashboard.
7
+ allowed-tools: Bash(npx aurawallet *), Bash(curl *), MCP(create_vault,wallet_api,request_human_action)
8
+ metadata:
9
+ author: auramaxx
10
+ version: "1.0"
11
+ ---
12
+
13
+ # AuraWallet Setup Skill (MCP)
14
+
15
+ Use this skill when the user asks to get started, onboard, initialize, unlock, or bootstrap agent access.
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ TMP_SKILL_DIR="$(mktemp -d /tmp/aurawallet-setup-skill-XXXXXX)"
21
+ cp -R ./skills/aurawallet-setup "$TMP_SKILL_DIR/"
22
+ npx -y skills add "$TMP_SKILL_DIR/aurawallet-setup" --yes
23
+ ```
24
+
25
+ If the skill is already pushed to GitHub, you can install by ref:
26
+
27
+ ```bash
28
+ python3 ~/.codex/skills/.system/skill-installer/scripts/install-skill-from-github.py \
29
+ --repo Aura-Industry/aurawallet \
30
+ --path skills/aurawallet-setup \
31
+ --ref <branch-or-commit>
32
+ ```
33
+
34
+ ## Agent Prompt
35
+
36
+ Example user prompt:
37
+
38
+ `Use the AuraWallet setup skill and onboard me via MCP.`
39
+
40
+ ## Setup Flow
41
+
42
+ 1. Check service health:
43
+
44
+ ```text
45
+ wallet_api GET /health
46
+ wallet_api GET /setup
47
+ ```
48
+
49
+ 2. If wallet is missing:
50
+ - Human-assisted: `npx aurawallet init --dashboard`
51
+ - Autonomous: `create_vault` with a generated password
52
+
53
+ 3. If wallet exists but locked:
54
+ - Prefer dashboard unlock (`http://localhost:4747/app`)
55
+ - Fallback: `npx aurawallet unlock`
56
+
57
+ 4. Bootstrap an agent token:
58
+ - Request token with least privilege first:
59
+ - `secret:read`
60
+ - `secret:write`
61
+ - Use `request_human_action` if approval is needed.
62
+
63
+ 5. Validate setup complete:
64
+
65
+ ```text
66
+ wallet_api GET /setup
67
+ ```
68
+
69
+ ## Done Criteria
70
+
71
+ - `hasWallet=true`
72
+ - `unlocked=true`
73
+ - agent has an active scoped token
74
+ - user gets a short summary of what was configured and what remains optional
@@ -0,0 +1,148 @@
1
+ ---
2
+ name: security-review
3
+ description: |
4
+ Security review checklist for AuraWallet Express server changes.
5
+ Use when: modifying server/routes/*.ts, adding new endpoints,
6
+ changing authentication logic, or updating permissions.
7
+ Also use after completing any task that touches the wallet server.
8
+ ---
9
+
10
+ # Security Review Checklist
11
+
12
+ Use this checklist when modifying the Express wallet server.
13
+
14
+ ## Before Completing Any Task
15
+
16
+ 1. **All tests pass** - Run `npm test` and ensure all tests pass
17
+ 2. **Documentation updated** - See checklist below
18
+
19
+ ## Documentation Checklist
20
+
21
+ Update the relevant docs when making changes:
22
+
23
+ | Change Type | Update |
24
+ |-------------|--------|
25
+ | New/modified endpoint | `docs/API.md` - add endpoint spec |
26
+ | New/modified permission | `docs/AUTH.md` - update permission matrix |
27
+ | New route with auth | `docs/AUTH.md` - add to route→permission table |
28
+ | WebSocket event changes | `docs/WORKSPACE.md` - update event reference |
29
+ | Security model changes | `docs/security.md` - update architecture |
30
+ | New wallet tier/feature | `CLAUDE.md` - update overview |
31
+
32
+ ## Security Architecture Requirements
33
+
34
+ - [ ] Auth decisions use memory only (not database)
35
+ - [ ] Permissions are properly checked via `requirePermission` middleware
36
+ - [ ] Wallet ownership is enforced (token can only access owned wallets)
37
+ - [ ] Cold wallet operations require human approval (unlocked wallet)
38
+ - [ ] No spending limit bypass (fund endpoint enforces limits)
39
+
40
+ ## Route Permission Checklist
41
+
42
+ When adding a new endpoint:
43
+
44
+ 1. Add permission to `server/lib/permissions.ts` if needed
45
+ 2. Add `requirePermission('permission:name')` middleware
46
+ 3. Add endpoint spec to `docs/API.md`
47
+ 4. Add route to permission matrix in `docs/AUTH.md`
48
+ 5. If permission should be in `trade:all` or `wallet:write`, update compound expansion in `server/lib/permissions.ts`
49
+
50
+ ## Key Files to Review
51
+
52
+ - `server/lib/auth.ts` - Token signing/validation (SIGNING_KEY)
53
+ - `server/lib/sessions.ts` - Spending limit tracking (memory Map)
54
+ - `server/lib/permissions.ts` - Permission definitions + compound expansion
55
+ - `server/middleware/auth.ts` - Auth middleware (signature, expiry, revocation, permissions)
56
+
57
+ ## Common Security Mistakes
58
+
59
+ - Using database for auth decisions (must use memory)
60
+ - Forgetting wallet ownership check on wallet operations
61
+ - Not updating AUTH.md permission matrix
62
+ - Skipping tests for auth edge cases
63
+ - Not checking if new permission belongs in `trade:all` compound
64
+
65
+ ## Security Model Summary
66
+
67
+ ```
68
+ IN MEMORY (security-critical): IN DATABASE (UI/logs only):
69
+ ├── SIGNING_KEY (random 32 bytes) ├── AgentToken table
70
+ ├── sessions Map (spending tracking) │ ├── tokenHash (for display)
71
+ └── revokedTokens Set │ ├── agentId, limit, spent
72
+ │ └── isRevoked, expiresAt
73
+ ```
74
+
75
+ **Key principle**: Auth decisions use ONLY memory. DB is just for display.
76
+
77
+ ## Token Validation Checklist
78
+
79
+ When working with token validation:
80
+
81
+ - [ ] Token signature verified with SIGNING_KEY
82
+ - [ ] Token expiry checked
83
+ - [ ] Token revocation checked against revokedTokens Set
84
+ - [ ] Permissions expanded (compound → individual)
85
+ - [ ] Required permission checked
86
+
87
+ ## Wallet Access Checklist
88
+
89
+ When working with wallet operations:
90
+
91
+ - [ ] Token ownership verified (tokenHash matches wallet.tokenHash)
92
+ - [ ] OR wallet in token's walletAccess array
93
+ - [ ] Ownership checked BEFORE executing the operation
94
+ - [ ] Cold wallet requires unlocked state for operations
95
+ - [ ] Hot wallet keys encrypted with mnemonic
96
+
97
+ ## Spending Limit Checklist
98
+
99
+ When working with spending endpoints (`/fund`, `/send`, `/swap`):
100
+
101
+ - [ ] Limit embedded in token (tamper-proof)
102
+ - [ ] Spending tracked in memory sessions Map
103
+ - [ ] Amount checked against remaining limit
104
+ - [ ] Spent amount updated after successful transfer
105
+ - [ ] Send/swap limits are optional (can be null/undefined)
106
+ - [ ] Sends to cold wallet address bypass send limit (returning funds)
107
+ - [ ] Admin tokens bypass all limits
108
+
109
+ ## What Restart Does
110
+
111
+ 1. New SIGNING_KEY generated → all old tokens invalid
112
+ 2. Memory sessions cleared → spending tracking reset
113
+ 3. Revocation list cleared → (tokens invalid anyway)
114
+ 4. Cold wallet locks → requires password to unlock
115
+ 5. Agents must request new approval
116
+
117
+ **This is intentional security, not a bug.**
118
+
119
+ ## Quick Reference: Route → Permission
120
+
121
+ | Route | Permission |
122
+ |-------|------------|
123
+ | `GET /wallets` | `wallet:list` |
124
+ | `POST /wallet/create` | `wallet:create:hot` or `wallet:create:temp` |
125
+ | `POST /wallet/rename` | `wallet:rename` |
126
+ | `POST /send` | `send:hot` or `send:temp` |
127
+ | `POST /swap` | `swap` |
128
+ | `POST /fund` | `fund` |
129
+ | `POST /launch` | `launch` |
130
+ | `POST /actions` | `action:create` |
131
+ | `GET /apikeys` | `apikey:get` |
132
+ | `POST /apikeys` | `apikey:set` |
133
+ | `DELETE /apikeys/:id` | `apikey:set` |
134
+ | `GET /strategies*` | `strategy:read` |
135
+ | `POST /strategies/*` | `strategy:manage` |
136
+ | App storage endpoints | `app:storage` |
137
+ | `POST /apps/:id/message` | `app:accesskey` |
138
+ | WebSocket mutations | `workspace:modify` |
139
+ | `GET /adapters` | `adapter:manage` |
140
+ | `POST /adapters` | `adapter:manage` |
141
+ | `/actions/resolve`, `/lock`, `/nuke` | `admin:*` |
142
+
143
+ ## Compound Permissions
144
+
145
+ | Compound | Expands To |
146
+ |----------|-----------|
147
+ | `trade:all` | `wallet:list`, `wallet:create:hot`, `wallet:create:temp`, `send:hot`, `send:temp`, `swap`, `fund`, `launch`, `apikey:get`, `strategy:read` |
148
+ | `wallet:write` | `wallet:create:hot`, `wallet:create:temp`, `wallet:rename`, `wallet:tx:add`, `wallet:asset:add`, `wallet:asset:remove` |
@@ -0,0 +1,30 @@
1
+ import { NextResponse } from 'next/server';
2
+
3
+ const EXPRESS_URL = process.env.WALLET_SERVER_URL || 'http://localhost:4242';
4
+
5
+ /**
6
+ * GET /api/agent-requests
7
+ * Proxy to Express /dashboard endpoint for agent actions and tokens
8
+ * No authentication required - returns pending actions and tokens
9
+ */
10
+ export async function GET() {
11
+ try {
12
+ const response = await fetch(`${EXPRESS_URL}/dashboard`);
13
+ const data = await response.json();
14
+
15
+ if (!response.ok) {
16
+ return NextResponse.json(
17
+ { success: false, error: data.error || 'Failed to fetch agent requests' },
18
+ { status: response.status }
19
+ );
20
+ }
21
+
22
+ return NextResponse.json(data);
23
+ } catch (error) {
24
+ console.error('[AgentDashboard] Error fetching from Express:', error);
25
+ return NextResponse.json(
26
+ { success: false, error: 'Failed to fetch agent requests' },
27
+ { status: 500 }
28
+ );
29
+ }
30
+ }
@@ -0,0 +1,126 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { installApp, removeApp } from '../../../../../server/lib/app-installer';
3
+
4
+ const WALLET_API = process.env.WALLET_SERVER_URL || 'http://localhost:4242';
5
+
6
+ /**
7
+ * Validate admin access by forwarding the Authorization header to Express.
8
+ * Returns true if the token is valid and has admin permissions.
9
+ */
10
+ async function validateAdmin(authHeader: string | null): Promise<boolean> {
11
+ if (!authHeader) return false;
12
+
13
+ try {
14
+ // Use a lightweight endpoint to verify the token is valid + admin
15
+ const resp = await fetch(`${WALLET_API}/setup`, {
16
+ headers: { Authorization: authHeader },
17
+ });
18
+ return resp.ok;
19
+ } catch {
20
+ return false;
21
+ }
22
+ }
23
+
24
+ /**
25
+ * POST /api/apps/install — Install a app from a source
26
+ * Body: { source: string, name?: string, force?: boolean }
27
+ */
28
+ export async function POST(req: NextRequest) {
29
+ const authHeader = req.headers.get('authorization');
30
+ const isAdmin = await validateAdmin(authHeader);
31
+ if (!isAdmin) {
32
+ return NextResponse.json(
33
+ { success: false, error: 'Admin access required' },
34
+ { status: 403 },
35
+ );
36
+ }
37
+
38
+ try {
39
+ const body = await req.json();
40
+ const { source, name, force } = body;
41
+
42
+ if (!source || typeof source !== 'string') {
43
+ return NextResponse.json(
44
+ { success: false, error: 'source is required' },
45
+ { status: 400 },
46
+ );
47
+ }
48
+
49
+ const result = installApp(source, { name, force });
50
+
51
+ // Hot-reload: create token for the new app without restart
52
+ try {
53
+ await fetch(`${WALLET_API}/apps/${result.id}/reload`, {
54
+ method: 'POST',
55
+ headers: {
56
+ Authorization: authHeader!,
57
+ 'Content-Type': 'application/json',
58
+ },
59
+ });
60
+ } catch {
61
+ // Non-critical — app will get a token on next server restart
62
+ }
63
+
64
+ return NextResponse.json({
65
+ success: true,
66
+ app: {
67
+ id: result.id,
68
+ name: result.name,
69
+ source: result.source,
70
+ },
71
+ });
72
+ } catch (err) {
73
+ const message = err instanceof Error ? err.message : 'Install failed';
74
+ return NextResponse.json(
75
+ { success: false, error: message },
76
+ { status: 400 },
77
+ );
78
+ }
79
+ }
80
+
81
+ /**
82
+ * DELETE /api/apps/install — Remove an installed app
83
+ * Body: { appId: string }
84
+ */
85
+ export async function DELETE(req: NextRequest) {
86
+ const authHeader = req.headers.get('authorization');
87
+ const isAdmin = await validateAdmin(authHeader);
88
+ if (!isAdmin) {
89
+ return NextResponse.json(
90
+ { success: false, error: 'Admin access required' },
91
+ { status: 403 },
92
+ );
93
+ }
94
+
95
+ try {
96
+ const body = await req.json();
97
+ const { appId } = body;
98
+
99
+ if (!appId || typeof appId !== 'string') {
100
+ return NextResponse.json(
101
+ { success: false, error: 'appId is required' },
102
+ { status: 400 },
103
+ );
104
+ }
105
+
106
+ // Revoke the app's token via Express (separate process, holds token in memory)
107
+ try {
108
+ await fetch(`${WALLET_API}/apps/${appId}/approve`, {
109
+ method: 'DELETE',
110
+ headers: { Authorization: authHeader! },
111
+ });
112
+ } catch {
113
+ // Non-critical if Express is down — token expires in 24h max
114
+ }
115
+
116
+ removeApp(appId);
117
+
118
+ return NextResponse.json({ success: true, appId, removed: true });
119
+ } catch (err) {
120
+ const message = err instanceof Error ? err.message : 'Remove failed';
121
+ return NextResponse.json(
122
+ { success: false, error: message },
123
+ { status: 400 },
124
+ );
125
+ }
126
+ }
@@ -0,0 +1,16 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { loadAppManifests } from '@/lib/app-loader';
3
+
4
+ // GET /api/apps/manifests - Return all loaded app manifests
5
+ export async function GET() {
6
+ try {
7
+ const manifests = loadAppManifests();
8
+ return NextResponse.json({ success: true, manifests });
9
+ } catch (error) {
10
+ console.error('Failed to load app manifests:', error);
11
+ return NextResponse.json(
12
+ { success: false, error: 'Failed to load app manifests' },
13
+ { status: 500 }
14
+ );
15
+ }
16
+ }
@@ -0,0 +1,57 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+
5
+ const MIME_TYPES: Record<string, string> = {
6
+ '.html': 'text/html',
7
+ '.css': 'text/css',
8
+ '.js': 'application/javascript',
9
+ '.json': 'application/json',
10
+ '.png': 'image/png',
11
+ '.jpg': 'image/jpeg',
12
+ '.svg': 'image/svg+xml',
13
+ '.gif': 'image/gif',
14
+ '.ico': 'image/x-icon',
15
+ '.woff': 'font/woff',
16
+ '.woff2': 'font/woff2',
17
+ };
18
+
19
+ // GET /api/apps/static/[...path] - Serve static files from apps/ directory
20
+ export async function GET(
21
+ _request: NextRequest,
22
+ { params }: { params: Promise<{ path: string[] }> }
23
+ ) {
24
+ try {
25
+ const { path: segments } = await params;
26
+ const relativePath = segments.join('/');
27
+
28
+ // Security: prevent path traversal
29
+ if (relativePath.includes('..') || relativePath.includes('\0')) {
30
+ return NextResponse.json({ error: 'Invalid path' }, { status: 400 });
31
+ }
32
+
33
+ const appsDir = path.join(process.cwd(), 'apps');
34
+ const filePath = path.join(appsDir, relativePath);
35
+
36
+ // Ensure resolved path is within apps/
37
+ const resolved = path.resolve(filePath);
38
+ if (!resolved.startsWith(path.resolve(appsDir))) {
39
+ return NextResponse.json({ error: 'Invalid path' }, { status: 400 });
40
+ }
41
+
42
+ if (!fs.existsSync(filePath) || fs.statSync(filePath).isDirectory()) {
43
+ return NextResponse.json({ error: 'Not found' }, { status: 404 });
44
+ }
45
+
46
+ const ext = path.extname(filePath).toLowerCase();
47
+ const contentType = MIME_TYPES[ext] || 'application/octet-stream';
48
+ const content = fs.readFileSync(filePath);
49
+
50
+ return new NextResponse(content, {
51
+ headers: { 'Content-Type': contentType },
52
+ });
53
+ } catch (error) {
54
+ console.error('Failed to serve app static file:', error);
55
+ return NextResponse.json({ error: 'Not found' }, { status: 404 });
56
+ }
57
+ }
@@ -0,0 +1,92 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { broadcast } from '@/lib/websocket-server';
3
+ import { prisma } from '@/lib/db';
4
+ import type { WalletEvent } from '@/lib/events';
5
+
6
+ /**
7
+ * GET /api/events
8
+ * Query events from database with optional filtering
9
+ * No authentication required
10
+ */
11
+ export async function GET(request: NextRequest) {
12
+ try {
13
+ const { searchParams } = new URL(request.url);
14
+ const type = searchParams.get('type');
15
+ const category = searchParams.get('category');
16
+ const limit = Math.min(parseInt(searchParams.get('limit') || '50'), 250);
17
+ const offset = parseInt(searchParams.get('offset') || '0');
18
+
19
+ // Build where clause
20
+ const where: Record<string, unknown> = {};
21
+ if (type) {
22
+ where.type = type;
23
+ } else if (category) {
24
+ where.type = { startsWith: `${category}:` };
25
+ }
26
+
27
+ // Query events
28
+ const [events, total] = await Promise.all([
29
+ prisma.event.findMany({
30
+ where,
31
+ orderBy: { timestamp: 'desc' },
32
+ take: limit,
33
+ skip: offset,
34
+ }),
35
+ prisma.event.count({ where }),
36
+ ]);
37
+
38
+ return NextResponse.json({
39
+ success: true,
40
+ events: events.map((e: any) => ({
41
+ ...e,
42
+ data: typeof e.data === 'string' ? JSON.parse(e.data) : e.data,
43
+ })),
44
+ pagination: {
45
+ total,
46
+ limit,
47
+ offset,
48
+ hasMore: offset + events.length < total,
49
+ },
50
+ });
51
+ } catch (error) {
52
+ console.error('[Events] Error fetching events:', error);
53
+ return NextResponse.json(
54
+ { success: false, error: 'Failed to fetch events' },
55
+ { status: 500 }
56
+ );
57
+ }
58
+ }
59
+
60
+ /**
61
+ * POST /api/events
62
+ * Webhook endpoint to receive events from Express server
63
+ * and broadcast them to WebSocket clients
64
+ */
65
+ export async function POST(request: NextRequest) {
66
+ try {
67
+ const event: WalletEvent = await request.json();
68
+
69
+ // Validate event structure
70
+ if (!event.type || !event.timestamp || !event.data) {
71
+ return NextResponse.json(
72
+ { error: 'Invalid event structure' },
73
+ { status: 400 }
74
+ );
75
+ }
76
+
77
+ // Broadcast to all connected WebSocket clients
78
+ broadcast(event);
79
+
80
+ return NextResponse.json({
81
+ success: true,
82
+ type: event.type,
83
+ clientsNotified: true,
84
+ });
85
+ } catch (error) {
86
+ console.error('[Events] Error processing webhook:', error);
87
+ return NextResponse.json(
88
+ { error: 'Failed to process event' },
89
+ { status: 500 }
90
+ );
91
+ }
92
+ }