auramaxx 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +26 -0
- package/README.md +77 -0
- package/apps/desktop-electron/main.js +428 -0
- package/bin/auramaxx.js +1063 -0
- package/docs/ADAPTERS.md +466 -0
- package/docs/AGENT_SETUP.md +159 -0
- package/docs/API.md +127 -0
- package/docs/APPS.md +199 -0
- package/docs/ARCHITECTURE.md +235 -0
- package/docs/AUTH.md +318 -0
- package/docs/BEST-PRACTICES.md +82 -0
- package/docs/CLI.md +141 -0
- package/docs/DESKTOP_ELECTRON.md +26 -0
- package/docs/DEVELOPING-APPS.md +453 -0
- package/docs/MCP.md +122 -0
- package/docs/PACKAGING_POLICY.md +19 -0
- package/docs/PERMISSION.md +137 -0
- package/docs/PROTOCOL.md +142 -0
- package/docs/README.md +50 -0
- package/docs/SKILLS.md +132 -0
- package/docs/TROUBLESHOOTING.md +376 -0
- package/docs/WORKSPACE.md +673 -0
- package/docs/agent-auth.md +14 -0
- package/docs/api/authentication.md +79 -0
- package/docs/api/secrets/api-keys.md +28 -0
- package/docs/api/secrets/credentials.md +80 -0
- package/docs/api/secrets/sharing.md +48 -0
- package/docs/api/system.md +41 -0
- package/docs/api/wallets/apps-strategies.md +66 -0
- package/docs/api/wallets/core.md +46 -0
- package/docs/api/wallets/data-portfolio.md +42 -0
- package/docs/aura-file.md +48 -0
- package/docs/core-concepts/FEATURES.md +114 -0
- package/docs/credentials.md +120 -0
- package/docs/external/HOW_TO_AURAMAXX/GETTING_SECRETS.md +33 -0
- package/docs/external/HOW_TO_AURAMAXX/README.md +45 -0
- package/docs/external/getting-started.md +10 -0
- package/docs/external/overview.md +19 -0
- package/docs/external/persona-paths.md +7 -0
- package/docs/external/share-secret.md +76 -0
- package/docs/external/why-aura.md +7 -0
- package/docs/security.md +227 -0
- package/docs/templates/RELEASE_NOTES_TEMPLATE.md +22 -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 +28 -0
- package/package.json +167 -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/20260222090000_update_admin_ttl_default/migration.sql +10 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +447 -0
- package/public/logo.webp +0 -0
- package/scripts/add-app.js +245 -0
- package/server/abi/SwapHelper.json +438 -0
- package/server/cli/approval.ts +447 -0
- package/server/cli/commands/actions.ts +474 -0
- package/server/cli/commands/api.ts +220 -0
- package/server/cli/commands/apikey.ts +277 -0
- package/server/cli/commands/app.ts +204 -0
- package/server/cli/commands/auth.ts +464 -0
- package/server/cli/commands/cron.ts +24 -0
- package/server/cli/commands/diary.ts +274 -0
- package/server/cli/commands/doctor.ts +1247 -0
- package/server/cli/commands/env.ts +476 -0
- package/server/cli/commands/experimental.ts +69 -0
- package/server/cli/commands/init.ts +798 -0
- package/server/cli/commands/lock.ts +157 -0
- package/server/cli/commands/mcp.ts +285 -0
- package/server/cli/commands/quickhack.ts +86 -0
- package/server/cli/commands/release-check.ts +231 -0
- package/server/cli/commands/restore.ts +314 -0
- package/server/cli/commands/service.ts +320 -0
- package/server/cli/commands/shell-hook.ts +512 -0
- package/server/cli/commands/skill.ts +216 -0
- package/server/cli/commands/start.ts +139 -0
- package/server/cli/commands/status.ts +59 -0
- package/server/cli/commands/stop.ts +36 -0
- package/server/cli/commands/token.ts +180 -0
- package/server/cli/commands/unlock.ts +50 -0
- package/server/cli/commands/vault.ts +1323 -0
- package/server/cli/commands/wallet.ts +209 -0
- package/server/cli/index.ts +280 -0
- package/server/cli/lib/approval-poll.ts +94 -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 +280 -0
- package/server/cli/lib/dotenv-migrate.ts +116 -0
- package/server/cli/lib/dotenv-parser.ts +146 -0
- package/server/cli/lib/escalation.ts +57 -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/lock-unlock-helper.ts +71 -0
- package/server/cli/lib/process.ts +162 -0
- package/server/cli/lib/prompt.ts +294 -0
- package/server/cli/lib/theme.ts +240 -0
- package/server/cli/socket.ts +579 -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 +420 -0
- package/server/lib/adapters/factory.ts +119 -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 +419 -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 +258 -0
- package/server/lib/app-installer.ts +505 -0
- package/server/lib/app-tokens.ts +247 -0
- package/server/lib/approval-link.ts +27 -0
- package/server/lib/auth.ts +314 -0
- package/server/lib/auto-execute.ts +160 -0
- package/server/lib/batch.ts +242 -0
- package/server/lib/cold.ts +1048 -0
- package/server/lib/config.ts +408 -0
- package/server/lib/credential-access-audit.ts +85 -0
- package/server/lib/credential-access-policy.ts +111 -0
- package/server/lib/credential-health.ts +343 -0
- package/server/lib/credential-import.ts +608 -0
- package/server/lib/credential-scope.ts +102 -0
- package/server/lib/credential-shares.ts +190 -0
- package/server/lib/credential-transport.ts +533 -0
- package/server/lib/credential-vault.ts +77 -0
- package/server/lib/credentials.ts +422 -0
- package/server/lib/crypto.ts +8 -0
- package/server/lib/db.ts +58 -0
- package/server/lib/defaults.ts +386 -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/diary.ts +34 -0
- package/server/lib/dont-ask-again-policy.ts +41 -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 +114 -0
- package/server/lib/error.ts +20 -0
- package/server/lib/events.ts +217 -0
- package/server/lib/feature-flags.ts +93 -0
- package/server/lib/hot.ts +357 -0
- package/server/lib/human-action-summary.ts +80 -0
- package/server/lib/key-fingerprint.ts +28 -0
- package/server/lib/logger.ts +340 -0
- package/server/lib/network.ts +137 -0
- package/server/lib/notifications.ts +230 -0
- package/server/lib/oauth2-refresh.ts +241 -0
- package/server/lib/oursecret.ts +71 -0
- package/server/lib/passkey-credential.ts +360 -0
- package/server/lib/passkey.ts +68 -0
- package/server/lib/permissions.ts +299 -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 +297 -0
- package/server/lib/resolve-action.ts +328 -0
- package/server/lib/resolve.ts +36 -0
- package/server/lib/secret-gist-share.ts +296 -0
- package/server/lib/sessions.ts +634 -0
- package/server/lib/socket-path.ts +56 -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 +159 -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 +237 -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 +84 -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/update-check.ts +35 -0
- package/server/lib/verified-summary.ts +414 -0
- package/server/lib/view-registry.ts +80 -0
- package/server/mcp/profile-policy.ts +30 -0
- package/server/mcp/server.ts +1589 -0
- package/server/mcp/tools.ts +276 -0
- package/server/middleware/auth.ts +119 -0
- package/server/middleware/requestLogger.ts +84 -0
- package/server/routes/actions.ts +539 -0
- package/server/routes/adapters.ts +711 -0
- package/server/routes/addressbook.ts +113 -0
- package/server/routes/ai.ts +34 -0
- package/server/routes/apikeys.ts +343 -0
- package/server/routes/apps.ts +601 -0
- package/server/routes/auth.ts +406 -0
- package/server/routes/backup.ts +404 -0
- package/server/routes/batch.ts +270 -0
- package/server/routes/bookmarks.ts +162 -0
- package/server/routes/credential-shares.ts +380 -0
- package/server/routes/credential-vaults.ts +159 -0
- package/server/routes/credentials.ts +1782 -0
- package/server/routes/dashboard.ts +97 -0
- package/server/routes/defaults.ts +124 -0
- package/server/routes/flags.ts +11 -0
- package/server/routes/fund.ts +225 -0
- package/server/routes/heartbeat.ts +375 -0
- package/server/routes/import.ts +364 -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 +366 -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 +352 -0
- package/server/routes/swap-solana.ts +176 -0
- package/server/routes/swap.ts +356 -0
- package/server/routes/token.ts +247 -0
- package/server/routes/unlock.ts +467 -0
- package/server/routes/views.ts +41 -0
- package/server/routes/wallet-assets.ts +361 -0
- package/server/routes/wallet-transactions.ts +515 -0
- package/server/routes/wallet.ts +709 -0
- package/server/types.ts +146 -0
- package/shared/credential-field-schema.ts +248 -0
- package/skills/auramaxx/HEARTBEAT.md +78 -0
- package/skills/auramaxx/SKILL.md +745 -0
- package/skills/auramaxx/docs/AGENT_SETUP.md +155 -0
- package/skills/auramaxx/docs/API.md +127 -0
- package/skills/auramaxx/docs/AUTH.md +318 -0
- package/skills/auramaxx/docs/CLI.md +130 -0
- package/skills/auramaxx/docs/MCP.md +122 -0
- package/skills/auramaxx/docs/TROUBLESHOOTING.md +357 -0
- package/skills/auramaxx/docs/WORKSPACE.md +673 -0
- package/skills/auramaxx/docs/security.md +227 -0
- package/skills/task-lifecycle/SKILL.md +378 -0
- package/src/app/api/[...doc]/page.tsx +36 -0
- package/src/app/api/agent-requests/route.ts +30 -0
- package/src/app/api/apps/install/route.ts +132 -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/docs/plain/route.ts +74 -0
- package/src/app/api/events/route.ts +92 -0
- package/src/app/api/page.tsx +290 -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 +40 -0
- package/src/app/api/workspace/config/route.ts +121 -0
- package/src/app/api/workspace/import/route.ts +127 -0
- package/src/app/api/workspace/route.ts +116 -0
- package/src/app/app-legacy-do-not-use/page.tsx +2245 -0
- package/src/app/apple-icon.png +0 -0
- package/src/app/approve/[actionId]/page.tsx +409 -0
- package/src/app/docs/DocsPageContent.tsx +269 -0
- package/src/app/docs/[...doc]/page.tsx +41 -0
- package/src/app/docs/page.tsx +38 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +819 -0
- package/src/app/health/page.tsx +5 -0
- package/src/app/hello/page.tsx +102 -0
- package/src/app/icon.png +0 -0
- package/src/app/layout.tsx +39 -0
- package/src/app/page.tsx +1964 -0
- package/src/app/privacy/page.tsx +63 -0
- package/src/app/providers.tsx +87 -0
- package/src/app/share/[token]/page.tsx +295 -0
- package/src/app/terms/page.tsx +80 -0
- package/src/components/ChainSelector.tsx +44 -0
- package/src/components/HumanActionBar.tsx +697 -0
- package/src/components/NotificationDrawer.tsx +387 -0
- package/src/components/PasskeyEnrollmentPrompt.tsx +235 -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 +88 -0
- package/src/components/design-system/ChainIndicator.tsx +65 -0
- package/src/components/design-system/ChainSelector.tsx +147 -0
- package/src/components/design-system/ConfirmationModal.tsx +107 -0
- package/src/components/design-system/ConfirmationPopover.tsx +81 -0
- package/src/components/design-system/DownloadButton.tsx +149 -0
- package/src/components/design-system/Drawer.tsx +133 -0
- package/src/components/design-system/FilterDropdown.tsx +183 -0
- package/src/components/design-system/ItemPicker.tsx +157 -0
- package/src/components/design-system/Modal.tsx +296 -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 +65 -0
- package/src/components/design-system/TyvekCollapsibleSection.tsx +55 -0
- package/src/components/design-system/index.ts +14 -0
- package/src/components/docs/ClientSideMarkdown.tsx +51 -0
- package/src/components/docs/DocsSearchBar.tsx +118 -0
- package/src/components/docs/DocsThemeToggle.tsx +38 -0
- package/src/components/docs/PersistentDocGroup.tsx +91 -0
- package/src/components/docs/ShareUrlButton.tsx +33 -0
- package/src/components/docs/SidebarScrollMemory.tsx +56 -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/CreateViewModal.tsx +88 -0
- package/src/components/layout/LeftRail.tsx +114 -0
- package/src/components/layout/TabBar.tsx +284 -0
- package/src/components/layout/WalletSidebar.tsx +1030 -0
- package/src/components/layout/index.ts +6 -0
- package/src/components/marketing/AuraMaxxSpecOverlay.tsx +653 -0
- package/src/components/marketing/DeviceMorphExperience.tsx +216 -0
- package/src/components/vault/ApiKeysConsole.tsx +1272 -0
- package/src/components/vault/AuditConsole.tsx +600 -0
- package/src/components/vault/CredentialDetail.tsx +625 -0
- package/src/components/vault/CredentialEmpty.tsx +55 -0
- package/src/components/vault/CredentialField.tsx +583 -0
- package/src/components/vault/CredentialForm.tsx +1484 -0
- package/src/components/vault/CredentialList.tsx +265 -0
- package/src/components/vault/CredentialRow.tsx +130 -0
- package/src/components/vault/CredentialShareModal.tsx +273 -0
- package/src/components/vault/CredentialVault.tsx +1662 -0
- package/src/components/vault/CredentialWalletWidget.tsx +103 -0
- package/src/components/vault/DocsConsole.tsx +113 -0
- package/src/components/vault/ImportCredentialsModal.tsx +578 -0
- package/src/components/vault/LargeTypeModal.tsx +88 -0
- package/src/components/vault/PasswordGenerator.tsx +232 -0
- package/src/components/vault/TOTPDisplay.tsx +108 -0
- package/src/components/vault/TotpSetupPanel.tsx +198 -0
- package/src/components/vault/VaultSidebar.tsx +881 -0
- package/src/components/vault/credentialFormName.ts +91 -0
- package/src/components/vault/hooks/useVaultKeyboardShortcuts.ts +69 -0
- package/src/components/vault/types.ts +56 -0
- package/src/context/AuthContext.tsx +365 -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 +4 -0
- package/src/hooks/useAgentActions.ts +552 -0
- package/src/hooks/useBalance.ts +103 -0
- package/src/hooks/useBalances.ts +129 -0
- package/src/hooks/useTheme.ts +156 -0
- package/src/instrumentation.ts +12 -0
- package/src/lib/api-docs.ts +154 -0
- package/src/lib/api.ts +474 -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/credential-field-schema.ts +11 -0
- package/src/lib/crypto.ts +112 -0
- package/src/lib/db.ts +21 -0
- package/src/lib/docs.ts +544 -0
- package/src/lib/events.ts +363 -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/totp-import.ts +57 -0
- package/src/lib/vault-crypto.ts +129 -0
- package/src/lib/view-registry.ts +57 -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 +170 -0
- package/tailwind.config.ts +99 -0
- package/tsconfig.json +42 -0
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* auramaxx actions — Human-action request and token management
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
bootstrapViaAuthRequest,
|
|
7
|
+
bootstrapViaSocket,
|
|
8
|
+
decryptWithPrivateKey,
|
|
9
|
+
generateEphemeralKeypair,
|
|
10
|
+
type ProfileIssuanceSelection,
|
|
11
|
+
} from '../../lib/credential-transport';
|
|
12
|
+
import { getErrorMessage } from '../../lib/error';
|
|
13
|
+
import { waitForAuthDecision } from '../lib/approval-poll';
|
|
14
|
+
import { printHelp } from '../lib/theme';
|
|
15
|
+
import { serverUrl } from '../lib/http';
|
|
16
|
+
|
|
17
|
+
type JsonObject = Record<string, unknown>;
|
|
18
|
+
|
|
19
|
+
interface ParsedPollCommon {
|
|
20
|
+
json: boolean;
|
|
21
|
+
rawToken: boolean;
|
|
22
|
+
noWait: boolean;
|
|
23
|
+
timeoutMs: number;
|
|
24
|
+
intervalMs: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function showHelp(): void {
|
|
28
|
+
printHelp('ACTIONS', 'npx auramaxx actions <subcommand> [options]', [
|
|
29
|
+
{ name: 'create', desc: 'Create action request and optionally poll for approval token' },
|
|
30
|
+
{ name: 'pending', desc: 'List pending human actions' },
|
|
31
|
+
{ name: 'resolve <id>', desc: 'Approve or reject a pending action' },
|
|
32
|
+
{ name: 'tokens', desc: 'List agent tokens (admin)' },
|
|
33
|
+
{ name: 'revoke <tokenHash>', desc: 'Revoke token by hash (or --self)' },
|
|
34
|
+
], [
|
|
35
|
+
'Create options:',
|
|
36
|
+
' --summary <text> Required summary',
|
|
37
|
+
' --permissions <a,b,c> Required permission CSV',
|
|
38
|
+
' --ttl <seconds> Optional token TTL for approved action token',
|
|
39
|
+
' --limit-fund <eth> Optional fund limit override',
|
|
40
|
+
' --limit-send <eth> Optional send limit override',
|
|
41
|
+
' --limit-swap <eth> Optional swap limit override',
|
|
42
|
+
' --wallet-access <a,b,c> Optional wallet access CSV',
|
|
43
|
+
' --credential-read <a,b,c> Optional credential read scope CSV',
|
|
44
|
+
' --credential-write <a,b,c> Optional credential write scope CSV',
|
|
45
|
+
' --exclude-fields <a,b,c> Optional excluded field CSV',
|
|
46
|
+
' --metadata <json> Optional metadata object',
|
|
47
|
+
' --no-wait Do not poll for approval result',
|
|
48
|
+
' --timeout-ms <ms> Poll timeout (default: 120000)',
|
|
49
|
+
' --interval-ms <ms> Poll interval (default: 3000)',
|
|
50
|
+
' --raw-token Print full approved token',
|
|
51
|
+
' --json JSON output',
|
|
52
|
+
'',
|
|
53
|
+
'Auth bootstrap options (when AURA_TOKEN is not set):',
|
|
54
|
+
' --profile <id> /auth fallback profile (default: strict)',
|
|
55
|
+
' --profile-version <v> /auth fallback profile version (default: v1)',
|
|
56
|
+
' --profile-overrides <json> Tighten-only profile override JSON',
|
|
57
|
+
'',
|
|
58
|
+
'Resolve options:',
|
|
59
|
+
' --approve Approve action',
|
|
60
|
+
' --reject Reject action',
|
|
61
|
+
' --wallet-access <a,b,c> Optional wallet access override',
|
|
62
|
+
' --limits <json> Optional limits override object',
|
|
63
|
+
'',
|
|
64
|
+
'Token options:',
|
|
65
|
+
' --token <token> Use this bearer token (default: AURA_TOKEN or socket fallback)',
|
|
66
|
+
' --self Revoke current token (for revoke subcommand)',
|
|
67
|
+
'',
|
|
68
|
+
'Examples:',
|
|
69
|
+
' npx auramaxx actions create --summary "Grant read" --permissions secret:read',
|
|
70
|
+
' npx auramaxx actions pending',
|
|
71
|
+
' npx auramaxx actions resolve act_123 --approve',
|
|
72
|
+
' npx auramaxx actions tokens',
|
|
73
|
+
' npx auramaxx actions revoke tok_abc',
|
|
74
|
+
]);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function getFlagValue(args: string[], flag: string): string | undefined {
|
|
78
|
+
const idx = args.indexOf(flag);
|
|
79
|
+
return idx >= 0 ? args[idx + 1] : undefined;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function parseInteger(args: string[], flag: string, fallback: number): number {
|
|
83
|
+
const raw = getFlagValue(args, flag);
|
|
84
|
+
if (!raw) return fallback;
|
|
85
|
+
const n = Number(raw);
|
|
86
|
+
if (!Number.isFinite(n) || n <= 0) throw new Error(`${flag} must be a positive number`);
|
|
87
|
+
return Math.floor(n);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function parseNumber(args: string[], flag: string): number | undefined {
|
|
91
|
+
const raw = getFlagValue(args, flag);
|
|
92
|
+
if (!raw) return undefined;
|
|
93
|
+
const n = Number(raw);
|
|
94
|
+
if (!Number.isFinite(n) || n < 0) throw new Error(`${flag} must be a non-negative number`);
|
|
95
|
+
return n;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function parseCsv(args: string[], flag: string): string[] | undefined {
|
|
99
|
+
const raw = getFlagValue(args, flag);
|
|
100
|
+
if (!raw) return undefined;
|
|
101
|
+
const out = raw.split(',').map((v) => v.trim()).filter(Boolean);
|
|
102
|
+
return out.length > 0 ? out : undefined;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function parseJsonObject(args: string[], flag: string): JsonObject | undefined {
|
|
106
|
+
const raw = getFlagValue(args, flag);
|
|
107
|
+
if (!raw) return undefined;
|
|
108
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
109
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
110
|
+
throw new Error(`${flag} must be a JSON object`);
|
|
111
|
+
}
|
|
112
|
+
return parsed as JsonObject;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function parsePollCommon(args: string[]): ParsedPollCommon {
|
|
116
|
+
return {
|
|
117
|
+
json: args.includes('--json'),
|
|
118
|
+
rawToken: args.includes('--raw-token'),
|
|
119
|
+
noWait: args.includes('--no-wait'),
|
|
120
|
+
timeoutMs: parseInteger(args, '--timeout-ms', 120_000),
|
|
121
|
+
intervalMs: parseInteger(args, '--interval-ms', 3_000),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function parseProfileSelection(args: string[]): ProfileIssuanceSelection {
|
|
126
|
+
const profile = getFlagValue(args, '--profile');
|
|
127
|
+
const profileVersion = getFlagValue(args, '--profile-version');
|
|
128
|
+
const profileOverrides = parseJsonObject(args, '--profile-overrides');
|
|
129
|
+
return {
|
|
130
|
+
...(profile ? { profile } : {}),
|
|
131
|
+
...(profileVersion ? { profileVersion } : {}),
|
|
132
|
+
...(profileOverrides ? { profileOverrides } : {}),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function resolveBearerToken(args: string[]): Promise<string> {
|
|
137
|
+
const explicit = getFlagValue(args, '--token') || process.env.AURA_TOKEN;
|
|
138
|
+
if (explicit) return explicit;
|
|
139
|
+
|
|
140
|
+
const selection = parseProfileSelection(args);
|
|
141
|
+
const keypair = generateEphemeralKeypair();
|
|
142
|
+
|
|
143
|
+
if (selection.profile) {
|
|
144
|
+
const result = await bootstrapViaAuthRequest(serverUrl(), 'cli-actions', keypair, {
|
|
145
|
+
...selection,
|
|
146
|
+
noWait: true,
|
|
147
|
+
onStatus: (message) => console.error(message),
|
|
148
|
+
});
|
|
149
|
+
if (result.approveUrl) {
|
|
150
|
+
console.error(`Approve at: ${result.approveUrl}`);
|
|
151
|
+
}
|
|
152
|
+
console.error(`After approval, re-run with: AURA_TOKEN=<token> npx auramaxx actions ...`);
|
|
153
|
+
console.error(`Or use: npx auramaxx auth request --profile ${selection.profile} --raw-token`);
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
return await bootstrapViaSocket('cli-actions', keypair);
|
|
159
|
+
} catch (socketErr) {
|
|
160
|
+
return bootstrapViaAuthRequest(serverUrl(), 'cli-actions', keypair, {
|
|
161
|
+
...selection,
|
|
162
|
+
onStatus: (message) => console.error(message),
|
|
163
|
+
}).catch((authErr) => {
|
|
164
|
+
throw new Error(`${getErrorMessage(socketErr)}\n${getErrorMessage(authErr)}`);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function maskToken(token: string): string {
|
|
170
|
+
if (token.length <= 24) return token;
|
|
171
|
+
return `${token.slice(0, 20)}...${token.slice(-4)}`;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async function postJson(path: string, token: string, body?: unknown): Promise<Record<string, unknown>> {
|
|
175
|
+
const res = await fetch(`${serverUrl()}${path}`, {
|
|
176
|
+
method: body !== undefined ? 'POST' : 'GET',
|
|
177
|
+
headers: {
|
|
178
|
+
'Authorization': `Bearer ${token}`,
|
|
179
|
+
'Content-Type': 'application/json',
|
|
180
|
+
},
|
|
181
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
182
|
+
signal: AbortSignal.timeout(12_000),
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
const data = await res.json().catch(() => ({})) as Record<string, unknown>;
|
|
186
|
+
if (!res.ok) {
|
|
187
|
+
throw new Error(String(data.error || `HTTP ${res.status}`));
|
|
188
|
+
}
|
|
189
|
+
return data;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async function cmdCreate(args: string[]): Promise<number> {
|
|
193
|
+
console.error('DEPRECATED: `actions create` is deprecated. Use `npx auramaxx auth request --profile <profile>` instead.');
|
|
194
|
+
console.error(' To include a pre-computed action: --action \'{"endpoint":"/send","method":"POST","body":{...}}\'');
|
|
195
|
+
console.error('');
|
|
196
|
+
const common = parsePollCommon(args);
|
|
197
|
+
const summary = getFlagValue(args, '--summary');
|
|
198
|
+
const permissions = parseCsv(args, '--permissions');
|
|
199
|
+
if (!summary) throw new Error('--summary is required');
|
|
200
|
+
if (!permissions || permissions.length === 0) throw new Error('--permissions is required');
|
|
201
|
+
|
|
202
|
+
const token = await resolveBearerToken(args);
|
|
203
|
+
const keypair = generateEphemeralKeypair();
|
|
204
|
+
|
|
205
|
+
const ttl = parseNumber(args, '--ttl');
|
|
206
|
+
const limitFund = parseNumber(args, '--limit-fund');
|
|
207
|
+
const limitSend = parseNumber(args, '--limit-send');
|
|
208
|
+
const limitSwap = parseNumber(args, '--limit-swap');
|
|
209
|
+
const metadata = parseJsonObject(args, '--metadata');
|
|
210
|
+
const walletAccess = parseCsv(args, '--wallet-access');
|
|
211
|
+
const credentialRead = parseCsv(args, '--credential-read');
|
|
212
|
+
const credentialWrite = parseCsv(args, '--credential-write');
|
|
213
|
+
const excludeFields = parseCsv(args, '--exclude-fields');
|
|
214
|
+
|
|
215
|
+
const limits: Record<string, number> = {};
|
|
216
|
+
if (limitFund !== undefined) limits.fund = limitFund;
|
|
217
|
+
if (limitSend !== undefined) limits.send = limitSend;
|
|
218
|
+
if (limitSwap !== undefined) limits.swap = limitSwap;
|
|
219
|
+
|
|
220
|
+
const credentialAccess: Record<string, unknown> = {};
|
|
221
|
+
if (credentialRead) credentialAccess.read = credentialRead;
|
|
222
|
+
if (credentialWrite) credentialAccess.write = credentialWrite;
|
|
223
|
+
if (excludeFields) credentialAccess.excludeFields = excludeFields;
|
|
224
|
+
|
|
225
|
+
const body: Record<string, unknown> = {
|
|
226
|
+
summary,
|
|
227
|
+
permissions,
|
|
228
|
+
pubkey: keypair.publicKeyPem,
|
|
229
|
+
...(ttl !== undefined ? { ttl } : {}),
|
|
230
|
+
...(Object.keys(limits).length > 0 ? { limits } : {}),
|
|
231
|
+
...(walletAccess ? { walletAccess } : {}),
|
|
232
|
+
...(Object.keys(credentialAccess).length > 0 ? { credentialAccess } : {}),
|
|
233
|
+
...(metadata ? { metadata } : {}),
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const created = await postJson('/actions', token, body) as {
|
|
237
|
+
success?: boolean;
|
|
238
|
+
requestId?: string;
|
|
239
|
+
secret?: string;
|
|
240
|
+
message?: string;
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
if (!created.success || !created.requestId || !created.secret) {
|
|
244
|
+
throw new Error('Action request did not return requestId/secret');
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (common.noWait) {
|
|
248
|
+
if (common.json) {
|
|
249
|
+
console.log(JSON.stringify({
|
|
250
|
+
success: true,
|
|
251
|
+
status: 'pending',
|
|
252
|
+
requestId: created.requestId,
|
|
253
|
+
secret: created.secret,
|
|
254
|
+
}, null, 2));
|
|
255
|
+
} else {
|
|
256
|
+
console.log(`Action request created.`);
|
|
257
|
+
console.log(` requestId: ${created.requestId}`);
|
|
258
|
+
console.log(` secret: ${created.secret}`);
|
|
259
|
+
console.log('Use `npx auramaxx auth poll <requestId> --secret <secret>` to continue.');
|
|
260
|
+
}
|
|
261
|
+
return 0;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
console.log(`Action request created (${created.requestId}). Waiting for approval...`);
|
|
265
|
+
|
|
266
|
+
const { response, attempts, elapsedMs } = await waitForAuthDecision(
|
|
267
|
+
serverUrl(),
|
|
268
|
+
created.requestId,
|
|
269
|
+
created.secret,
|
|
270
|
+
{
|
|
271
|
+
timeoutMs: common.timeoutMs,
|
|
272
|
+
intervalMs: common.intervalMs,
|
|
273
|
+
onPending: ({ attempt }) => {
|
|
274
|
+
if (attempt === 1 || attempt % 5 === 0) {
|
|
275
|
+
console.log(' pending...');
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
if (response.status === 'rejected') {
|
|
282
|
+
if (common.json) {
|
|
283
|
+
console.log(JSON.stringify({
|
|
284
|
+
success: true,
|
|
285
|
+
status: 'rejected',
|
|
286
|
+
requestId: created.requestId,
|
|
287
|
+
attempts,
|
|
288
|
+
elapsedMs,
|
|
289
|
+
}, null, 2));
|
|
290
|
+
} else {
|
|
291
|
+
console.log('Action request was rejected.');
|
|
292
|
+
}
|
|
293
|
+
return 1;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (!response.encryptedToken) {
|
|
297
|
+
throw new Error('Approved action response missing encryptedToken');
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const approvedToken = decryptWithPrivateKey(response.encryptedToken, keypair.privateKeyPem);
|
|
301
|
+
|
|
302
|
+
if (common.json) {
|
|
303
|
+
console.log(JSON.stringify({
|
|
304
|
+
success: true,
|
|
305
|
+
status: 'approved',
|
|
306
|
+
requestId: created.requestId,
|
|
307
|
+
attempts,
|
|
308
|
+
elapsedMs,
|
|
309
|
+
token: common.rawToken ? approvedToken : undefined,
|
|
310
|
+
tokenPreview: maskToken(approvedToken),
|
|
311
|
+
}, null, 2));
|
|
312
|
+
} else {
|
|
313
|
+
console.log('Approved.');
|
|
314
|
+
if (common.rawToken) {
|
|
315
|
+
console.log(` token: ${approvedToken}`);
|
|
316
|
+
} else {
|
|
317
|
+
console.log(` token: ${maskToken(approvedToken)}`);
|
|
318
|
+
console.log(' (use --raw-token to print full token)');
|
|
319
|
+
}
|
|
320
|
+
console.log(` export AURA_TOKEN='${approvedToken}'`);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return 0;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
async function cmdPending(args: string[]): Promise<number> {
|
|
327
|
+
const token = await resolveBearerToken(args);
|
|
328
|
+
const json = args.includes('--json');
|
|
329
|
+
const data = await postJson('/actions/pending', token);
|
|
330
|
+
|
|
331
|
+
if (json) {
|
|
332
|
+
console.log(JSON.stringify(data, null, 2));
|
|
333
|
+
return 0;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const actions = Array.isArray((data as { actions?: unknown[] }).actions)
|
|
337
|
+
? (data as { actions: Array<{ id: string; type: string; status: string; metadata?: string }> }).actions
|
|
338
|
+
: [];
|
|
339
|
+
|
|
340
|
+
if (actions.length === 0) {
|
|
341
|
+
console.log('No pending actions.');
|
|
342
|
+
return 0;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
for (const action of actions) {
|
|
346
|
+
console.log(`${action.id} type=${action.type} status=${action.status}`);
|
|
347
|
+
}
|
|
348
|
+
return 0;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
async function cmdResolve(args: string[]): Promise<number> {
|
|
352
|
+
const actionId = args[0];
|
|
353
|
+
if (!actionId) throw new Error('Usage: npx auramaxx actions resolve <id> --approve|--reject');
|
|
354
|
+
|
|
355
|
+
const approve = args.includes('--approve');
|
|
356
|
+
const reject = args.includes('--reject');
|
|
357
|
+
if (approve === reject) {
|
|
358
|
+
throw new Error('Specify exactly one of --approve or --reject');
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const token = await resolveBearerToken(args);
|
|
362
|
+
const walletAccess = parseCsv(args, '--wallet-access');
|
|
363
|
+
const limits = parseJsonObject(args, '--limits');
|
|
364
|
+
const json = args.includes('--json');
|
|
365
|
+
|
|
366
|
+
const data = await postJson(`/actions/${encodeURIComponent(actionId)}/resolve`, token, {
|
|
367
|
+
approved: approve,
|
|
368
|
+
...(walletAccess ? { walletAccess } : {}),
|
|
369
|
+
...(limits ? { limits } : {}),
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
if (json) {
|
|
373
|
+
console.log(JSON.stringify(data, null, 2));
|
|
374
|
+
} else {
|
|
375
|
+
console.log(`Resolved ${actionId}: ${approve ? 'approved' : 'rejected'}`);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return 0;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
async function cmdTokens(args: string[]): Promise<number> {
|
|
382
|
+
const token = await resolveBearerToken(args);
|
|
383
|
+
const json = args.includes('--json');
|
|
384
|
+
const data = await postJson('/actions/tokens', token);
|
|
385
|
+
|
|
386
|
+
if (json) {
|
|
387
|
+
console.log(JSON.stringify(data, null, 2));
|
|
388
|
+
return 0;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const total = Number((data as { total?: unknown }).total || 0);
|
|
392
|
+
const tokens = (data as { tokens?: Record<string, unknown[]> }).tokens || {};
|
|
393
|
+
const active = Array.isArray(tokens.active) ? tokens.active.length : 0;
|
|
394
|
+
const inactive = Array.isArray(tokens.inactive) ? tokens.inactive.length : 0;
|
|
395
|
+
const expired = Array.isArray(tokens.expired) ? tokens.expired.length : 0;
|
|
396
|
+
const revoked = Array.isArray(tokens.revoked) ? tokens.revoked.length : 0;
|
|
397
|
+
const depleted = Array.isArray(tokens.depleted) ? tokens.depleted.length : 0;
|
|
398
|
+
|
|
399
|
+
console.log(`total=${total}`);
|
|
400
|
+
console.log(`active=${active}`);
|
|
401
|
+
console.log(`inactive=${inactive}`);
|
|
402
|
+
console.log(`expired=${expired}`);
|
|
403
|
+
console.log(`revoked=${revoked}`);
|
|
404
|
+
console.log(`depleted=${depleted}`);
|
|
405
|
+
return 0;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
async function cmdRevoke(args: string[]): Promise<number> {
|
|
409
|
+
const token = await resolveBearerToken(args);
|
|
410
|
+
const json = args.includes('--json');
|
|
411
|
+
const self = args.includes('--self');
|
|
412
|
+
const tokenHash = self ? undefined : args[0];
|
|
413
|
+
|
|
414
|
+
if (!self && !tokenHash) {
|
|
415
|
+
throw new Error('Usage: npx auramaxx actions revoke <tokenHash> (or --self)');
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const body = self ? {} : { tokenHash };
|
|
419
|
+
const data = await postJson('/actions/tokens/revoke', token, body);
|
|
420
|
+
|
|
421
|
+
if (json) {
|
|
422
|
+
console.log(JSON.stringify(data, null, 2));
|
|
423
|
+
} else {
|
|
424
|
+
console.log(String((data as { message?: unknown }).message || 'Token revoke attempted.'));
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return (data as { success?: boolean }).success === false ? 1 : 0;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
async function main(): Promise<void> {
|
|
431
|
+
const args = process.argv.slice(2);
|
|
432
|
+
const subcommand = args[0];
|
|
433
|
+
|
|
434
|
+
if (!subcommand || subcommand === '--help' || subcommand === '-h') {
|
|
435
|
+
showHelp();
|
|
436
|
+
process.exit(0);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
try {
|
|
440
|
+
let exitCode = 0;
|
|
441
|
+
switch (subcommand) {
|
|
442
|
+
case 'create':
|
|
443
|
+
exitCode = await cmdCreate(args.slice(1));
|
|
444
|
+
break;
|
|
445
|
+
case 'pending':
|
|
446
|
+
case 'list':
|
|
447
|
+
exitCode = await cmdPending(args.slice(1));
|
|
448
|
+
break;
|
|
449
|
+
case 'resolve':
|
|
450
|
+
exitCode = await cmdResolve(args.slice(1));
|
|
451
|
+
break;
|
|
452
|
+
case 'tokens':
|
|
453
|
+
exitCode = await cmdTokens(args.slice(1));
|
|
454
|
+
break;
|
|
455
|
+
case 'revoke':
|
|
456
|
+
exitCode = await cmdRevoke(args.slice(1));
|
|
457
|
+
break;
|
|
458
|
+
default:
|
|
459
|
+
throw new Error(`Unknown actions subcommand: ${subcommand}`);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
process.exit(exitCode);
|
|
463
|
+
} catch (error) {
|
|
464
|
+
console.error(`Actions command failed: ${getErrorMessage(error)}`);
|
|
465
|
+
process.exit(1);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
470
|
+
main().catch((error) => {
|
|
471
|
+
console.error(`Actions command failed: ${getErrorMessage(error)}`);
|
|
472
|
+
process.exit(1);
|
|
473
|
+
});
|
|
474
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* auramaxx api — Generic wallet API caller from CLI
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* npx auramaxx api GET /health
|
|
6
|
+
* npx auramaxx api POST /auth --body '{"agentId":"cli-api","profile":"dev","profileVersion":"v1","pubkey":"..."}' --no-auth
|
|
7
|
+
* npx auramaxx api POST /credentials --body '{"name":"X","type":"note","fields":[{"key":"content","value":"hello"}]}'
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
bootstrapViaAuthRequest,
|
|
12
|
+
bootstrapViaSocket,
|
|
13
|
+
generateEphemeralKeypair,
|
|
14
|
+
type ProfileIssuanceSelection,
|
|
15
|
+
} from '../../lib/credential-transport';
|
|
16
|
+
import { getErrorMessage } from '../../lib/error';
|
|
17
|
+
import { handlePermissionDenied } from '../lib/escalation';
|
|
18
|
+
import { maybeHandleLockError } from '../lib/lock-unlock-helper';
|
|
19
|
+
import { serverUrl } from '../lib/http';
|
|
20
|
+
import { printHelp } from '../lib/theme';
|
|
21
|
+
|
|
22
|
+
interface ApiCliArgs {
|
|
23
|
+
method: string;
|
|
24
|
+
endpoint: string;
|
|
25
|
+
bodyRaw?: string;
|
|
26
|
+
noAuth: boolean;
|
|
27
|
+
profile?: string;
|
|
28
|
+
profileVersion?: string;
|
|
29
|
+
profileOverridesRaw?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function showHelp(): void {
|
|
33
|
+
printHelp('API', 'npx auramaxx api [METHOD] <endpoint> [options]', [], [
|
|
34
|
+
'Examples:',
|
|
35
|
+
' npx auramaxx api GET /health --no-auth',
|
|
36
|
+
' npx auramaxx api GET /setup --no-auth',
|
|
37
|
+
' npx auramaxx api GET /wallets',
|
|
38
|
+
' npx auramaxx api POST /credential-shares --body \'{"credentialId":"cred_x","expiresAfter":"24h"}\'',
|
|
39
|
+
' npx auramaxx api GET /credential-shares/<token> --no-auth',
|
|
40
|
+
' npx auramaxx api POST /auth --no-auth --body \'{"agentId":"cli-api","profile":"dev","profileVersion":"v1","pubkey":"..."}\'',
|
|
41
|
+
'',
|
|
42
|
+
'Options:',
|
|
43
|
+
' --body <json> JSON request body',
|
|
44
|
+
' --no-auth Do not attach bearer auth token',
|
|
45
|
+
' --profile <p> Profile for /auth fallback when socket auto-approve is blocked',
|
|
46
|
+
' --profile-version <v> Profile version for /auth fallback',
|
|
47
|
+
' --profile-overrides <j> Tighten-only profile override JSON for /auth fallback',
|
|
48
|
+
'',
|
|
49
|
+
'Auth:',
|
|
50
|
+
' Uses Unix socket by default.',
|
|
51
|
+
' Falls back to /auth polling when strict local mode disables auto-approve.',
|
|
52
|
+
' Uses AURA_TOKEN if present.',
|
|
53
|
+
]);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function parseArgs(argv: string[]): ApiCliArgs | null {
|
|
57
|
+
const args = [...argv];
|
|
58
|
+
if (args.length === 0 || args.includes('--help') || args.includes('-h')) return null;
|
|
59
|
+
|
|
60
|
+
let method = 'GET';
|
|
61
|
+
let endpoint = '';
|
|
62
|
+
|
|
63
|
+
if (args[0].startsWith('/')) {
|
|
64
|
+
endpoint = args.shift()!;
|
|
65
|
+
} else {
|
|
66
|
+
method = (args.shift() || 'GET').toUpperCase();
|
|
67
|
+
endpoint = args.shift() || '';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (!endpoint) return null;
|
|
71
|
+
if (!endpoint.startsWith('/')) endpoint = `/${endpoint}`;
|
|
72
|
+
|
|
73
|
+
const getValue = (flag: string): string | undefined => {
|
|
74
|
+
const idx = args.indexOf(flag);
|
|
75
|
+
return idx >= 0 ? args[idx + 1] : undefined;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
method,
|
|
80
|
+
endpoint,
|
|
81
|
+
bodyRaw: getValue('--body'),
|
|
82
|
+
noAuth: args.includes('--no-auth'),
|
|
83
|
+
profile: getValue('--profile'),
|
|
84
|
+
profileVersion: getValue('--profile-version'),
|
|
85
|
+
profileOverridesRaw: getValue('--profile-overrides'),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function parseProfileOverrides(raw?: string): ProfileIssuanceSelection['profileOverrides'] | undefined {
|
|
90
|
+
if (!raw) return undefined;
|
|
91
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
92
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
93
|
+
throw new Error('--profile-overrides must be a JSON object');
|
|
94
|
+
}
|
|
95
|
+
return parsed as ProfileIssuanceSelection['profileOverrides'];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function parseBody(raw?: string): unknown | undefined {
|
|
99
|
+
if (!raw) return undefined;
|
|
100
|
+
return JSON.parse(raw) as unknown;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async function resolveAuthToken(selection: ProfileIssuanceSelection): Promise<string> {
|
|
104
|
+
const envToken = process.env.AURA_TOKEN;
|
|
105
|
+
if (envToken) return envToken;
|
|
106
|
+
|
|
107
|
+
const keypair = generateEphemeralKeypair();
|
|
108
|
+
|
|
109
|
+
// If an explicit profile was requested, skip socket bootstrap (which ignores profiles)
|
|
110
|
+
// and create the /auth request non-blocking — print approval URL and exit.
|
|
111
|
+
if (selection.profile) {
|
|
112
|
+
const result = await bootstrapViaAuthRequest(serverUrl(), 'cli-api', keypair, {
|
|
113
|
+
...selection,
|
|
114
|
+
noWait: true,
|
|
115
|
+
onStatus: (message) => console.error(message),
|
|
116
|
+
});
|
|
117
|
+
if (result.approveUrl) {
|
|
118
|
+
console.error(`Approve at: ${result.approveUrl}`);
|
|
119
|
+
}
|
|
120
|
+
console.error(`After approval, re-run with: AURA_TOKEN=<token> npx auramaxx api ...`);
|
|
121
|
+
console.error(`Or use: npx auramaxx auth request --profile ${selection.profile} --raw-token`);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
return await bootstrapViaSocket('cli-api', keypair);
|
|
127
|
+
} catch (socketErr) {
|
|
128
|
+
return bootstrapViaAuthRequest(serverUrl(), 'cli-api', keypair, {
|
|
129
|
+
...selection,
|
|
130
|
+
onStatus: (message) => console.error(message),
|
|
131
|
+
}).catch((authErr) => {
|
|
132
|
+
throw new Error(`${getErrorMessage(socketErr)}\n${getErrorMessage(authErr)}`);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async function main(): Promise<void> {
|
|
138
|
+
const parsed = parseArgs(process.argv.slice(2));
|
|
139
|
+
if (!parsed) {
|
|
140
|
+
showHelp();
|
|
141
|
+
process.exit(0);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const base = serverUrl();
|
|
145
|
+
const url = `${base}${parsed.endpoint}`;
|
|
146
|
+
|
|
147
|
+
const profileOverrides = parseProfileOverrides(parsed.profileOverridesRaw);
|
|
148
|
+
const authSelection: ProfileIssuanceSelection = {
|
|
149
|
+
...(parsed.profile ? { profile: parsed.profile } : {}),
|
|
150
|
+
...(parsed.profileVersion ? { profileVersion: parsed.profileVersion } : {}),
|
|
151
|
+
...(profileOverrides ? { profileOverrides } : {}),
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const body = parseBody(parsed.bodyRaw);
|
|
155
|
+
const token = parsed.noAuth ? null : await resolveAuthToken(authSelection);
|
|
156
|
+
|
|
157
|
+
const headers: Record<string, string> = {};
|
|
158
|
+
if (body !== undefined) headers['Content-Type'] = 'application/json';
|
|
159
|
+
if (token) headers['Authorization'] = `Bearer ${token}`;
|
|
160
|
+
|
|
161
|
+
const res = await fetch(url, {
|
|
162
|
+
method: parsed.method,
|
|
163
|
+
headers,
|
|
164
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
165
|
+
signal: AbortSignal.timeout(15_000),
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const text = await res.text();
|
|
169
|
+
let payload: unknown = text;
|
|
170
|
+
try {
|
|
171
|
+
payload = text ? JSON.parse(text) as unknown : {};
|
|
172
|
+
} catch {
|
|
173
|
+
payload = text;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (!res.ok) {
|
|
177
|
+
const handledLock = await maybeHandleLockError({
|
|
178
|
+
context: 'api command',
|
|
179
|
+
statusCode: res.status,
|
|
180
|
+
payload,
|
|
181
|
+
});
|
|
182
|
+
if (!handledLock) {
|
|
183
|
+
if (handlePermissionDenied(res.status, payload)) {
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
if (typeof payload === 'string') {
|
|
187
|
+
console.error(`HTTP ${res.status}: ${payload}`);
|
|
188
|
+
} else {
|
|
189
|
+
console.error(`HTTP ${res.status}: ${JSON.stringify(payload, null, 2)}`);
|
|
190
|
+
const obj = payload as Record<string, unknown>;
|
|
191
|
+
const approvalUrl = typeof obj.approveUrl === 'string' ? obj.approveUrl : undefined;
|
|
192
|
+
const actionId = typeof obj.actionId === 'string' ? obj.actionId : undefined;
|
|
193
|
+
|
|
194
|
+
if (approvalUrl) {
|
|
195
|
+
console.error(`\nApproval required. Open: ${approvalUrl}`);
|
|
196
|
+
if (actionId) console.error(`Action ID: ${actionId}`);
|
|
197
|
+
console.error('After approval, retry the same command.');
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
process.exit(1);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (typeof payload === 'string') {
|
|
205
|
+
console.log(payload);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
213
|
+
main().catch(async (error) => {
|
|
214
|
+
const handledLock = await maybeHandleLockError({ context: 'api command', error });
|
|
215
|
+
if (!handledLock) {
|
|
216
|
+
console.error(`API call failed: ${getErrorMessage(error)}`);
|
|
217
|
+
}
|
|
218
|
+
process.exit(1);
|
|
219
|
+
});
|
|
220
|
+
}
|