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,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Passkey challenge store and helpers for WebAuthn biometric unlock.
|
|
3
|
+
* Challenges are in-memory, single-use, with 60s TTL.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const CHALLENGE_TTL_MS = 60_000;
|
|
7
|
+
|
|
8
|
+
interface PendingChallenge {
|
|
9
|
+
type: 'register' | 'authenticate';
|
|
10
|
+
expiresAt: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const challenges = new Map<string, PendingChallenge>();
|
|
14
|
+
|
|
15
|
+
// Cleanup expired challenges periodically
|
|
16
|
+
let cleanupTimer: ReturnType<typeof setInterval> | null = null;
|
|
17
|
+
|
|
18
|
+
function ensureCleanup() {
|
|
19
|
+
if (cleanupTimer) return;
|
|
20
|
+
cleanupTimer = setInterval(() => {
|
|
21
|
+
const now = Date.now();
|
|
22
|
+
for (const [key, val] of challenges) {
|
|
23
|
+
if (val.expiresAt <= now) challenges.delete(key);
|
|
24
|
+
}
|
|
25
|
+
if (challenges.size === 0 && cleanupTimer) {
|
|
26
|
+
clearInterval(cleanupTimer);
|
|
27
|
+
cleanupTimer = null;
|
|
28
|
+
}
|
|
29
|
+
}, 30_000);
|
|
30
|
+
// Don't keep process alive for cleanup
|
|
31
|
+
if (cleanupTimer && typeof cleanupTimer === 'object' && 'unref' in cleanupTimer) {
|
|
32
|
+
cleanupTimer.unref();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Store a challenge for later verification.
|
|
38
|
+
*/
|
|
39
|
+
export function storeChallenge(challenge: string, type: 'register' | 'authenticate'): void {
|
|
40
|
+
challenges.set(challenge, { type, expiresAt: Date.now() + CHALLENGE_TTL_MS });
|
|
41
|
+
ensureCleanup();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Consume a challenge (single-use). Returns true if valid and not expired.
|
|
46
|
+
*/
|
|
47
|
+
export function consumeChallenge(challenge: string, type: 'register' | 'authenticate'): boolean {
|
|
48
|
+
const entry = challenges.get(challenge);
|
|
49
|
+
if (!entry) return false;
|
|
50
|
+
challenges.delete(challenge);
|
|
51
|
+
if (entry.type !== type) return false;
|
|
52
|
+
if (entry.expiresAt <= Date.now()) return false;
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Convert base64url string to Uint8Array.
|
|
58
|
+
*/
|
|
59
|
+
export function base64urlToUint8Array(base64url: string): Uint8Array {
|
|
60
|
+
return Buffer.from(base64url, 'base64url');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Convert Uint8Array (or Buffer) to base64url string.
|
|
65
|
+
*/
|
|
66
|
+
export function uint8ArrayToBase64url(bytes: Uint8Array | Buffer): string {
|
|
67
|
+
return Buffer.from(bytes).toString('base64url');
|
|
68
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import { AgentTokenPayload } from '../types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* PERMISSION SYSTEM
|
|
6
|
+
* =================
|
|
7
|
+
*
|
|
8
|
+
* Permission strings control access to specific routes and operations.
|
|
9
|
+
* Admin tokens bypass all permission checks.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// All valid permission strings
|
|
13
|
+
export type Permission =
|
|
14
|
+
// Wallet operations
|
|
15
|
+
| 'wallet:list' // List/view wallets
|
|
16
|
+
| 'wallet:create:hot' // Create hot wallets
|
|
17
|
+
| 'wallet:create:temp' // Create temp wallets
|
|
18
|
+
| 'wallet:rename' // Rename wallets
|
|
19
|
+
| 'wallet:export' // Export private keys
|
|
20
|
+
| 'wallet:tx:add' // Manually add transactions to wallet history
|
|
21
|
+
| 'wallet:asset:add' // Add assets to track for a wallet
|
|
22
|
+
| 'wallet:asset:remove' // Remove tracked assets from a wallet
|
|
23
|
+
|
|
24
|
+
// Transaction operations
|
|
25
|
+
| 'send:hot' // Send from hot wallets
|
|
26
|
+
| 'send:temp' // Send from temp wallets
|
|
27
|
+
| 'swap' // Execute swaps
|
|
28
|
+
| 'fund' // Cold→hot transfers
|
|
29
|
+
| 'launch' // Execute token launches
|
|
30
|
+
|
|
31
|
+
// API Key operations
|
|
32
|
+
| 'apikey:get' // Read API keys
|
|
33
|
+
| 'apikey:set' // Create/update/delete API keys
|
|
34
|
+
|
|
35
|
+
// Workspace/UI operations
|
|
36
|
+
| 'workspace:modify' // Add/update/remove apps, modify workspaces
|
|
37
|
+
|
|
38
|
+
// Strategy operations
|
|
39
|
+
| 'strategy:read' // View strategies and their state
|
|
40
|
+
| 'strategy:manage' // Enable/disable strategies, update config
|
|
41
|
+
|
|
42
|
+
// App operations
|
|
43
|
+
| 'app:storage' // Read/write own app's storage via Express API
|
|
44
|
+
| 'app:storage:all' // Read/write ANY app's storage via Express API
|
|
45
|
+
| 'app:accesskey' // Read API keys from app storage
|
|
46
|
+
|
|
47
|
+
// Action operations
|
|
48
|
+
| 'action:create' // Create human action requests (propose actions for approval)
|
|
49
|
+
| 'action:read' // Read/list pending actions
|
|
50
|
+
| 'action:resolve' // Approve or reject pending actions
|
|
51
|
+
|
|
52
|
+
// Adapter operations
|
|
53
|
+
| 'adapter:manage' // Configure and restart approval adapters (Telegram, webhooks)
|
|
54
|
+
|
|
55
|
+
// Address book & bookmark operations
|
|
56
|
+
| 'addressbook:write' // Create/update/delete address labels
|
|
57
|
+
| 'bookmark:write' // Create/delete token bookmarks
|
|
58
|
+
|
|
59
|
+
// Credential vault operations
|
|
60
|
+
| 'secret:read' // Read credentials from the vault
|
|
61
|
+
| 'secret:write' // Create/update/delete credentials in the vault
|
|
62
|
+
| 'totp:read' // Generate TOTP codes from credential secrets
|
|
63
|
+
|
|
64
|
+
// Compound permissions (expand to multiple permissions)
|
|
65
|
+
| 'trade:all' // All trading permissions + apikey:get + strategy:read
|
|
66
|
+
| 'wallet:write' // All wallet write operations
|
|
67
|
+
| 'extension:*' // Browser extension permissions
|
|
68
|
+
|
|
69
|
+
// Admin (UI only)
|
|
70
|
+
| 'admin:*'; // All permissions, bypass limits
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Compound permission mappings
|
|
74
|
+
* These permissions expand to multiple underlying permissions
|
|
75
|
+
*/
|
|
76
|
+
const COMPOUND_PERMISSIONS: Record<string, Permission[]> = {
|
|
77
|
+
'admin:*': [
|
|
78
|
+
'swap', 'send:hot', 'send:temp', 'fund', 'launch',
|
|
79
|
+
'wallet:create:hot', 'wallet:create:temp', 'wallet:export', 'wallet:list', 'wallet:rename',
|
|
80
|
+
'wallet:tx:add', 'wallet:asset:add', 'wallet:asset:remove',
|
|
81
|
+
'secret:read', 'secret:write', 'totp:read',
|
|
82
|
+
'action:create', 'action:read', 'action:resolve',
|
|
83
|
+
'apikey:get', 'apikey:set',
|
|
84
|
+
'workspace:modify',
|
|
85
|
+
'strategy:read', 'strategy:manage',
|
|
86
|
+
'app:storage', 'app:storage:all', 'app:accesskey',
|
|
87
|
+
'adapter:manage',
|
|
88
|
+
'addressbook:write', 'bookmark:write',
|
|
89
|
+
],
|
|
90
|
+
'trade:all': [
|
|
91
|
+
'wallet:list',
|
|
92
|
+
'wallet:create:hot',
|
|
93
|
+
'wallet:create:temp',
|
|
94
|
+
'send:hot',
|
|
95
|
+
'send:temp',
|
|
96
|
+
'swap',
|
|
97
|
+
'fund',
|
|
98
|
+
'launch',
|
|
99
|
+
'apikey:get',
|
|
100
|
+
'strategy:read'
|
|
101
|
+
],
|
|
102
|
+
'extension:*': [
|
|
103
|
+
'wallet:list',
|
|
104
|
+
'secret:read',
|
|
105
|
+
'action:read',
|
|
106
|
+
'action:resolve'
|
|
107
|
+
],
|
|
108
|
+
'wallet:write': [
|
|
109
|
+
'wallet:create:hot',
|
|
110
|
+
'wallet:create:temp',
|
|
111
|
+
'wallet:rename',
|
|
112
|
+
'wallet:tx:add',
|
|
113
|
+
'wallet:asset:add',
|
|
114
|
+
'wallet:asset:remove'
|
|
115
|
+
]
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Expand and normalize permissions array
|
|
120
|
+
* - Expands compound permissions (e.g., 'trade:all' → multiple permissions)
|
|
121
|
+
* - Deduplicates the result
|
|
122
|
+
*/
|
|
123
|
+
export function expandPermissions(permissions: string[]): Permission[] {
|
|
124
|
+
const expanded = new Set<Permission>();
|
|
125
|
+
|
|
126
|
+
for (const perm of permissions) {
|
|
127
|
+
// Check if this is a compound permission
|
|
128
|
+
if (COMPOUND_PERMISSIONS[perm]) {
|
|
129
|
+
for (const subPerm of COMPOUND_PERMISSIONS[perm]) {
|
|
130
|
+
expanded.add(subPerm);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Always add the original permission too
|
|
134
|
+
expanded.add(perm as Permission);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return Array.from(expanded);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get the list of compound permissions and what they expand to
|
|
142
|
+
*/
|
|
143
|
+
export function getCompoundPermissions(): Record<string, Permission[]> {
|
|
144
|
+
return { ...COMPOUND_PERMISSIONS };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Check if token has ANY of the required permissions
|
|
149
|
+
* Automatically expands compound permissions before checking
|
|
150
|
+
*/
|
|
151
|
+
export function hasAnyPermission(
|
|
152
|
+
tokenPermissions: string[],
|
|
153
|
+
requiredPermissions: string[]
|
|
154
|
+
): boolean {
|
|
155
|
+
// Admin bypass
|
|
156
|
+
if (tokenPermissions.includes('admin:*')) {
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Expand compound permissions
|
|
161
|
+
const expanded = expandPermissions(tokenPermissions);
|
|
162
|
+
|
|
163
|
+
for (const required of requiredPermissions) {
|
|
164
|
+
if (expanded.includes(required as Permission)) {
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Check if token has ALL of the required permissions
|
|
174
|
+
* Automatically expands compound permissions before checking
|
|
175
|
+
*/
|
|
176
|
+
export function hasAllPermissions(
|
|
177
|
+
tokenPermissions: string[],
|
|
178
|
+
requiredPermissions: string[]
|
|
179
|
+
): boolean {
|
|
180
|
+
// Admin bypass
|
|
181
|
+
if (tokenPermissions.includes('admin:*')) {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Expand compound permissions
|
|
186
|
+
const expanded = expandPermissions(tokenPermissions);
|
|
187
|
+
|
|
188
|
+
for (const required of requiredPermissions) {
|
|
189
|
+
if (!expanded.includes(required as Permission)) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Check if a token is an admin token (has admin:* permission)
|
|
199
|
+
*/
|
|
200
|
+
export function isAdmin(auth: { token: { permissions: string[] } }): boolean {
|
|
201
|
+
return auth.token.permissions.includes('admin:*');
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Middleware factory that requires specific permissions
|
|
206
|
+
*
|
|
207
|
+
* Usage:
|
|
208
|
+
* router.post('/create', requireWalletAuth, requirePermission('wallet:create:hot'), handler)
|
|
209
|
+
* router.post('/send', requireWalletAuth, requirePermission('send:hot', 'send:temp'), handler)
|
|
210
|
+
*/
|
|
211
|
+
export function requirePermission(...permissions: string[]) {
|
|
212
|
+
return (req: Request, res: Response, next: NextFunction): void => {
|
|
213
|
+
if (!req.auth) {
|
|
214
|
+
res.status(401).json({ error: 'Authentication required' });
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Check if token has any of the required permissions (admin:* bypasses via hasAnyPermission)
|
|
219
|
+
if (!hasAnyPermission(req.auth.token.permissions, permissions)) {
|
|
220
|
+
const dashboardBase = `http://localhost:${process.env.DASHBOARD_PORT || '4747'}`;
|
|
221
|
+
res.status(403).json({
|
|
222
|
+
error: 'Insufficient permissions',
|
|
223
|
+
required: permissions,
|
|
224
|
+
have: req.auth.token.permissions,
|
|
225
|
+
escalation: {
|
|
226
|
+
via: 'auth',
|
|
227
|
+
permissions,
|
|
228
|
+
dashboard: dashboardBase,
|
|
229
|
+
note: 'Request a new token via POST /auth with a profile that includes the required permissions.',
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
next();
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Middleware that requires admin permission specifically
|
|
241
|
+
*/
|
|
242
|
+
export function requireAdmin(req: Request, res: Response, next: NextFunction): void {
|
|
243
|
+
if (!req.auth) {
|
|
244
|
+
res.status(401).json({ error: 'Authentication required' });
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (!isAdmin(req.auth)) {
|
|
249
|
+
const dashboardBase = `http://localhost:${process.env.DASHBOARD_PORT || '4747'}`;
|
|
250
|
+
res.status(403).json({
|
|
251
|
+
error: 'Admin access required',
|
|
252
|
+
required: ['admin:*'],
|
|
253
|
+
have: req.auth.token.permissions,
|
|
254
|
+
escalation: {
|
|
255
|
+
via: 'auth',
|
|
256
|
+
permissions: ['admin:*'],
|
|
257
|
+
dashboard: dashboardBase,
|
|
258
|
+
note: 'Request a new token via POST /auth with profile "admin".',
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
next();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Get the permission required for a wallet tier operation
|
|
269
|
+
*/
|
|
270
|
+
export function getWalletCreatePermission(tier: 'hot' | 'temp'): Permission {
|
|
271
|
+
return tier === 'hot' ? 'wallet:create:hot' : 'wallet:create:temp';
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Get the permission required for sending from a wallet tier
|
|
276
|
+
*/
|
|
277
|
+
export function getSendPermission(tier: 'hot' | 'temp'): Permission {
|
|
278
|
+
return tier === 'hot' ? 'send:hot' : 'send:temp';
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Build a 403 response body with escalation info.
|
|
283
|
+
* Use this instead of bare `{ error: '...' }` for permission denials
|
|
284
|
+
* so that agents (MCP, CLI, SDK) know how to self-escalate.
|
|
285
|
+
*/
|
|
286
|
+
export function buildPermissionDenied(error: string, required: string[], have?: string[]): Record<string, unknown> {
|
|
287
|
+
const dashboardBase = `http://localhost:${process.env.DASHBOARD_PORT || '4747'}`;
|
|
288
|
+
return {
|
|
289
|
+
error,
|
|
290
|
+
required,
|
|
291
|
+
...(have ? { have } : {}),
|
|
292
|
+
escalation: {
|
|
293
|
+
via: 'auth',
|
|
294
|
+
permissions: required,
|
|
295
|
+
dashboard: dashboardBase,
|
|
296
|
+
note: 'Request a new token via POST /auth with a profile that includes the required permissions.',
|
|
297
|
+
},
|
|
298
|
+
};
|
|
299
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Pino logger instance for the Express server (port 4242)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import pino from 'pino';
|
|
6
|
+
|
|
7
|
+
const isDev = process.env.NODE_ENV !== 'production';
|
|
8
|
+
const isTest = process.env.NODE_ENV === 'test' || process.env.VITEST === 'true';
|
|
9
|
+
|
|
10
|
+
export const log = pino({
|
|
11
|
+
level: isTest ? 'silent' : (process.env.LOG_LEVEL || 'debug'),
|
|
12
|
+
...(isDev && !isTest
|
|
13
|
+
? {
|
|
14
|
+
transport: {
|
|
15
|
+
target: 'pino-pretty',
|
|
16
|
+
options: {
|
|
17
|
+
colorize: true,
|
|
18
|
+
translateTime: 'HH:MM:ss.l',
|
|
19
|
+
ignore: 'pid,hostname',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
: {}),
|
|
24
|
+
});
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { ResolveProfileInput, ResolvedProfilePolicy } from './agent-profiles';
|
|
2
|
+
|
|
3
|
+
export type DenyCode =
|
|
4
|
+
| 'DENY_PERMISSION_MISSING'
|
|
5
|
+
| 'DENY_CREDENTIAL_READ_SCOPE'
|
|
6
|
+
| 'DENY_CREDENTIAL_WRITE_SCOPE'
|
|
7
|
+
| 'DENY_EXCLUDED_FIELD'
|
|
8
|
+
| 'DENY_MAX_READS_EXCEEDED'
|
|
9
|
+
| 'DENY_RATE_LIMIT';
|
|
10
|
+
|
|
11
|
+
export interface PolicyPreviewV1 {
|
|
12
|
+
version: 'v1';
|
|
13
|
+
request: {
|
|
14
|
+
profile: string;
|
|
15
|
+
profileVersion: string;
|
|
16
|
+
overrides?: ResolveProfileInput['overrides'];
|
|
17
|
+
};
|
|
18
|
+
effectivePolicy: {
|
|
19
|
+
permissions: string[];
|
|
20
|
+
credentialAccess: {
|
|
21
|
+
read: string[];
|
|
22
|
+
write: string[];
|
|
23
|
+
excludeFields: string[];
|
|
24
|
+
maxReads: number | null;
|
|
25
|
+
};
|
|
26
|
+
ttlSeconds: number;
|
|
27
|
+
maxReads: number | null;
|
|
28
|
+
rateBudget: {
|
|
29
|
+
state: 'none' | 'inherited' | 'explicit';
|
|
30
|
+
requests: number | null;
|
|
31
|
+
windowSeconds: number | null;
|
|
32
|
+
source: 'none' | 'profile' | 'override';
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
effectivePolicyHash: string;
|
|
36
|
+
overrideDelta: string[];
|
|
37
|
+
warnings: string[];
|
|
38
|
+
denyExamples: Array<{ code: DenyCode; message: string }>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function canonicalizeEffectivePolicy(policy: ResolvedProfilePolicy): PolicyPreviewV1['effectivePolicy'] {
|
|
42
|
+
return {
|
|
43
|
+
permissions: Array.from(new Set(policy.permissions)).sort(),
|
|
44
|
+
credentialAccess: {
|
|
45
|
+
read: Array.from(new Set(policy.credentialAccess.read || [])).sort(),
|
|
46
|
+
write: Array.from(new Set(policy.credentialAccess.write || [])).sort(),
|
|
47
|
+
excludeFields: Array.from(new Set(policy.credentialAccess.excludeFields || [])).sort(),
|
|
48
|
+
maxReads: typeof policy.credentialAccess.maxReads === 'number' ? policy.credentialAccess.maxReads : null,
|
|
49
|
+
},
|
|
50
|
+
ttlSeconds: policy.ttlSeconds,
|
|
51
|
+
maxReads: typeof policy.credentialAccess.maxReads === 'number' ? policy.credentialAccess.maxReads : null,
|
|
52
|
+
rateBudget: {
|
|
53
|
+
state: 'none',
|
|
54
|
+
requests: null,
|
|
55
|
+
windowSeconds: null,
|
|
56
|
+
source: 'none',
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const DENY_ORDER: DenyCode[] = [
|
|
62
|
+
'DENY_PERMISSION_MISSING',
|
|
63
|
+
'DENY_CREDENTIAL_READ_SCOPE',
|
|
64
|
+
'DENY_CREDENTIAL_WRITE_SCOPE',
|
|
65
|
+
'DENY_EXCLUDED_FIELD',
|
|
66
|
+
'DENY_MAX_READS_EXCEEDED',
|
|
67
|
+
'DENY_RATE_LIMIT',
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
const DENY_MESSAGES: Record<DenyCode, string> = {
|
|
71
|
+
DENY_PERMISSION_MISSING: 'Operation denied: required permission is not granted by this policy.',
|
|
72
|
+
DENY_CREDENTIAL_READ_SCOPE: 'Credential read denied: target credential is outside allowed read scopes.',
|
|
73
|
+
DENY_CREDENTIAL_WRITE_SCOPE: 'Credential write denied: target credential is outside allowed write scopes.',
|
|
74
|
+
DENY_EXCLUDED_FIELD: 'Field access denied: requested field is explicitly excluded by policy.',
|
|
75
|
+
DENY_MAX_READS_EXCEEDED: 'Read denied: token maxReads budget would be exceeded.',
|
|
76
|
+
DENY_RATE_LIMIT: 'Rate limit denied: request would exceed configured token rate budget.',
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export function buildDenyExamples(): Array<{ code: DenyCode; message: string }> {
|
|
80
|
+
return DENY_ORDER.map((code) => ({ code, message: DENY_MESSAGES[code] }));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function buildPolicyPreviewV1(
|
|
84
|
+
input: ResolveProfileInput,
|
|
85
|
+
resolved: ResolvedProfilePolicy,
|
|
86
|
+
): PolicyPreviewV1 {
|
|
87
|
+
const profileVersion = input.profileVersion || resolved.profile.version;
|
|
88
|
+
return {
|
|
89
|
+
version: 'v1',
|
|
90
|
+
request: {
|
|
91
|
+
profile: input.profileId,
|
|
92
|
+
profileVersion,
|
|
93
|
+
...(input.overrides ? { overrides: input.overrides } : {}),
|
|
94
|
+
},
|
|
95
|
+
effectivePolicy: canonicalizeEffectivePolicy(resolved),
|
|
96
|
+
effectivePolicyHash: resolved.effectivePolicyHash,
|
|
97
|
+
overrideDelta: [...resolved.overrideDelta],
|
|
98
|
+
warnings: [...resolved.warnings],
|
|
99
|
+
denyExamples: buildDenyExamples(),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface PreviewErrorV1 {
|
|
104
|
+
version: 'v1';
|
|
105
|
+
code:
|
|
106
|
+
| 'ERR_UNAUTHORIZED'
|
|
107
|
+
| 'ERR_FORBIDDEN'
|
|
108
|
+
| 'ERR_PROFILE_NOT_FOUND'
|
|
109
|
+
| 'ERR_PROFILE_VERSION_UNSUPPORTED'
|
|
110
|
+
| 'ERR_OVERRIDE_INVALID'
|
|
111
|
+
| 'ERR_RESOLUTION_FAILED';
|
|
112
|
+
error: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function mapPreviewError(code: string): { status: number; error: PreviewErrorV1 } {
|
|
116
|
+
if (code === 'AGENT_PROFILE_NOT_FOUND') {
|
|
117
|
+
return {
|
|
118
|
+
status: 404,
|
|
119
|
+
error: { version: 'v1', code: 'ERR_PROFILE_NOT_FOUND', error: 'Requested profile does not exist.' },
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
if (code === 'AGENT_PROFILE_VERSION_UNSUPPORTED') {
|
|
123
|
+
return {
|
|
124
|
+
status: 409,
|
|
125
|
+
error: { version: 'v1', code: 'ERR_PROFILE_VERSION_UNSUPPORTED', error: 'Requested profile version is unsupported.' },
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
if (code.startsWith('AGENT_PROFILE_')) {
|
|
129
|
+
return {
|
|
130
|
+
status: 422,
|
|
131
|
+
error: { version: 'v1', code: 'ERR_OVERRIDE_INVALID', error: 'Profile overrides are invalid for the selected profile.' },
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
status: 500,
|
|
136
|
+
error: { version: 'v1', code: 'ERR_RESOLUTION_FAILED', error: 'Failed to resolve policy preview.' },
|
|
137
|
+
};
|
|
138
|
+
}
|