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,328 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Aura Wallet CLI - Headless mode for programmatic wallet control
|
|
4
|
+
*
|
|
5
|
+
* Security Design:
|
|
6
|
+
* - Admin token stored in-process memory only (never touches disk)
|
|
7
|
+
* - Main wallet server hosts Unix socket IPC for local agent connections
|
|
8
|
+
* - Crash = re-auth required (aligns with server restart security model)
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* npm run cli # Interactive password prompt
|
|
12
|
+
* npm run cli --password-stdin # Read password from stdin (CI/automation)
|
|
13
|
+
* npm run cli --auto-approve # Auto-approve all requests (DANGEROUS)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import * as readline from 'readline';
|
|
17
|
+
import { encryptPassword, generateAgentKeypair } from './transport-client';
|
|
18
|
+
import { ApprovalManager } from './approval';
|
|
19
|
+
import * as fs from 'fs';
|
|
20
|
+
import { getErrorMessage } from '../lib/error';
|
|
21
|
+
import { printBanner, printBox, printStatus } from './lib/theme';
|
|
22
|
+
|
|
23
|
+
const SERVER_URL = process.env.WALLET_SERVER_URL || 'http://localhost:4242';
|
|
24
|
+
const LOCK_FILE = `/tmp/aura-cli-${process.getuid?.() ?? 'unknown'}.lock`;
|
|
25
|
+
|
|
26
|
+
// In-process memory only - never persisted
|
|
27
|
+
let adminToken: string | null = null;
|
|
28
|
+
let coldWalletAddress: string | null = null;
|
|
29
|
+
|
|
30
|
+
// Parse command line arguments
|
|
31
|
+
const args = process.argv.slice(2);
|
|
32
|
+
const passwordStdin = args.includes('--password-stdin');
|
|
33
|
+
const autoApprove = args.includes('--auto-approve');
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Check if another CLI instance is running
|
|
37
|
+
*/
|
|
38
|
+
function checkLockFile(): boolean {
|
|
39
|
+
try {
|
|
40
|
+
if (fs.existsSync(LOCK_FILE)) {
|
|
41
|
+
const pid = parseInt(fs.readFileSync(LOCK_FILE, 'utf8'), 10);
|
|
42
|
+
// Check if process is still running
|
|
43
|
+
try {
|
|
44
|
+
process.kill(pid, 0); // Signal 0 tests if process exists
|
|
45
|
+
return true; // Process exists, lock is valid
|
|
46
|
+
} catch {
|
|
47
|
+
// Process doesn't exist, stale lock file
|
|
48
|
+
fs.unlinkSync(LOCK_FILE);
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
} catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Create lock file with our PID
|
|
60
|
+
*/
|
|
61
|
+
function createLockFile(): void {
|
|
62
|
+
fs.writeFileSync(LOCK_FILE, process.pid.toString(), { mode: 0o600 });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Remove lock file on exit
|
|
67
|
+
*/
|
|
68
|
+
function removeLockFile(): void {
|
|
69
|
+
try {
|
|
70
|
+
if (fs.existsSync(LOCK_FILE)) {
|
|
71
|
+
const pid = parseInt(fs.readFileSync(LOCK_FILE, 'utf8'), 10);
|
|
72
|
+
if (pid === process.pid) {
|
|
73
|
+
fs.unlinkSync(LOCK_FILE);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
} catch {
|
|
77
|
+
// Ignore cleanup errors
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Fetch the server's RSA public key for password encryption
|
|
83
|
+
*/
|
|
84
|
+
async function fetchPublicKey(): Promise<string> {
|
|
85
|
+
const response = await fetch(`${SERVER_URL}/auth/connect`);
|
|
86
|
+
if (!response.ok) {
|
|
87
|
+
throw new Error(`Failed to connect to wallet server: ${response.status}`);
|
|
88
|
+
}
|
|
89
|
+
const data = await response.json() as { publicKey: string };
|
|
90
|
+
return data.publicKey;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Unlock the wallet with encrypted password
|
|
95
|
+
*/
|
|
96
|
+
async function unlockWallet(encryptedPassword: string, pubkey: string): Promise<{ token: string; address: string }> {
|
|
97
|
+
const response = await fetch(`${SERVER_URL}/unlock`, {
|
|
98
|
+
method: 'POST',
|
|
99
|
+
headers: { 'Content-Type': 'application/json' },
|
|
100
|
+
body: JSON.stringify({ encrypted: encryptedPassword, pubkey })
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const data = await response.json() as { success?: boolean; token?: string; address?: string; error?: string };
|
|
104
|
+
|
|
105
|
+
if (!response.ok || !data.success) {
|
|
106
|
+
throw new Error(data.error || 'Failed to unlock wallet');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return { token: data.token!, address: data.address! };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Prompt for password (hidden input)
|
|
114
|
+
*/
|
|
115
|
+
async function promptPassword(): Promise<string> {
|
|
116
|
+
return new Promise((resolve) => {
|
|
117
|
+
const rl = readline.createInterface({
|
|
118
|
+
input: process.stdin,
|
|
119
|
+
output: process.stdout
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Hide input by writing to stderr and using raw mode
|
|
123
|
+
process.stdout.write('Password: ');
|
|
124
|
+
|
|
125
|
+
// For hidden input, we need to handle it manually
|
|
126
|
+
const stdin = process.stdin;
|
|
127
|
+
const wasRaw = stdin.isRaw;
|
|
128
|
+
|
|
129
|
+
if (stdin.isTTY) {
|
|
130
|
+
stdin.setRawMode(true);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
let password = '';
|
|
134
|
+
|
|
135
|
+
const onData = (char: Buffer) => {
|
|
136
|
+
const c = char.toString();
|
|
137
|
+
|
|
138
|
+
if (c === '\n' || c === '\r') {
|
|
139
|
+
// Enter pressed
|
|
140
|
+
stdin.removeListener('data', onData);
|
|
141
|
+
if (stdin.isTTY) {
|
|
142
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
143
|
+
}
|
|
144
|
+
process.stdout.write('\n');
|
|
145
|
+
rl.close();
|
|
146
|
+
resolve(password);
|
|
147
|
+
} else if (c === '\u0003') {
|
|
148
|
+
// Ctrl+C
|
|
149
|
+
process.stdout.write('\n');
|
|
150
|
+
process.exit(1);
|
|
151
|
+
} else if (c === '\u007f' || c === '\b') {
|
|
152
|
+
// Backspace
|
|
153
|
+
if (password.length > 0) {
|
|
154
|
+
password = password.slice(0, -1);
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
password += c;
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
stdin.on('data', onData);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Read password from stdin (for automation)
|
|
167
|
+
*/
|
|
168
|
+
async function readPasswordFromStdin(): Promise<string> {
|
|
169
|
+
return new Promise((resolve, reject) => {
|
|
170
|
+
let data = '';
|
|
171
|
+
|
|
172
|
+
process.stdin.setEncoding('utf8');
|
|
173
|
+
process.stdin.on('data', (chunk) => {
|
|
174
|
+
data += chunk;
|
|
175
|
+
});
|
|
176
|
+
process.stdin.on('end', () => {
|
|
177
|
+
const password = data.trim();
|
|
178
|
+
if (!password) {
|
|
179
|
+
reject(new Error('No password provided on stdin'));
|
|
180
|
+
} else {
|
|
181
|
+
resolve(password);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
process.stdin.on('error', reject);
|
|
185
|
+
|
|
186
|
+
// Set a timeout for stdin read
|
|
187
|
+
setTimeout(() => {
|
|
188
|
+
if (!data) {
|
|
189
|
+
reject(new Error('Timeout waiting for password on stdin'));
|
|
190
|
+
}
|
|
191
|
+
}, 5000);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Get the admin token (for use by other modules)
|
|
197
|
+
*/
|
|
198
|
+
export function getAdminToken(): string | null {
|
|
199
|
+
return adminToken;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Get the cold wallet address
|
|
204
|
+
*/
|
|
205
|
+
export function getColdWalletAddress(): string | null {
|
|
206
|
+
return coldWalletAddress;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Get the server URL
|
|
211
|
+
*/
|
|
212
|
+
export function getServerUrl(): string {
|
|
213
|
+
return SERVER_URL;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Main entry point
|
|
218
|
+
*/
|
|
219
|
+
async function main() {
|
|
220
|
+
printBanner('CLI MODE');
|
|
221
|
+
|
|
222
|
+
// Check for existing instance
|
|
223
|
+
if (checkLockFile()) {
|
|
224
|
+
console.error('ERROR: Another CLI instance is already running.');
|
|
225
|
+
console.error('If this is incorrect, remove the lock file:', LOCK_FILE);
|
|
226
|
+
process.exit(1);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Auto-approve warning
|
|
230
|
+
if (autoApprove) {
|
|
231
|
+
console.log('⚠️ WARNING: --auto-approve is enabled!');
|
|
232
|
+
console.log(' All agent requests will be automatically approved.');
|
|
233
|
+
console.log(' This is DANGEROUS in production environments.\n');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
// 1. Fetch server's public key
|
|
238
|
+
console.log('Connecting to wallet server...');
|
|
239
|
+
const publicKey = await fetchPublicKey();
|
|
240
|
+
console.log('Connected. Server RSA key received.\n');
|
|
241
|
+
|
|
242
|
+
// 2. Get password
|
|
243
|
+
let password: string;
|
|
244
|
+
if (passwordStdin) {
|
|
245
|
+
console.log('Reading password from stdin...');
|
|
246
|
+
password = await readPasswordFromStdin();
|
|
247
|
+
} else {
|
|
248
|
+
password = await promptPassword();
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// 3. Encrypt and unlock
|
|
252
|
+
console.log('Unlocking wallet...');
|
|
253
|
+
const encryptedPassword = encryptPassword(password, publicKey);
|
|
254
|
+
const { publicKey: agentPubkey } = generateAgentKeypair();
|
|
255
|
+
const { token, address } = await unlockWallet(encryptedPassword, agentPubkey);
|
|
256
|
+
|
|
257
|
+
// Clear password from memory
|
|
258
|
+
password = '';
|
|
259
|
+
|
|
260
|
+
// Store token in memory only
|
|
261
|
+
adminToken = token;
|
|
262
|
+
coldWalletAddress = address;
|
|
263
|
+
|
|
264
|
+
console.log(`\n✓ Wallet unlocked successfully`);
|
|
265
|
+
console.log(` Address: ${address}`);
|
|
266
|
+
console.log(` Token: ${token.substring(0, 20)}...`);
|
|
267
|
+
|
|
268
|
+
// Create lock file
|
|
269
|
+
createLockFile();
|
|
270
|
+
|
|
271
|
+
// 4. Start approval manager (WebSocket listener)
|
|
272
|
+
console.log('\nStarting approval listener...');
|
|
273
|
+
const approvalManager = new ApprovalManager({
|
|
274
|
+
serverUrl: SERVER_URL,
|
|
275
|
+
getToken: () => adminToken,
|
|
276
|
+
autoApprove,
|
|
277
|
+
headless: passwordStdin // Skip terminal interface when using stdin
|
|
278
|
+
});
|
|
279
|
+
await approvalManager.start();
|
|
280
|
+
|
|
281
|
+
// 5. Socket broker now runs in the main wallet server process.
|
|
282
|
+
const socketPath = `/tmp/aura-cli-${process.getuid?.() ?? 'unknown'}.sock`;
|
|
283
|
+
|
|
284
|
+
console.log('');
|
|
285
|
+
printBox([
|
|
286
|
+
'CLI Ready — Listening for agent requests',
|
|
287
|
+
'',
|
|
288
|
+
`Socket: ${socketPath}`,
|
|
289
|
+
'Press Ctrl+C to exit',
|
|
290
|
+
]);
|
|
291
|
+
|
|
292
|
+
// Handle graceful shutdown
|
|
293
|
+
const shutdown = async () => {
|
|
294
|
+
console.log('\n\nShutting down...');
|
|
295
|
+
approvalManager.stop();
|
|
296
|
+
removeLockFile();
|
|
297
|
+
|
|
298
|
+
// Clear sensitive data
|
|
299
|
+
adminToken = null;
|
|
300
|
+
coldWalletAddress = null;
|
|
301
|
+
|
|
302
|
+
console.log('Goodbye.');
|
|
303
|
+
process.exit(0);
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
process.on('SIGINT', shutdown);
|
|
307
|
+
process.on('SIGTERM', shutdown);
|
|
308
|
+
process.on('exit', removeLockFile);
|
|
309
|
+
|
|
310
|
+
// Keep process alive
|
|
311
|
+
await new Promise(() => {
|
|
312
|
+
// Never resolves - keeps CLI running
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
} catch (error) {
|
|
316
|
+
const message = getErrorMessage(error);
|
|
317
|
+
console.error(`\nERROR: ${message}`);
|
|
318
|
+
removeLockFile();
|
|
319
|
+
process.exit(1);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Run main
|
|
324
|
+
main().catch((error) => {
|
|
325
|
+
console.error('Fatal error:', error);
|
|
326
|
+
removeLockFile();
|
|
327
|
+
process.exit(1);
|
|
328
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* .aura file parser — shared between env.ts and init.ts
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import {
|
|
7
|
+
type AuraMapping,
|
|
8
|
+
validateEnvVarName,
|
|
9
|
+
} from './credential-resolve';
|
|
10
|
+
|
|
11
|
+
export { type AuraMapping } from './credential-resolve';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Parse a .aura file into an array of env-var → credential mappings.
|
|
15
|
+
*/
|
|
16
|
+
export function parseAuraFile(filePath: string): AuraMapping[] {
|
|
17
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
18
|
+
const mappings: AuraMapping[] = [];
|
|
19
|
+
|
|
20
|
+
for (const rawLine of content.split('\n')) {
|
|
21
|
+
const line = rawLine.trim();
|
|
22
|
+
if (!line || line.startsWith('#')) continue;
|
|
23
|
+
|
|
24
|
+
const eqIdx = line.indexOf('=');
|
|
25
|
+
if (eqIdx === -1) {
|
|
26
|
+
throw new Error(`Invalid line in .aura (missing '='): ${line}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const envVar = line.substring(0, eqIdx).trim();
|
|
30
|
+
const ref = line.substring(eqIdx + 1).trim();
|
|
31
|
+
|
|
32
|
+
if (!envVar || !ref) {
|
|
33
|
+
throw new Error(`Invalid line in .aura: ${line}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Validate env var name (audit finding #6)
|
|
37
|
+
validateEnvVarName(envVar);
|
|
38
|
+
|
|
39
|
+
let vault: string | null = null;
|
|
40
|
+
let credentialName: string;
|
|
41
|
+
let field: string;
|
|
42
|
+
|
|
43
|
+
if (ref.startsWith('@')) {
|
|
44
|
+
const parts = ref.substring(1).split('/');
|
|
45
|
+
if (parts.length < 3) {
|
|
46
|
+
throw new Error(`Invalid vault reference (expected @vault/credential/field): ${ref}`);
|
|
47
|
+
}
|
|
48
|
+
vault = parts[0];
|
|
49
|
+
credentialName = parts[1];
|
|
50
|
+
field = parts.slice(2).join('/');
|
|
51
|
+
} else {
|
|
52
|
+
const parts = ref.split('/');
|
|
53
|
+
if (parts.length < 2) {
|
|
54
|
+
throw new Error(`Invalid reference (expected credential/field): ${ref}`);
|
|
55
|
+
}
|
|
56
|
+
credentialName = parts[0];
|
|
57
|
+
field = parts.slice(1).join('/');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
mappings.push({ envVar, vault, credentialName, field });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return mappings;
|
|
64
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI helper for creating credentials via the server API.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { serverUrl } from './http';
|
|
6
|
+
|
|
7
|
+
interface CreateCredentialOpts {
|
|
8
|
+
token: string;
|
|
9
|
+
vaultId: string;
|
|
10
|
+
name: string;
|
|
11
|
+
type?: string;
|
|
12
|
+
fields: Array<{ key: string; value: string }>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface CreateResult {
|
|
16
|
+
success: boolean;
|
|
17
|
+
credential?: { id: string; name: string };
|
|
18
|
+
error?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Create a credential via POST /credentials.
|
|
23
|
+
* Fields are sent as sensitiveFields (server encrypts them).
|
|
24
|
+
*/
|
|
25
|
+
export async function createCredentialViaApi(opts: CreateCredentialOpts): Promise<CreateResult> {
|
|
26
|
+
const base = serverUrl();
|
|
27
|
+
const body = {
|
|
28
|
+
vaultId: opts.vaultId,
|
|
29
|
+
type: opts.type || 'api',
|
|
30
|
+
name: opts.name,
|
|
31
|
+
sensitiveFields: opts.fields.map(f => ({
|
|
32
|
+
key: f.key,
|
|
33
|
+
value: f.value,
|
|
34
|
+
sensitive: true,
|
|
35
|
+
})),
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const res = await fetch(`${base}/credentials`, {
|
|
39
|
+
method: 'POST',
|
|
40
|
+
headers: {
|
|
41
|
+
'Content-Type': 'application/json',
|
|
42
|
+
'Authorization': `Bearer ${opts.token}`,
|
|
43
|
+
},
|
|
44
|
+
body: JSON.stringify(body),
|
|
45
|
+
signal: AbortSignal.timeout(10000),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const data = await res.json() as CreateResult;
|
|
49
|
+
if (!res.ok) {
|
|
50
|
+
return { success: false, error: data.error || `HTTP ${res.status}` };
|
|
51
|
+
}
|
|
52
|
+
return data;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get the primary vault ID.
|
|
57
|
+
*/
|
|
58
|
+
export async function getPrimaryVaultId(token: string): Promise<string> {
|
|
59
|
+
const base = serverUrl();
|
|
60
|
+
const res = await fetch(`${base}/vaults/credential`, {
|
|
61
|
+
headers: { 'Authorization': `Bearer ${token}` },
|
|
62
|
+
signal: AbortSignal.timeout(5000),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (!res.ok) throw new Error(`Failed to list vaults: HTTP ${res.status}`);
|
|
66
|
+
|
|
67
|
+
const data = await res.json() as { vaults: Array<{ id: string; name: string; isPrimary: boolean }> };
|
|
68
|
+
const primary = data.vaults?.find(v => v.isPrimary);
|
|
69
|
+
if (!primary) {
|
|
70
|
+
if (data.vaults?.length > 0) return data.vaults[0].id;
|
|
71
|
+
throw new Error('No vaults found. Run `aura init` first.');
|
|
72
|
+
}
|
|
73
|
+
return primary.id;
|
|
74
|
+
}
|