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
package/docs/AUTH.md
ADDED
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
# Authentication & Permissions
|
|
2
|
+
|
|
3
|
+
This document describes the authentication system and permission model for AuraWallet.
|
|
4
|
+
|
|
5
|
+
## For Agents
|
|
6
|
+
|
|
7
|
+
> **IMPORTANT**: If you're an agent, request a token via `POST /auth` and wait for human approval. You do NOT need an admin token - those are only for emergency/headless scenarios where a human is completely out of the loop.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# 1. Request access (returns requestId + secret)
|
|
11
|
+
curl -X POST http://localhost:4242/auth \
|
|
12
|
+
-H "Content-Type: application/json" \
|
|
13
|
+
-d '{"agentId": "my-agent", "permissions": ["wallet:create:hot", "send:hot", "fund"]}'
|
|
14
|
+
|
|
15
|
+
# 2. Human approves in dashboard UI
|
|
16
|
+
|
|
17
|
+
# 3. Poll for your token
|
|
18
|
+
curl "http://localhost:4242/auth/<requestId>?secret=<secret>"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Auth Flow Comparison
|
|
24
|
+
|
|
25
|
+
AuraWallet has multiple token flows for different scenarios. Use this table to pick the right one:
|
|
26
|
+
|
|
27
|
+
| Flow | Endpoint | Who Uses It | Approval | Token TTL | Use Case |
|
|
28
|
+
|------|----------|-------------|----------|-----------|----------|
|
|
29
|
+
| **Agent Request** | `POST /auth` | AI agents | Human approval required | Custom (default 1h) | Standard agent onboarding — agent requests access, human approves |
|
|
30
|
+
| **Human Unlock** | `POST /unlock` | Humans | Password (RSA-encrypted) + `pubkey` | 7 days | Unlock vault, get admin token for dashboard/API |
|
|
31
|
+
| **Direct Create** | `POST /actions/token` | Admins | Admin auth + `pubkey` | Custom | Emergency/headless — skip approval flow entirely |
|
|
32
|
+
| **Permission Upgrade** | `POST /auth/request-permissions` | Agents with token | Human approval required | Same as new token | Agent needs more permissions or wallet access |
|
|
33
|
+
| **Human Action** | `POST /actions` | Agents with `action:create` | Human approval required | Custom (default 60s) | Per-operation approval — scoped temp token for one action. Server generates verified summary from actual action params |
|
|
34
|
+
|
|
35
|
+
### Which flow should I use?
|
|
36
|
+
|
|
37
|
+
- **I'm an AI agent connecting for the first time** → `POST /auth` (standard flow)
|
|
38
|
+
- **I'm a human unlocking the wallet** → `POST /unlock` (returns admin token)
|
|
39
|
+
- **I'm an agent and need to do something outside my permissions** → `POST /actions` (request approval for one action)
|
|
40
|
+
- **I'm an agent and need permanent permission upgrades** → `POST /auth/request-permissions`
|
|
41
|
+
- **I'm running a script/CI with no human** → `POST /actions/token` (requires admin token)
|
|
42
|
+
|
|
43
|
+
### Token properties by flow
|
|
44
|
+
|
|
45
|
+
| Property | Agent Request | Human Unlock | Direct Create | Permission Upgrade | Human Action |
|
|
46
|
+
|----------|:---:|:---:|:---:|:---:|:---:|
|
|
47
|
+
| Spending limits | Yes | No | Yes | Yes | Yes |
|
|
48
|
+
| Wallet access grants | Yes | All | Yes | Yes | Yes |
|
|
49
|
+
| Survives restart | No | No | No | No | No |
|
|
50
|
+
| Revocable | Yes | Yes | Yes | Yes | Yes |
|
|
51
|
+
| Requires human | Yes | Self (password) | No (admin) | Yes | Yes |
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Overview
|
|
56
|
+
|
|
57
|
+
AuraWallet uses Bearer token authentication. Tokens are issued to agents after human approval and contain embedded permissions and spending limits.
|
|
58
|
+
|
|
59
|
+
**Key Security Properties:**
|
|
60
|
+
- Tokens are HMAC-signed with an in-memory `SIGNING_KEY`
|
|
61
|
+
- Server restart invalidates ALL tokens (new SIGNING_KEY generated)
|
|
62
|
+
- Spending limits are embedded in tokens and tracked in memory
|
|
63
|
+
- Admin tokens bypass all permission checks
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Token Types
|
|
68
|
+
|
|
69
|
+
### Agent Token
|
|
70
|
+
|
|
71
|
+
Issued to AI agents after human approval. Contains specific permissions and limits.
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
interface AgentTokenPayload {
|
|
75
|
+
agentId: string; // Identifier for the agent
|
|
76
|
+
permissions: string[]; // Permission strings (see below)
|
|
77
|
+
exp: number; // Expiration timestamp (ms)
|
|
78
|
+
|
|
79
|
+
// Per-permission limits (optional)
|
|
80
|
+
// Plain number = legacy single-currency limit (ETH)
|
|
81
|
+
// Record<string, number> = per-currency limits keyed by native token address
|
|
82
|
+
limits?: {
|
|
83
|
+
fund?: number | Record<string, number>; // Limit for cold→hot transfers
|
|
84
|
+
send?: number | Record<string, number>; // Limit for sends (optional)
|
|
85
|
+
swap?: number | Record<string, number>; // Volume limit for swaps (optional)
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// Wallet access grants
|
|
89
|
+
walletAccess?: string[]; // Additional wallet addresses this token can access
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Admin Token
|
|
94
|
+
|
|
95
|
+
Admin tokens are regular agent tokens with `admin:*` permission. Generated when wallet is unlocked via `POST /unlock`.
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// Admin token is just an AgentTokenPayload with:
|
|
99
|
+
{
|
|
100
|
+
agentId: 'admin',
|
|
101
|
+
permissions: ['admin:*'],
|
|
102
|
+
exp: <7 days from creation>,
|
|
103
|
+
// ... no limits (admin has full access)
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Key behaviors:**
|
|
108
|
+
- Multiple admin tokens can exist simultaneously (each unlock creates a new one)
|
|
109
|
+
- Admin tokens are revocable via `POST /actions/tokens/revoke`
|
|
110
|
+
- Locking the wallet does NOT auto-revoke tokens (but most admin ops require unlocked wallet)
|
|
111
|
+
- Server restart invalidates all tokens (including admin)
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Permissions Reference
|
|
116
|
+
|
|
117
|
+
### Wallet Operations
|
|
118
|
+
|
|
119
|
+
| Permission | Description | Routes |
|
|
120
|
+
|------------|-------------|--------|
|
|
121
|
+
| `wallet:list` | List and view wallets | `GET /wallets`, `GET /wallets/transactions`, `GET /wallet/:address` |
|
|
122
|
+
| `wallet:create:hot` | Create hot wallets | `POST /wallet/create` (tier: hot) |
|
|
123
|
+
| `wallet:create:temp` | Create temp wallets | `POST /wallet/create` (tier: temp) |
|
|
124
|
+
| `wallet:rename` | Update wallet metadata | `POST /wallet/rename` |
|
|
125
|
+
| `wallet:export` | Export private keys | `POST /wallet/:address/export` |
|
|
126
|
+
| `wallet:tx:add` | Add manual transaction records | `POST /wallet/:address/transactions` |
|
|
127
|
+
| `wallet:asset:add` | Add tracked assets | `POST /wallet/:address/asset` |
|
|
128
|
+
| `wallet:asset:remove` | Remove tracked assets | `DELETE /wallet/:address/asset/:id` |
|
|
129
|
+
|
|
130
|
+
### Transaction Operations
|
|
131
|
+
|
|
132
|
+
| Permission | Description | Routes |
|
|
133
|
+
|------------|-------------|--------|
|
|
134
|
+
| `send:hot` | Send from hot wallets | `POST /send` (from hot wallet) |
|
|
135
|
+
| `send:temp` | Send from temp wallets | `POST /send` (from temp wallet) |
|
|
136
|
+
| `swap` | Execute token swaps | `POST /swap` |
|
|
137
|
+
| `fund` | Transfer from cold to hot | `POST /fund` |
|
|
138
|
+
| `launch` | Execute token launches via Doppler | `POST /launch` |
|
|
139
|
+
|
|
140
|
+
### API Key Operations
|
|
141
|
+
|
|
142
|
+
| Permission | Description | Routes |
|
|
143
|
+
|------------|-------------|--------|
|
|
144
|
+
| `apikey:get` | Read API keys | `GET /apikeys` |
|
|
145
|
+
| `apikey:set` | Create/update/delete API keys | `POST /apikeys`, `DELETE /apikeys/:id` |
|
|
146
|
+
|
|
147
|
+
### Credential Vault Operations
|
|
148
|
+
|
|
149
|
+
| Permission | Description | Routes |
|
|
150
|
+
|------------|-------------|--------|
|
|
151
|
+
| `secret:read` | List credential metadata and read credential fields (encrypted to token pubkey) | `GET /credentials`, `GET /credentials/:id`, `POST /credentials/:id/read` |
|
|
152
|
+
| `secret:write` | Create, update, and delete credentials | `POST /credentials`, `PUT /credentials/:id`, `DELETE /credentials/:id` |
|
|
153
|
+
|
|
154
|
+
### Credential Access Controls
|
|
155
|
+
|
|
156
|
+
Tokens with secret permissions can include `credentialAccess`:
|
|
157
|
+
|
|
158
|
+
- `read` / `write`: scope arrays (`*`, `vault:<id>`, `tag:<name>`, or specific credential IDs)
|
|
159
|
+
- `excludeFields`: remove sensitive field keys from read responses
|
|
160
|
+
- `ttl`: credential-read lifetime in seconds from token `iat`
|
|
161
|
+
- `maxReads`: maximum successful credential reads for the token
|
|
162
|
+
|
|
163
|
+
### Agent Profiles (Policy Packs)
|
|
164
|
+
|
|
165
|
+
`POST /auth` and `POST /actions/token` support policy profile issuance:
|
|
166
|
+
|
|
167
|
+
- `profile` (required for profile mode): profile id (`observer`, `deploy-bot`, `rotation-bot`, `trader`)
|
|
168
|
+
- `profileVersion` (optional, default `v1`)
|
|
169
|
+
- `profileOverrides` (optional tighten-only constraints)
|
|
170
|
+
|
|
171
|
+
When `profile` is provided, profile policy becomes the source of truth for:
|
|
172
|
+
|
|
173
|
+
- `permissions`
|
|
174
|
+
- `credentialAccess`
|
|
175
|
+
- `ttl`
|
|
176
|
+
|
|
177
|
+
Response metadata includes:
|
|
178
|
+
|
|
179
|
+
- `profile`
|
|
180
|
+
- `effectivePolicyHash`
|
|
181
|
+
- `overrideDelta`
|
|
182
|
+
- `warnings`
|
|
183
|
+
|
|
184
|
+
#### Override constraints (fail-closed)
|
|
185
|
+
|
|
186
|
+
Profile overrides are **tighten-only**:
|
|
187
|
+
|
|
188
|
+
- `ttlSeconds`: must be positive and <= profile default
|
|
189
|
+
- `maxReads`: must be positive and <= profile default
|
|
190
|
+
- `readScopes` / `writeScopes`: must be subsets of profile scopes (no broadening)
|
|
191
|
+
- `excludeFields`: cannot remove profile-required exclusions (can only add)
|
|
192
|
+
|
|
193
|
+
Invalid profile ids/versions or unsafe overrides return stable profile error codes (for deterministic automation handling).
|
|
194
|
+
|
|
195
|
+
### Mandatory `pubkey` on Token Minting
|
|
196
|
+
|
|
197
|
+
All token mint paths require a valid RSA public key (`pubkey` / `requestedPubkey`):
|
|
198
|
+
|
|
199
|
+
- `POST /unlock`
|
|
200
|
+
- `POST /unlock/:vaultId`
|
|
201
|
+
- `POST /setup`
|
|
202
|
+
- `POST /auth`
|
|
203
|
+
- `POST /actions/token`
|
|
204
|
+
- token-issuing approval flows (`POST /actions`, `POST /actions/:id/resolve`, `POST /auth/request-permissions`)
|
|
205
|
+
|
|
206
|
+
The server normalizes and stores this value on the token as `agentPubkey`. Credential reads (`POST /credentials/:id/read`) are encrypted to that key and never returned in plaintext.
|
|
207
|
+
|
|
208
|
+
### Strategy Operations
|
|
209
|
+
|
|
210
|
+
| Permission | Description | Routes |
|
|
211
|
+
|------------|-------------|--------|
|
|
212
|
+
| `strategy:read` | View strategies and their state | `GET /strategies`, `GET /strategies/:id/config`, `GET /strategies/:id/state`, `GET /strategies/history` |
|
|
213
|
+
| `strategy:manage` | Enable/disable strategies, update config, approve intents/apps | `POST /strategies/:id/toggle`, `PUT /strategies/:id/config`, `POST /strategies/:id/approve`, `POST /strategies/reload`, `POST /apps/:id/approve`, `DELETE /apps/:id/approve` |
|
|
214
|
+
|
|
215
|
+
### App Operations
|
|
216
|
+
|
|
217
|
+
| Permission | Description | Routes |
|
|
218
|
+
|------------|-------------|--------|
|
|
219
|
+
| `app:storage` | Read/write own app's storage and send messages (scoped by agentId). Auto-granted to all app tokens. | `GET /apps/:id/storage`, `GET /apps/:id/storage/:key`, `PUT /apps/:id/storage/:key`, `DELETE /apps/:id/storage/:key`, `POST /apps/:id/message` |
|
|
220
|
+
| `app:storage:all` | Read/write ANY app's storage (cross-app) | Same routes as `app:storage`, bypasses scope check |
|
|
221
|
+
| `app:accesskey` | Read API keys from app storage. Auto-granted to app tokens whose sources use `key` fields. | `GET /apps/:id/apikey/:keyName` |
|
|
222
|
+
|
|
223
|
+
**App token agentId prefixes:** App tokens use `app:<appId>` as their agentId (e.g., `app:tic-tac-toe`). Legacy strategy tokens use `strategy:<appId>`. The storage scope enforcement strips both prefixes when matching against the URL's `:appId` parameter.
|
|
224
|
+
|
|
225
|
+
### Address Book & Bookmark Operations
|
|
226
|
+
|
|
227
|
+
| Permission | Description | Routes |
|
|
228
|
+
|------------|-------------|--------|
|
|
229
|
+
| `addressbook:write` | Create, update, and delete address labels | `POST /address-labels`, `DELETE /address-labels/:id` |
|
|
230
|
+
| `bookmark:write` | Create and delete token bookmarks (watchlist) | `POST /bookmarks`, `DELETE /bookmarks/:id` |
|
|
231
|
+
|
|
232
|
+
### Action Operations
|
|
233
|
+
|
|
234
|
+
| Permission | Description | Routes |
|
|
235
|
+
|------------|-------------|--------|
|
|
236
|
+
| `action:create` | Create human action requests (propose actions for approval), send notifications, and enable `request_human_action` tool in chat apps | `POST /actions` |
|
|
237
|
+
|
|
238
|
+
**Verified summaries:** When an agent creates an action request via `POST /actions`, the server generates a `verifiedSummary` from the actual pre-computed action parameters (endpoint, body, amounts, recipients). This is stored in the action metadata alongside the agent's `summary` text. The dashboard shows the server-generated one-liner and flags discrepancies (e.g., agent says "Swap 0.01 ETH" but the action body contains 10 ETH). Summary text is limited to 500 characters.
|
|
239
|
+
|
|
240
|
+
### Compound Permissions
|
|
241
|
+
|
|
242
|
+
Compound permissions expand to multiple underlying permissions for convenience.
|
|
243
|
+
|
|
244
|
+
| Permission | Description | Expands To |
|
|
245
|
+
|------------|-------------|------------|
|
|
246
|
+
| `trade:all` | All trading permissions | `wallet:list`, `wallet:create:hot`, `wallet:create:temp`, `send:hot`, `send:temp`, `swap`, `fund`, `launch`, `apikey:get`, `strategy:read` |
|
|
247
|
+
| `wallet:write` | All wallet write operations | `wallet:create:hot`, `wallet:create:temp`, `wallet:rename`, `wallet:tx:add`, `wallet:asset:add`, `wallet:asset:remove` |
|
|
248
|
+
|
|
249
|
+
**Usage Example:**
|
|
250
|
+
```typescript
|
|
251
|
+
// Instead of listing all trading permissions:
|
|
252
|
+
permissions: ['wallet:list', 'wallet:create:hot', 'send:hot', 'swap', 'fund', 'apikey:get']
|
|
253
|
+
|
|
254
|
+
// Use the compound permission:
|
|
255
|
+
permissions: ['trade:all']
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Onboarding note:** `trade:all` does NOT include `apikey:set` or `adapter:manage`. Agents helping with first-time setup (configuring API keys, Telegram adapter) should request these explicitly:
|
|
259
|
+
```typescript
|
|
260
|
+
permissions: ['trade:all', 'apikey:set', 'adapter:manage', 'action:create']
|
|
261
|
+
```
|
|
262
|
+
See the [SKILL.md](../skills/aurawallet/SKILL.md) agent reference for the full onboarding guide.
|
|
263
|
+
|
|
264
|
+
### UI/Workspace Operations
|
|
265
|
+
|
|
266
|
+
| Permission | Description | Routes |
|
|
267
|
+
|------------|-------------|--------|
|
|
268
|
+
| `workspace:modify` | Modify dashboard workspaces | WebSocket events (app:added, etc.) |
|
|
269
|
+
|
|
270
|
+
### Admin
|
|
271
|
+
|
|
272
|
+
| Permission | Description | Routes |
|
|
273
|
+
|------------|-------------|--------|
|
|
274
|
+
| `admin:*` | Full access, bypass all checks | All routes |
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Route → Permission Mapping
|
|
279
|
+
|
|
280
|
+
| Route | Method | Permission Required | Notes |
|
|
281
|
+
|-------|--------|---------------------|-------|
|
|
282
|
+
| `/wallets` | GET | *public* | No auth required |
|
|
283
|
+
| `/wallet/:address` | GET | `wallet:list` | Optional auth, agents see only owned |
|
|
284
|
+
| `/wallet/create` | POST | `wallet:create:hot` or `wallet:create:temp` | Based on tier |
|
|
285
|
+
| `/wallet/rename` | POST | `wallet:rename` | + wallet access |
|
|
286
|
+
| `/wallet/:address/export` | POST | `wallet:export` | + wallet access + unlocked |
|
|
287
|
+
| `/wallets/transactions` | GET | `wallet:list` | Optional auth, agents see only owned |
|
|
288
|
+
| `/wallet/:address/transactions` | GET | `wallet:list` | Optional auth for own wallets; no auth for external addresses (on-chain fallback) |
|
|
289
|
+
| `/wallet/:address/transactions` | POST | `wallet:tx:add` | + wallet access |
|
|
290
|
+
| `/wallet/:address/assets` | GET | `wallet:list` | Optional auth, agents see only owned |
|
|
291
|
+
| `/wallet/:address/asset` | POST | `wallet:asset:add` | + wallet access |
|
|
292
|
+
| `/wallet/:address/asset/:id` | DELETE | `wallet:asset:remove` | + wallet access |
|
|
293
|
+
| `/send` | POST | `send:hot` or `send:temp` | Based on wallet tier |
|
|
294
|
+
| `/swap` | POST | `swap` | + wallet access |
|
|
295
|
+
| `/fund` | POST | `fund` | Limit enforced |
|
|
296
|
+
| `/launch` | POST | `launch` | + wallet access |
|
|
297
|
+
| `/launch/collect-fees` | POST | *(any token)* | Permissionless on-chain; wallet access for gas |
|
|
298
|
+
| `/launch/:addr/collect-fees` | POST | *(any token)* | Permissionless on-chain; wallet access for gas |
|
|
299
|
+
| `/auth/connect` | GET | *public* | Get server public key for password encryption |
|
|
300
|
+
| `/auth` | POST | *public* | Request token (`pubkey` required) |
|
|
301
|
+
| `/auth/:id` | GET | *public* | Poll for token |
|
|
302
|
+
| `/auth/validate` | POST | *any valid token* | Validate token |
|
|
303
|
+
| `/apikeys` | GET | `apikey:get` or `trade:all` | List all API keys |
|
|
304
|
+
| `/apikeys` | POST | `apikey:set` | Create/update API key |
|
|
305
|
+
| `/apikeys/validate` | POST | `apikey:set` | Validate API key against external service |
|
|
306
|
+
| `/apikeys/:id` | DELETE | `apikey:set` | Delete API key |
|
|
307
|
+
| `/unlock` | GET | *public* | Self-contained HTML unlock page (browser-based) |
|
|
308
|
+
| `/unlock` | POST | *public* | Unlock primary vault and mint admin token (`pubkey` required) |
|
|
309
|
+
| `/unlock/:vaultId` | POST | *public* | Unlock specific vault and mint admin token (`pubkey` required) |
|
|
310
|
+
| `/lock` | POST | `admin:*` | Locks ALL vaults. Admin only |
|
|
311
|
+
| `/lock/:vaultId` | POST | `admin:*` | Lock a specific vault. Admin only |
|
|
312
|
+
| `/vaults/credential` | GET | `admin:*` | List credential vaults |
|
|
313
|
+
| `/vaults/credential` | POST | `admin:*` | Create credential vault |
|
|
314
|
+
| `/vaults/credential/:id/lock` | POST | `admin:*` | Lock credential vault |
|
|
315
|
+
| `/vaults/credential/:id` | DELETE | `admin:*` | Delete credential vault + credentials |
|
|
316
|
+
| `/credentials` | GET | `secret:read` or `admin:*` | List credential metadata (scope filtered) |
|
|
317
|
+
| `/credentials` | POST | `secret:write` or `admin:*` | Create credential |
|
|
318
|
+
| `/credentials/:id` | GET | `secret:read` or `admin:*` | Get credential metadata |
|
|
319
|
+
| `/credentials/:id` | PUT | `secret:write` or `admin:*` | Update credential |
|
|
320
|
+
| `/credentials/:id` | DELETE | `secret:write` or `admin:*` | Delete credential |
|
|
321
|
+
| `/credentials/:id/read` | POST | `secret:read` or `admin:*` | Read credential (encrypted to `agentPubkey`) |
|
|
322
|
+
| `/setup/vault` | POST | `admin:*` | Create additional vault. Requires unlocked primary |
|
|
323
|
+
| `/setup/vault/import` | POST | `admin:*` | Import vault from seed. Requires unlocked primary |
|
|
324
|
+
| `/setup/vaults` | GET | *public* | List all vaults and their status |
|
|
325
|
+
| `/export-seed` | GET/POST | `admin:*` | Export seed phrase. Optional `vaultId` param |
|
|
326
|
+
| `/actions` | POST | `action:create` | Create human action request |
|
|
327
|
+
| `/actions/token` | POST | `admin:*` | Direct token creation (`pubkey` required) |
|
|
328
|
+
| `/actions/:id/resolve` | POST | `admin:*` | Approve/reject pending action |
|
|
329
|
+
| `/actions/tokens` | GET | `admin:*` | List all tokens |
|
|
330
|
+
| `/actions/tokens/revoke` | POST | `admin:*` or own token | Revoke a token |
|
|
331
|
+
| `/nuke` | POST | `admin:*` | Admin only |
|
|
332
|
+
| `/defaults` | GET | `admin:*` | List all system defaults |
|
|
333
|
+
| `/defaults/:key` | PATCH | `admin:*` | Update a system default |
|
|
334
|
+
| `/defaults/reset` | POST | `admin:*` | Reset system default(s) to seed values |
|
|
335
|
+
| `/ai/status` | GET | `admin:*` | AI provider status and availability |
|
|
336
|
+
| `/adapters` | GET | `adapter:manage` | List configured adapters |
|
|
337
|
+
| `/adapters` | POST | `adapter:manage` | Add/update adapter config |
|
|
338
|
+
| `/adapters/:type` | DELETE | `adapter:manage` | Remove adapter config |
|
|
339
|
+
| `/adapters/test` | POST | `adapter:manage` | Send test message through adapter |
|
|
340
|
+
| `/adapters/restart` | POST | `adapter:manage` | Restart approval router |
|
|
341
|
+
| `/address-labels` | GET | *any token or admin* | List all address labels |
|
|
342
|
+
| `/address-labels` | POST | `addressbook:write` | Create/update address label |
|
|
343
|
+
| `/address-labels/:id` | DELETE | `addressbook:write` | Delete address label |
|
|
344
|
+
| `/bookmarks` | GET | *any token or admin* | List bookmarked tokens |
|
|
345
|
+
| `/bookmarks` | POST | `bookmark:write` | Create token bookmark |
|
|
346
|
+
| `/bookmarks/:id` | DELETE | `bookmark:write` | Delete bookmark |
|
|
347
|
+
| `/health` | GET | *public* | No auth required |
|
|
348
|
+
| `/price/:address` | GET | *public* | Token price lookup |
|
|
349
|
+
| `/token/search` | GET | *public* | Search tokens by ticker/name |
|
|
350
|
+
| `/token/safety/:address` | GET | *public* | Token safety report (GoPlusLabs) |
|
|
351
|
+
| `/token/holders/:address` | GET | *public* | Top holders for a token |
|
|
352
|
+
| `/token/:tokenAddress/balance/:walletAddress` | GET | *public* | On-chain token balance for any address |
|
|
353
|
+
| `/batch` | POST | *public* | Batch multiple API calls with dependency chaining (auth per-sub-request) |
|
|
354
|
+
| `/strategies` | GET | `strategy:read` | List all strategies |
|
|
355
|
+
| `/strategies/:id/toggle` | POST | `strategy:manage` | Enable/disable strategy |
|
|
356
|
+
| `/strategies/:id/config` | GET | `strategy:read` | Get effective config |
|
|
357
|
+
| `/strategies/:id/config` | PUT | `strategy:manage` | Update config overrides |
|
|
358
|
+
| `/strategies/:id/approve` | POST | `strategy:manage` | Approve/reject intents |
|
|
359
|
+
| `/strategies/:id/state` | GET | `strategy:read` | Get strategy state (debug) |
|
|
360
|
+
| `/strategies/history` | GET | `strategy:read` | Strategy action history |
|
|
361
|
+
| `/strategies/reload` | POST | `strategy:manage` | Hot-reload from disk |
|
|
362
|
+
| `/apps/:id/storage` | GET | `app:storage` | List all storage keys |
|
|
363
|
+
| `/apps/:id/storage/:key` | GET | `app:storage` | Get storage value |
|
|
364
|
+
| `/apps/:id/storage/:key` | PUT | `app:storage` | Set storage value |
|
|
365
|
+
| `/apps/:id/storage/:key` | DELETE | `app:storage` | Delete storage key |
|
|
366
|
+
| `/apps/:id/apikey/:keyName` | GET | `app:accesskey` | Get API key from app storage |
|
|
367
|
+
| `/apps/:id/message` | POST | `app:storage` | Send message to app AI (scoped) |
|
|
368
|
+
| `/apps/:id/reload` | POST | `admin:*` | Hot-reload app token after install |
|
|
369
|
+
| `/apps/:id/approve` | POST | `strategy:manage` | Approve app permissions |
|
|
370
|
+
| `/apps/:id/approve` | DELETE | `strategy:manage` | Revoke app approval |
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Token Lifecycle
|
|
374
|
+
|
|
375
|
+
```
|
|
376
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
377
|
+
│ 1. Agent requests token │
|
|
378
|
+
│ POST /auth { agentId, permissions, limits, ttl, pubkey } │
|
|
379
|
+
│ → Returns requestId + secret │
|
|
380
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
381
|
+
│ 2. Human approves via UI or API │
|
|
382
|
+
│ POST /actions/:id/resolve { approved: true } │
|
|
383
|
+
│ → Token signed with SIGNING_KEY │
|
|
384
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
385
|
+
│ 3. Agent polls for token │
|
|
386
|
+
│ GET /auth/:requestId?secret=XXX │
|
|
387
|
+
│ → Returns signed token │
|
|
388
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
389
|
+
│ 4. Agent uses token │
|
|
390
|
+
│ Authorization: Bearer <token> │
|
|
391
|
+
│ → Validated against SIGNING_KEY │
|
|
392
|
+
│ → Spending tracked in memory │
|
|
393
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
394
|
+
│ 5. Agent requests permission upgrade (optional) │
|
|
395
|
+
│ POST /auth/request-permissions { requestedPermissions, requestedPubkey, ... } │
|
|
396
|
+
│ → Creates permission_update pending request │
|
|
397
|
+
│ → Human approves → poll for new token (same flow as step 3) │
|
|
398
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
399
|
+
│ 6. Token invalidation │
|
|
400
|
+
│ - Server restart (new SIGNING_KEY) - ALL tokens invalid │
|
|
401
|
+
│ - Human revokes: POST /actions/tokens/revoke │
|
|
402
|
+
│ - Token expires (exp timestamp) │
|
|
403
|
+
│ NOTE: Locking wallet does NOT invalidate tokens │
|
|
404
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## External Approval Channels
|
|
410
|
+
|
|
411
|
+
In addition to the Dashboard UI and CLI terminal, approvals can flow through external channels (Telegram, Discord, webhooks) via the adapter system. All channels converge on the same `POST /actions/:id/resolve` endpoint.
|
|
412
|
+
|
|
413
|
+
See [docs/ADAPTERS.md](./ADAPTERS.md) for configuration, built-in adapters, and how to build custom adapters.
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## Wallet Access Model
|
|
418
|
+
|
|
419
|
+
Tokens can access wallets they own OR wallets explicitly granted via `walletAccess`:
|
|
420
|
+
|
|
421
|
+
```typescript
|
|
422
|
+
// Token can access wallet if:
|
|
423
|
+
// 1. Token created the wallet (tokenHash matches), OR
|
|
424
|
+
// 2. Wallet address is in token's walletAccess array
|
|
425
|
+
|
|
426
|
+
function tokenCanAccessWallet(tokenHash, walletAccess, address): boolean
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
| Action | Who Can Do It |
|
|
430
|
+
|--------|---------------|
|
|
431
|
+
| Create hot wallet | Agent with `wallet:create:hot` permission |
|
|
432
|
+
| Send from wallet | Token that owns it OR has it in `walletAccess` |
|
|
433
|
+
| Export private key | Token owner OR admin with unlocked wallet |
|
|
434
|
+
| List wallets | Token sees owned wallets, admin sees all |
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## Spending Limits
|
|
439
|
+
|
|
440
|
+
Limits are only enforced on `/fund` (cold→hot transfers):
|
|
441
|
+
|
|
442
|
+
```typescript
|
|
443
|
+
// Token has embedded limits
|
|
444
|
+
{
|
|
445
|
+
limits: {
|
|
446
|
+
fund: 1.0, // Max 1 ETH from cold wallet
|
|
447
|
+
send: null, // No limit on sends (optional)
|
|
448
|
+
swap: null // No limit on swaps (optional)
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// Spending tracked in memory per token
|
|
453
|
+
sessions.get(tokenHash) = {
|
|
454
|
+
token: AgentTokenPayload,
|
|
455
|
+
spent: 0,
|
|
456
|
+
spentByType: {
|
|
457
|
+
fund: 0.5, // Already used 0.5 of 1.0 ETH fund limit
|
|
458
|
+
send: 0,
|
|
459
|
+
swap: 0
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
**Key Points:**
|
|
465
|
+
- `/fund` limit is the primary control (cold wallet access)
|
|
466
|
+
- `/send` has NO limit by default - agents spend freely from their hot wallets
|
|
467
|
+
- Limits are tamper-proof (embedded in HMAC-signed token)
|
|
468
|
+
- Server restart resets all spending (new sessions Map)
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## API Keys
|
|
473
|
+
|
|
474
|
+
AuraWallet stores API keys as encrypted credential-vault entries (`type: "apikey"`). Legacy `ApiKey` DB rows are migrated/synced for compatibility, and `/apikeys` is served through the credential vault path.
|
|
475
|
+
|
|
476
|
+
### Get All API Keys
|
|
477
|
+
|
|
478
|
+
```bash
|
|
479
|
+
curl http://localhost:4242/apikeys \
|
|
480
|
+
-H "Authorization: Bearer <token>"
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
Returns:
|
|
484
|
+
```json
|
|
485
|
+
{
|
|
486
|
+
"success": true,
|
|
487
|
+
"apiKeys": [
|
|
488
|
+
{
|
|
489
|
+
"id": "...",
|
|
490
|
+
"service": "alchemy",
|
|
491
|
+
"name": "default",
|
|
492
|
+
"keyMasked": "abc1****3xyz",
|
|
493
|
+
"createdAt": "2026-02-03T..."
|
|
494
|
+
}
|
|
495
|
+
]
|
|
496
|
+
}
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### Create/Update API Key
|
|
500
|
+
|
|
501
|
+
```bash
|
|
502
|
+
curl -X POST http://localhost:4242/apikeys \
|
|
503
|
+
-H "Authorization: Bearer <token>" \
|
|
504
|
+
-H "Content-Type: application/json" \
|
|
505
|
+
-d '{"service": "alchemy", "name": "default", "key": "your-api-key"}'
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
Requires `apikey:set` permission.
|
|
509
|
+
|
|
510
|
+
### Delete API Key
|
|
511
|
+
|
|
512
|
+
```bash
|
|
513
|
+
curl -X DELETE http://localhost:4242/apikeys/<id> \
|
|
514
|
+
-H "Authorization: Bearer <token>"
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
Requires `apikey:set` permission.
|
|
518
|
+
|
|
519
|
+
### Validate API Key
|
|
520
|
+
|
|
521
|
+
```bash
|
|
522
|
+
curl -X POST http://localhost:4242/apikeys/validate \
|
|
523
|
+
-H "Authorization: Bearer <token>" \
|
|
524
|
+
-H "Content-Type: application/json" \
|
|
525
|
+
-d '{"service": "alchemy", "key": "your-api-key"}'
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
Validates an API key against its external service before saving. Requires `apikey:set` permission.
|
|
529
|
+
|
|
530
|
+
**Supported services:**
|
|
531
|
+
- `alchemy` — Sends `eth_blockNumber` JSON-RPC call. Valid if response contains a block number.
|
|
532
|
+
- `anthropic` — Sends minimal request to Messages API. 200 or 429 (rate-limited) = valid, 401 = invalid.
|
|
533
|
+
- `adapter:telegram` — Calls Telegram Bot API `getMe`. Returns `{ valid: true, info: { botUsername } }` on success.
|
|
534
|
+
|
|
535
|
+
All external calls have a 5-second timeout. Returns `{ valid: false, error: "Validation timed out" }` on timeout.
|
|
536
|
+
|
|
537
|
+
### Test Adapter
|
|
538
|
+
|
|
539
|
+
```bash
|
|
540
|
+
curl -X POST http://localhost:4242/adapters/test \
|
|
541
|
+
-H "Authorization: Bearer <token>" \
|
|
542
|
+
-H "Content-Type: application/json" \
|
|
543
|
+
-d '{"type": "telegram"}'
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
Sends a test message through a configured adapter. Requires `adapter:manage` permission.
|
|
547
|
+
|
|
548
|
+
**Supported types:**
|
|
549
|
+
- `telegram` — Reads bot token and chat ID from DB, sends a test message via Telegram Bot API. Returns 404 if token or chat ID not configured.
|
|
550
|
+
- `webhook` — Reads webhook URL from adapter config, POSTs `{ type: "test", data: {}, timestamp }`. Returns 404 if URL not configured.
|
|
551
|
+
|
|
552
|
+
**Response:**
|
|
553
|
+
```json
|
|
554
|
+
{ "success": true }
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
---
|
|
558
|
+
|
|
559
|
+
## Authentication Header
|
|
560
|
+
|
|
561
|
+
```http
|
|
562
|
+
Authorization: Bearer <token>
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
Example:
|
|
566
|
+
```bash
|
|
567
|
+
curl http://localhost:4242/wallets \
|
|
568
|
+
-H "Authorization: Bearer eyJhZ2VudElkIjoibXktYm90IiwicGVybWlzc2..."
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
---
|
|
572
|
+
|
|
573
|
+
## Error Responses
|
|
574
|
+
|
|
575
|
+
| Error | HTTP Status | Meaning |
|
|
576
|
+
|-------|-------------|---------|
|
|
577
|
+
| `Authentication required` | 401 | No token provided |
|
|
578
|
+
| `Invalid or expired token` | 401 | Bad signature or expired |
|
|
579
|
+
| `Token has been revoked` | 401 | Human revoked the token |
|
|
580
|
+
| `Insufficient permissions` | 403 | Token lacks required permission |
|
|
581
|
+
| `Token does not have access to this wallet` | 403 | Not owner, not in walletAccess |
|
|
582
|
+
| `Admin access required` | 403 | Route requires admin token |
|
|
583
|
+
| `Amount exceeds remaining spending limit` | 403 | Fund limit exceeded |
|
|
584
|
+
| `Cold wallet must be unlocked` | 401 | Need human to unlock first |
|
|
585
|
+
|
|
586
|
+
---
|
|
587
|
+
|
|
588
|
+
## Encrypted Password Transport
|
|
589
|
+
|
|
590
|
+
Passwords for `/unlock` and `/setup` are encrypted before transmission using RSA-OAEP. This protects against local interception by malware or other processes.
|
|
591
|
+
|
|
592
|
+
### Flow
|
|
593
|
+
|
|
594
|
+
```
|
|
595
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
596
|
+
│ Server startup │
|
|
597
|
+
│ → Generate ephemeral RSA keypair (private key in memory) │
|
|
598
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
599
|
+
│ Frontend unlock/setup │
|
|
600
|
+
│ 1. GET /auth/connect → { publicKey: "-----BEGIN PUBLIC..." } │
|
|
601
|
+
│ 2. Encrypt password with RSA-OAEP using Web Crypto API │
|
|
602
|
+
│ 3. Generate caller RSA keypair (local) │
|
|
603
|
+
│ 4. POST /unlock → { encrypted: "base64...", pubkey: "..." } │
|
|
604
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
605
|
+
│ Server │
|
|
606
|
+
│ 1. Decrypt with private key → plaintext password │
|
|
607
|
+
│ 2. Normal unlock/setup flow │
|
|
608
|
+
│ 3. Return result (admin token on unlock) │
|
|
609
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
610
|
+
│ Server restart │
|
|
611
|
+
│ → New RSA keypair generated │
|
|
612
|
+
│ → Old cached public keys become invalid │
|
|
613
|
+
│ → Frontend auto-refetches on decryption failure │
|
|
614
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
The server also provides a built-in unlock page at `GET /unlock` that handles the encryption flow automatically in the browser — no frontend build required. **This is a fallback for headless environments.** When the dashboard (`http://localhost:4747/app`) is available, prefer directing users there instead.
|
|
618
|
+
|
|
619
|
+
### Security Properties
|
|
620
|
+
|
|
621
|
+
- RSA private key never leaves server memory
|
|
622
|
+
- Keypair regenerates on restart (aligns with existing security model)
|
|
623
|
+
- RSA-OAEP provides semantic security (same plaintext → different ciphertext)
|
|
624
|
+
- Passwords never appear in plaintext over HTTP
|
|
625
|
+
|
|
626
|
+
### Usage (Frontend)
|
|
627
|
+
|
|
628
|
+
```typescript
|
|
629
|
+
import { unlockWallet, setupWallet } from '@/lib/api';
|
|
630
|
+
|
|
631
|
+
// These functions handle encryption automatically
|
|
632
|
+
const result = await unlockWallet(password);
|
|
633
|
+
const result = await setupWallet(password);
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
---
|
|
637
|
+
|
|
638
|
+
## Security Best Practices
|
|
639
|
+
|
|
640
|
+
1. **Never expose ports to internet** - This is a local-only system
|
|
641
|
+
2. **Store secrets securely** - The `secret` from `/auth` is needed to retrieve tokens
|
|
642
|
+
3. **Use minimal permissions** - Request only the permissions you need
|
|
643
|
+
4. **Handle token expiry** - Tokens expire, implement refresh logic
|
|
644
|
+
5. **Expect restarts** - Server restart invalidates all tokens, this is intentional
|
|
645
|
+
|
|
646
|
+
---
|
|
647
|
+
|
|
648
|
+
## Note on Admin Tokens
|
|
649
|
+
|
|
650
|
+
> **IMPORTANT**: 99% of the time you just need an agent token via `POST /auth`. If the wallet is unlocked, agents can request tokens through the normal human-approval flow. You should NOT need an admin token.
|
|
651
|
+
|
|
652
|
+
Admin tokens are returned when unlocking the wallet via `/unlock`. In normal usage, **you should not need to use the admin token directly**. The dashboard UI handles authentication automatically.
|
|
653
|
+
|
|
654
|
+
Admin tokens are intended for:
|
|
655
|
+
- **Emergency access** - Recovering from UI issues or debugging
|
|
656
|
+
- **Headless/automated scenarios** - When running without a human in the loop at all (e.g., CI/CD, scripts)
|
|
657
|
+
- **API exploration** - Testing endpoints directly with curl
|
|
658
|
+
|
|
659
|
+
For regular human-supervised operation:
|
|
660
|
+
1. Just use the dashboard UI - it manages tokens internally
|
|
661
|
+
2. Agents should request tokens via `POST /auth` and wait for human approval
|
|
662
|
+
3. No admin token is needed for normal agent workflows
|
|
663
|
+
|
|
664
|
+
---
|
|
665
|
+
|
|
666
|
+
## Agent Permission Tiers
|
|
667
|
+
|
|
668
|
+
The `agent-chat` app supports two permission tiers that control what the chat agent can do directly vs. what requires human approval.
|
|
669
|
+
|
|
670
|
+
### Tiers
|
|
671
|
+
|
|
672
|
+
| Tier | Permissions | Behavior |
|
|
673
|
+
|------|-------------|----------|
|
|
674
|
+
| **admin** (default) | `admin:*` | Agent can call `/send`, `/swap`, `/fund`, etc. directly. No approval popups. |
|
|
675
|
+
| **restricted** | `wallet:list`, `action:create` | Agent can only view wallets and propose actions via `request_human_action`. All trades require human approval. |
|
|
676
|
+
|
|
677
|
+
### Configuration
|
|
678
|
+
|
|
679
|
+
The tier is stored as the system default `permissions.agent_tier`. It can be set:
|
|
680
|
+
|
|
681
|
+
- **Dashboard Settings** → `DEFAULT_AGENT` section → Permission Tier toggle
|
|
682
|
+
- **Setup Wizard** → AI Agent step → Permission Level toggle
|
|
683
|
+
- **API**: `PATCH /defaults/permissions.agent_tier` with `{ "value": "admin" | "restricted" }`
|
|
684
|
+
|
|
685
|
+
### How It Works
|
|
686
|
+
|
|
687
|
+
1. When `createAppToken('agent-chat')` runs, it checks `permissions.agent_tier`
|
|
688
|
+
2. If `admin` → the token gets `['admin:*']` permissions (full access)
|
|
689
|
+
3. If `restricted` → the token keeps the app's declared permissions (`wallet:list`, `action:create`)
|
|
690
|
+
4. Only the `agent-chat` app is affected — all other apps keep their own permissions
|
|
691
|
+
|
|
692
|
+
### Token Refresh on Tier Change
|
|
693
|
+
|
|
694
|
+
When `permissions.agent_tier` changes (via `PATCH /defaults`), the system automatically:
|
|
695
|
+
1. Revokes the existing `agent-chat` app token
|
|
696
|
+
2. Creates a new token with the updated permissions
|
|
697
|
+
|
|
698
|
+
This happens via an `onDefaultChanged` listener, so the change takes effect immediately without server restart.
|