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.
- package/LICENSE +26 -0
- package/README.md +112 -0
- package/bin/aurawallet.js +121 -0
- package/docs/ADAPTERS.md +467 -0
- package/docs/API.md +2679 -0
- package/docs/APPS.md +198 -0
- package/docs/ARCHITECTURE.md +350 -0
- package/docs/AUTH.md +698 -0
- package/docs/BEST-PRACTICES.md +121 -0
- package/docs/CLI.md +61 -0
- package/docs/DEVELOPING-APPS.md +452 -0
- package/docs/EXTENSION.md +97 -0
- package/docs/JOBS.md +33 -0
- package/docs/MCP.md +76 -0
- package/docs/PROTOCOL.md +142 -0
- package/docs/SETUP.md +219 -0
- package/docs/WORKSPACE.md +672 -0
- package/docs/agent-auth.md +63 -0
- package/docs/aura-file.md +48 -0
- package/docs/credentials.md +53 -0
- package/docs/external/getting-started.md +65 -0
- package/docs/external/overview.md +45 -0
- package/docs/external/use-cases.md +48 -0
- package/docs/external/why-aura.md +35 -0
- package/docs/jobs/connect-agent.md +77 -0
- package/docs/jobs/migrate-from-dotenv.md +79 -0
- package/docs/jobs/recover-from-lockout.md +72 -0
- package/docs/jobs/secure-ci.md +63 -0
- package/docs/oauth2.md +42 -0
- package/docs/passkeys.md +60 -0
- package/docs/security.md +540 -0
- package/docs/specs/aura-open-protocol.md +61 -0
- package/docs/specs/aura-provider-plugin.md +24 -0
- package/docs/specs/aura-registry-model.md +31 -0
- package/docs/specs/fixtures/invalid-bad-key.aura +1 -0
- package/docs/specs/fixtures/invalid-bad-unicode-escape.aura +1 -0
- package/docs/specs/fixtures/invalid-duplicate-key.aura +2 -0
- package/docs/specs/fixtures/valid-basic.aura +4 -0
- package/docs/specs/fixtures/valid-provider-ref.aura +1 -0
- package/docs/specs/fixtures/valid-quoted-escapes.aura +2 -0
- package/docs/templates/RELEASE_NOTES_TEMPLATE.md +22 -0
- package/docs/totp.md +40 -0
- package/docs/wallet/AI.md +508 -0
- package/docs/wallet/DEVELOPING-STRATEGIES.md +713 -0
- package/docs/wallet/README.md +47 -0
- package/docs/wallet/STRATEGY.md +89 -0
- package/next.config.ts +21 -0
- package/package.json +151 -0
- package/postcss.config.mjs +8 -0
- package/prisma/migrations/20260214170000_baseline/migration.sql +511 -0
- package/prisma/migrations/20260216214537_add_passkey_model/migration.sql +18 -0
- package/prisma/migrations/20260217150500_add_credential_access_audit/migration.sql +31 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +447 -0
- package/public/logo-chevron.svg +31 -0
- package/public/logo-concentric.svg +31 -0
- package/public/logo-crosshatch.svg +39 -0
- package/public/logo-dashed.svg +39 -0
- package/public/logo-horizontal.svg +31 -0
- package/public/logo-m56.svg +64 -0
- package/public/logo.webp +0 -0
- package/scripts/add-app.js +245 -0
- package/scripts/init.sh +57 -0
- package/scripts/migrate-apikeys-to-credentials.ts +35 -0
- package/scripts/sandbox-agent-flow.sh +235 -0
- package/scripts/sandbox.sh +175 -0
- package/scripts/validate-job-docs.mjs +125 -0
- package/server/abi/SwapHelper.json +438 -0
- package/server/cli/approval.ts +447 -0
- package/server/cli/commands/app.ts +204 -0
- package/server/cli/commands/cron.ts +24 -0
- package/server/cli/commands/doctor.ts +1007 -0
- package/server/cli/commands/env.ts +456 -0
- package/server/cli/commands/init.ts +752 -0
- package/server/cli/commands/mcp.ts +125 -0
- package/server/cli/commands/restore.ts +314 -0
- package/server/cli/commands/shell-hook.ts +468 -0
- package/server/cli/commands/start.ts +62 -0
- package/server/cli/commands/status.ts +59 -0
- package/server/cli/commands/stop.ts +14 -0
- package/server/cli/commands/token.ts +180 -0
- package/server/cli/commands/unlock.ts +49 -0
- package/server/cli/commands/vault.ts +417 -0
- package/server/cli/index.ts +328 -0
- package/server/cli/lib/aura-parser.ts +64 -0
- package/server/cli/lib/credential-create.ts +74 -0
- package/server/cli/lib/credential-resolve.ts +254 -0
- package/server/cli/lib/dotenv-migrate.ts +116 -0
- package/server/cli/lib/dotenv-parser.ts +146 -0
- package/server/cli/lib/http.ts +91 -0
- package/server/cli/lib/init-steps.ts +76 -0
- package/server/cli/lib/local-agent-trust.ts +45 -0
- package/server/cli/lib/process.ts +136 -0
- package/server/cli/lib/prompt.ts +85 -0
- package/server/cli/lib/theme.ts +240 -0
- package/server/cli/socket.ts +570 -0
- package/server/cli/transport-client.ts +50 -0
- package/server/cron/index.ts +137 -0
- package/server/cron/job.ts +31 -0
- package/server/cron/jobs/balance-sync.ts +436 -0
- package/server/cron/jobs/incoming-scan.ts +506 -0
- package/server/cron/jobs/native-price.ts +70 -0
- package/server/cron/jobs/orphan-cleanup.ts +40 -0
- package/server/cron/jobs/strategy-runner.ts +175 -0
- package/server/cron/scheduler.ts +125 -0
- package/server/index.ts +406 -0
- package/server/lib/adapters/factory.ts +110 -0
- package/server/lib/adapters/index.ts +19 -0
- package/server/lib/adapters/router.ts +297 -0
- package/server/lib/adapters/telegram.ts +645 -0
- package/server/lib/adapters/types.ts +89 -0
- package/server/lib/adapters/webhook.ts +95 -0
- package/server/lib/address.ts +49 -0
- package/server/lib/agent-auth/contracts.ts +1194 -0
- package/server/lib/agent-profiles.ts +328 -0
- package/server/lib/ai.ts +285 -0
- package/server/lib/api-registry/contracts.ts +86 -0
- package/server/lib/api-registry/validation.ts +172 -0
- package/server/lib/apikey-migration.ts +189 -0
- package/server/lib/app-installer.ts +505 -0
- package/server/lib/app-tokens.ts +247 -0
- package/server/lib/auth.ts +314 -0
- package/server/lib/batch.ts +242 -0
- package/server/lib/cold.ts +874 -0
- package/server/lib/config.ts +381 -0
- package/server/lib/credential-access-audit.ts +85 -0
- package/server/lib/credential-access-policy.ts +110 -0
- package/server/lib/credential-health.ts +343 -0
- package/server/lib/credential-import.ts +487 -0
- package/server/lib/credential-scope.ts +87 -0
- package/server/lib/credential-shares.ts +190 -0
- package/server/lib/credential-transport.ts +342 -0
- package/server/lib/credential-vault.ts +77 -0
- package/server/lib/credentials.ts +333 -0
- package/server/lib/crypto.ts +8 -0
- package/server/lib/db.ts +15 -0
- package/server/lib/defaults.ts +366 -0
- package/server/lib/dex/index.ts +80 -0
- package/server/lib/dex/relay.ts +235 -0
- package/server/lib/dex/types.ts +59 -0
- package/server/lib/dex/uniswap.ts +370 -0
- package/server/lib/e2e-agent/artifacts.ts +36 -0
- package/server/lib/e2e-agent/contracts.ts +112 -0
- package/server/lib/e2e-agent/validation.ts +135 -0
- package/server/lib/encrypt.ts +128 -0
- package/server/lib/error.ts +20 -0
- package/server/lib/events.ts +205 -0
- package/server/lib/hot.ts +357 -0
- package/server/lib/key-fingerprint.ts +28 -0
- package/server/lib/logger.ts +331 -0
- package/server/lib/network.ts +137 -0
- package/server/lib/notifications.ts +219 -0
- package/server/lib/oauth2-refresh.ts +241 -0
- package/server/lib/oursecret.ts +54 -0
- package/server/lib/passkey-credential.ts +360 -0
- package/server/lib/passkey.ts +68 -0
- package/server/lib/permissions.ts +248 -0
- package/server/lib/pino.ts +24 -0
- package/server/lib/policy-preview.ts +138 -0
- package/server/lib/price.ts +338 -0
- package/server/lib/prices.ts +34 -0
- package/server/lib/project-scope.ts +239 -0
- package/server/lib/resolve-action.ts +427 -0
- package/server/lib/resolve.ts +36 -0
- package/server/lib/sessions.ts +632 -0
- package/server/lib/solana/connection.ts +26 -0
- package/server/lib/solana/jupiter.ts +128 -0
- package/server/lib/solana/transfer.ts +108 -0
- package/server/lib/solana/wallet.ts +136 -0
- package/server/lib/strategy/emits.ts +21 -0
- package/server/lib/strategy/engine.ts +1305 -0
- package/server/lib/strategy/executor.ts +115 -0
- package/server/lib/strategy/hook-context.ts +158 -0
- package/server/lib/strategy/hooks.ts +990 -0
- package/server/lib/strategy/index.ts +28 -0
- package/server/lib/strategy/installer.ts +305 -0
- package/server/lib/strategy/loader.ts +256 -0
- package/server/lib/strategy/message.ts +235 -0
- package/server/lib/strategy/repository.ts +218 -0
- package/server/lib/strategy/session-logger.ts +693 -0
- package/server/lib/strategy/sources.ts +288 -0
- package/server/lib/strategy/state.ts +189 -0
- package/server/lib/strategy/templates.ts +403 -0
- package/server/lib/strategy/tick.ts +404 -0
- package/server/lib/strategy/types.ts +230 -0
- package/server/lib/swap.ts +3 -0
- package/server/lib/temp.ts +86 -0
- package/server/lib/token-metadata.ts +86 -0
- package/server/lib/token-safety.ts +200 -0
- package/server/lib/token-search.ts +444 -0
- package/server/lib/totp.ts +194 -0
- package/server/lib/transactions.ts +123 -0
- package/server/lib/transport.ts +75 -0
- package/server/lib/txhistory/decoder.ts +262 -0
- package/server/lib/txhistory/enricher.ts +652 -0
- package/server/lib/txhistory/index.ts +391 -0
- package/server/lib/txhistory/signatures.ts +59 -0
- package/server/lib/verified-summary.ts +421 -0
- package/server/mcp/profile-policy.ts +30 -0
- package/server/mcp/server.ts +619 -0
- package/server/mcp/tools.ts +523 -0
- package/server/middleware/auth.ts +119 -0
- package/server/middleware/requestLogger.ts +84 -0
- package/server/routes/actions.ts +459 -0
- package/server/routes/adapters.ts +703 -0
- package/server/routes/addressbook.ts +113 -0
- package/server/routes/ai.ts +34 -0
- package/server/routes/apikeys.ts +295 -0
- package/server/routes/apps.ts +601 -0
- package/server/routes/auth.ts +457 -0
- package/server/routes/backup.ts +340 -0
- package/server/routes/batch.ts +270 -0
- package/server/routes/bookmarks.ts +162 -0
- package/server/routes/credential-shares.ts +198 -0
- package/server/routes/credential-vaults.ts +154 -0
- package/server/routes/credentials.ts +1290 -0
- package/server/routes/dashboard.ts +71 -0
- package/server/routes/defaults.ts +124 -0
- package/server/routes/fund.ts +229 -0
- package/server/routes/import.ts +352 -0
- package/server/routes/launch.ts +665 -0
- package/server/routes/lock.ts +54 -0
- package/server/routes/logs.ts +68 -0
- package/server/routes/nuke.ts +111 -0
- package/server/routes/passkey-credentials.ts +99 -0
- package/server/routes/passkey.ts +346 -0
- package/server/routes/portfolio.ts +217 -0
- package/server/routes/price.ts +63 -0
- package/server/routes/resolve.ts +31 -0
- package/server/routes/security.ts +45 -0
- package/server/routes/send-evm.ts +241 -0
- package/server/routes/send-solana.ts +281 -0
- package/server/routes/send.ts +178 -0
- package/server/routes/setup.ts +210 -0
- package/server/routes/strategy.ts +894 -0
- package/server/routes/swap-evm.ts +353 -0
- package/server/routes/swap-solana.ts +177 -0
- package/server/routes/swap.ts +356 -0
- package/server/routes/token.ts +247 -0
- package/server/routes/unlock.ts +403 -0
- package/server/routes/wallet-assets.ts +361 -0
- package/server/routes/wallet-transactions.ts +515 -0
- package/server/routes/wallet.ts +710 -0
- package/server/types.ts +146 -0
- package/skills/aurawallet/SKILL.md +739 -0
- package/skills/aurawallet-setup/SKILL.md +74 -0
- package/skills/security-review/SKILL.md +148 -0
- package/src/app/api/agent-requests/route.ts +30 -0
- package/src/app/api/apps/install/route.ts +126 -0
- package/src/app/api/apps/manifests/route.ts +16 -0
- package/src/app/api/apps/static/[...path]/route.ts +57 -0
- package/src/app/api/events/route.ts +92 -0
- package/src/app/api/page.tsx +212 -0
- package/src/app/api/workspace/[id]/apps/[wid]/route.ts +119 -0
- package/src/app/api/workspace/[id]/apps/route.ts +81 -0
- package/src/app/api/workspace/[id]/export/route.ts +67 -0
- package/src/app/api/workspace/[id]/route.ts +168 -0
- package/src/app/api/workspace/auth.ts +34 -0
- package/src/app/api/workspace/config/route.ts +106 -0
- package/src/app/api/workspace/import/route.ts +127 -0
- package/src/app/api/workspace/route.ts +116 -0
- package/src/app/app/page.tsx +2122 -0
- package/src/app/apple-icon.png +0 -0
- package/src/app/docs/page.tsx +178 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +572 -0
- package/src/app/health/page.tsx +5 -0
- package/src/app/hello/page.tsx +15 -0
- package/src/app/icon.png +0 -0
- package/src/app/layout.tsx +34 -0
- package/src/app/page.tsx +986 -0
- package/src/app/providers.tsx +90 -0
- package/src/app/share/[token]/page.tsx +295 -0
- package/src/components/ChainSelector.tsx +144 -0
- package/src/components/HumanActionBar.tsx +695 -0
- package/src/components/NotificationDrawer.tsx +129 -0
- package/src/components/apps/AgentKeysApp.tsx +490 -0
- package/src/components/apps/App.tsx +153 -0
- package/src/components/apps/AppGrid.tsx +15 -0
- package/src/components/apps/DetailedAddressDrawer.tsx +325 -0
- package/src/components/apps/DraggableApp.tsx +562 -0
- package/src/components/apps/IFrameApp.tsx +73 -0
- package/src/components/apps/LogsApp.tsx +360 -0
- package/src/components/apps/SendApp.tsx +394 -0
- package/src/components/apps/SetupWizardApp.tsx +1004 -0
- package/src/components/apps/SystemDefaultsApp.tsx +845 -0
- package/src/components/apps/ThirdPartyApp.tsx +428 -0
- package/src/components/apps/TokenApp.tsx +319 -0
- package/src/components/apps/TransactionsApp.tsx +438 -0
- package/src/components/apps/WalletDetailApp.tsx +1505 -0
- package/src/components/apps/index.ts +13 -0
- package/src/components/design-system/Button.tsx +53 -0
- package/src/components/design-system/ChainIndicator.tsx +65 -0
- package/src/components/design-system/ChainSelector.tsx +137 -0
- package/src/components/design-system/ConfirmationModal.tsx +106 -0
- package/src/components/design-system/ConfirmationPopover.tsx +81 -0
- package/src/components/design-system/Drawer.tsx +123 -0
- package/src/components/design-system/FilterDropdown.tsx +72 -0
- package/src/components/design-system/Modal.tsx +206 -0
- package/src/components/design-system/Popover.tsx +142 -0
- package/src/components/design-system/TextInput.tsx +85 -0
- package/src/components/design-system/Toggle.tsx +58 -0
- package/src/components/design-system/index.ts +11 -0
- package/src/components/docs/DocsThemeToggle.tsx +49 -0
- package/src/components/health/CredentialHealthDashboard.tsx +214 -0
- package/src/components/icons/ChainIcons.tsx +72 -0
- package/src/components/layout/AppStoreDrawer.tsx +369 -0
- package/src/components/layout/ContentArea.tsx +21 -0
- package/src/components/layout/TabBar.tsx +278 -0
- package/src/components/layout/WalletSidebar.tsx +1033 -0
- package/src/components/layout/index.ts +4 -0
- package/src/components/marketing/AuraWalletSpecOverlay.tsx +635 -0
- package/src/components/marketing/DeviceMorphExperience.tsx +216 -0
- package/src/components/vault/ApiKeysConsole.tsx +1080 -0
- package/src/components/vault/AuditConsole.tsx +584 -0
- package/src/components/vault/CredentialDetail.tsx +455 -0
- package/src/components/vault/CredentialEmpty.tsx +55 -0
- package/src/components/vault/CredentialField.tsx +361 -0
- package/src/components/vault/CredentialForm.tsx +1212 -0
- package/src/components/vault/CredentialList.tsx +165 -0
- package/src/components/vault/CredentialRow.tsx +97 -0
- package/src/components/vault/CredentialShareModal.tsx +178 -0
- package/src/components/vault/CredentialVault.tsx +754 -0
- package/src/components/vault/CredentialWalletWidget.tsx +103 -0
- package/src/components/vault/ImportCredentialsModal.tsx +515 -0
- package/src/components/vault/LargeTypeModal.tsx +64 -0
- package/src/components/vault/PasswordGenerator.tsx +224 -0
- package/src/components/vault/TOTPDisplay.tsx +123 -0
- package/src/components/vault/VaultSidebar.tsx +413 -0
- package/src/components/vault/types.ts +54 -0
- package/src/context/AuthContext.tsx +337 -0
- package/src/context/PriceContext.tsx +113 -0
- package/src/context/ThemeContext.tsx +164 -0
- package/src/context/WebSocketContext.tsx +269 -0
- package/src/context/WorkspaceContext.tsx +668 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useAgentActions.ts +368 -0
- package/src/hooks/useBalance.ts +103 -0
- package/src/hooks/useBalances.ts +129 -0
- package/src/instrumentation.ts +12 -0
- package/src/lib/api.ts +449 -0
- package/src/lib/app-loader.ts +148 -0
- package/src/lib/app-registry.ts +178 -0
- package/src/lib/app-sdk.ts +157 -0
- package/src/lib/audit-console-adapter.ts +151 -0
- package/src/lib/auth-client.ts +75 -0
- package/src/lib/config.ts +74 -0
- package/src/lib/crypto.ts +112 -0
- package/src/lib/db.ts +21 -0
- package/src/lib/docs.ts +390 -0
- package/src/lib/events.ts +361 -0
- package/src/lib/pino.ts +24 -0
- package/src/lib/theme-handlers.ts +168 -0
- package/src/lib/theme.ts +351 -0
- package/src/lib/tokenData.ts +378 -0
- package/src/lib/vault-crypto.ts +129 -0
- package/src/lib/websocket-server.ts +302 -0
- package/src/lib/websocket-setup.ts +79 -0
- package/src/lib/wordlist.ts +2050 -0
- package/src/lib/workspace-handlers.ts +285 -0
- package/start.sh +80 -0
- package/tailwind.config.ts +99 -0
- 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
|
+
}
|