tapimo 0.15.0 → 0.18.0
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/README.md +137 -0
- package/dist/ApiKey.d.ts +1 -0
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +4 -2
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +37 -11
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +163 -10
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +13085 -11974
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +46 -15
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +1 -1
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +1 -1
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +896 -191
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +5 -1
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +33 -33
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +8 -3
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +66 -27
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +36 -7
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +25 -25
- package/dist/admin/apps/organizations.d.ts.map +1 -1
- package/dist/admin/apps/organizations.js +5 -4
- package/dist/admin/apps/organizations.js.map +1 -1
- package/dist/admin/apps/route-policies.d.ts +632 -0
- package/dist/admin/apps/route-policies.d.ts.map +1 -0
- package/dist/admin/apps/route-policies.js +257 -0
- package/dist/admin/apps/route-policies.js.map +1 -0
- package/dist/admin/apps/routes-support.js +39 -3
- package/dist/admin/apps/routes-support.js.map +1 -1
- package/dist/admin/apps/routes.d.ts +454 -1
- package/dist/admin/apps/routes.d.ts.map +1 -1
- package/dist/admin/apps/routes.js +82 -1
- package/dist/admin/apps/routes.js.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +10 -4
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.js +24 -4
- package/dist/admin/apps/verified-tokens.js.map +1 -1
- package/dist/admin/index.d.ts +0 -1
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +0 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.d.ts.map +1 -1
- package/dist/admin/ui.generated.js +99 -103
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/Analytics.d.ts.map +1 -1
- package/dist/analytics/Analytics.js +65 -1
- package/dist/analytics/Analytics.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts +1 -1
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +58 -59
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/data/App.d.ts +2709 -2670
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +5 -5
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +50 -0
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +248 -248
- package/dist/apps/data/routes/balances.d.ts +22 -22
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +5 -7
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +54 -54
- package/dist/apps/data/routes/earn.d.ts +103 -12
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +456 -220
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +267 -97
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts +1 -19
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +93 -56
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +10 -10
- package/dist/apps/data/routes/rpc.d.ts +30 -30
- package/dist/apps/data/routes/rpc.js +45 -11
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +11 -6
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +2 -0
- package/dist/apps/data/routes/transactions.d.ts.map +1 -1
- package/dist/apps/data/routes/transactions.js +30 -22
- package/dist/apps/data/routes/transactions.js.map +1 -1
- package/dist/apps/data/routes/transfers.d.ts +12 -12
- package/dist/apps/data/routes/valuation.d.ts +30 -30
- package/dist/apps/data/routes/verified-tokens.d.ts +5 -5
- package/dist/apps/data/routes/webhooks.d.ts +1 -1
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +18 -11
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zones.d.ts +3 -3
- package/dist/apps/management/App.d.ts +3043 -2198
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +2 -0
- package/dist/apps/management/App.js.map +1 -1
- package/dist/apps/management/Billing.d.ts +2 -4
- package/dist/apps/management/Billing.d.ts.map +1 -1
- package/dist/apps/management/Billing.js +65 -26
- package/dist/apps/management/Billing.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +16 -4
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +70 -11
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +84 -84
- package/dist/apps/management/routes/cli.d.ts +912 -0
- package/dist/apps/management/routes/cli.d.ts.map +1 -0
- package/dist/apps/management/routes/cli.js +416 -0
- package/dist/apps/management/routes/cli.js.map +1 -0
- package/dist/apps/management/routes/faucet.d.ts +8 -8
- package/dist/apps/management/routes/invitations.d.ts +24 -24
- package/dist/apps/management/routes/invite-links.d.ts +66 -66
- package/dist/apps/management/routes/members.d.ts +16 -16
- package/dist/apps/management/routes/orgs.d.ts +20 -20
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +8 -2
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts +76 -76
- package/dist/apps/management/routes/usage.d.ts +8 -8
- package/dist/apps/management/routes/verified-token-requests.d.ts +42 -42
- package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.js +7 -9
- package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
- package/dist/apps/management/routes/webhooks.d.ts +119 -119
- package/dist/apps/mcp.d.ts.map +1 -1
- package/dist/apps/mcp.js +16 -3
- package/dist/apps/mcp.js.map +1 -1
- package/dist/apps/mpp/internal/Policy.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Policy.js +4 -2
- package/dist/apps/mpp/internal/Policy.js.map +1 -1
- package/dist/apps/mpp/internal/Sponsorship.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Sponsorship.js +6 -4
- package/dist/apps/mpp/internal/Sponsorship.js.map +1 -1
- package/dist/apps/relay/App.d.ts +8 -0
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +16 -4
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/relay/Sponsorships.d.ts +4 -6
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
- package/dist/apps/relay/Sponsorships.js +71 -60
- package/dist/apps/relay/Sponsorships.js.map +1 -1
- package/dist/apps/routes/Access.d.ts +53 -0
- package/dist/apps/routes/Access.d.ts.map +1 -1
- package/dist/apps/routes/Access.js +121 -0
- package/dist/apps/routes/Access.js.map +1 -1
- package/dist/apps/routes/App.d.ts +397 -158
- package/dist/apps/routes/App.d.ts.map +1 -1
- package/dist/apps/routes/App.js.map +1 -1
- package/dist/apps/routes/routes/deposit-addresses.d.ts +169 -61
- package/dist/apps/routes/routes/deposit-addresses.d.ts.map +1 -1
- package/dist/apps/routes/routes/deposit-addresses.js +217 -32
- package/dist/apps/routes/routes/deposit-addresses.js.map +1 -1
- package/dist/apps/routes/routes/quotes.d.ts +90 -0
- package/dist/apps/routes/routes/quotes.d.ts.map +1 -1
- package/dist/apps/routes/routes/quotes.js +101 -27
- package/dist/apps/routes/routes/quotes.js.map +1 -1
- package/dist/apps/routes/routes/transfers.d.ts +187 -135
- package/dist/apps/routes/routes/transfers.d.ts.map +1 -1
- package/dist/apps/routes/routes/transfers.js +182 -37
- package/dist/apps/routes/routes/transfers.js.map +1 -1
- package/dist/cli/ApiKeys.d.ts +120 -0
- package/dist/cli/ApiKeys.d.ts.map +1 -0
- package/dist/cli/ApiKeys.js +138 -0
- package/dist/cli/ApiKeys.js.map +1 -0
- package/dist/cli/Cli.d.ts +92 -34
- package/dist/cli/Cli.d.ts.map +1 -1
- package/dist/cli/Cli.js +188 -11
- package/dist/cli/Cli.js.map +1 -1
- package/dist/cli/Credentials.d.ts +95 -0
- package/dist/cli/Credentials.d.ts.map +1 -0
- package/dist/cli/Credentials.js +110 -0
- package/dist/cli/Credentials.js.map +1 -0
- package/dist/cli/Spec.d.ts +59 -0
- package/dist/cli/Spec.d.ts.map +1 -0
- package/dist/cli/Spec.js +77 -0
- package/dist/cli/Spec.js.map +1 -0
- package/dist/cli/bin.js +5 -1
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/commands/admin.d.ts +5 -5
- package/dist/cli/commands/admin.d.ts.map +1 -1
- package/dist/cli/commands/auth.d.ts +73 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +204 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/keys.d.ts +17 -0
- package/dist/cli/commands/keys.d.ts.map +1 -0
- package/dist/cli/commands/keys.js +109 -0
- package/dist/cli/commands/keys.js.map +1 -0
- package/dist/cloudflare.d.ts +27 -2
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +144 -17
- package/dist/cloudflare.js.map +1 -1
- package/dist/db/Db.d.ts +23 -0
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +418 -1
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +44 -1
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +56 -3
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/apiKeyAdmissions.d.ts +28 -2
- package/dist/db/tables/apiKeyAdmissions.d.ts.map +1 -1
- package/dist/db/tables/apiKeyAdmissions.js +65 -9
- package/dist/db/tables/apiKeyAdmissions.js.map +1 -1
- package/dist/db/tables/apiKeyOwnerTombstones.d.ts +2 -0
- package/dist/db/tables/apiKeyOwnerTombstones.d.ts.map +1 -1
- package/dist/db/tables/apiKeyOwnerTombstones.js +2 -2
- package/dist/db/tables/apiKeyOwnerTombstones.js.map +1 -1
- package/dist/db/tables/authAccounts.d.ts.map +1 -1
- package/dist/db/tables/authAccounts.js +1 -0
- package/dist/db/tables/authAccounts.js.map +1 -1
- package/dist/db/tables/earnVaults.d.ts +5 -1
- package/dist/db/tables/earnVaults.d.ts.map +1 -1
- package/dist/db/tables/earnVaults.js +12 -1
- package/dist/db/tables/earnVaults.js.map +1 -1
- package/dist/db/tables/organizations.d.ts +4 -2
- package/dist/db/tables/organizations.d.ts.map +1 -1
- package/dist/db/tables/organizations.js +8 -34
- package/dist/db/tables/organizations.js.map +1 -1
- package/dist/db/tables/requestUsage.d.ts +5 -1
- package/dist/db/tables/requestUsage.d.ts.map +1 -1
- package/dist/db/tables/requestUsage.js +10 -2
- package/dist/db/tables/requestUsage.js.map +1 -1
- package/dist/db/tables/rewardEligibilityAssociations.d.ts +13 -0
- package/dist/db/tables/rewardEligibilityAssociations.d.ts.map +1 -1
- package/dist/db/tables/rewardEligibilityAssociations.js +11 -0
- package/dist/db/tables/rewardEligibilityAssociations.js.map +1 -1
- package/dist/db/tables/rewardRuns.d.ts.map +1 -1
- package/dist/db/tables/rewardRuns.js +4 -0
- package/dist/db/tables/rewardRuns.js.map +1 -1
- package/dist/db/tables/rewardTransactionAttempts.d.ts.map +1 -1
- package/dist/db/tables/rewardTransactionAttempts.js +2 -0
- package/dist/db/tables/rewardTransactionAttempts.js.map +1 -1
- package/dist/db/tables/routesDepositAddresses.d.ts +29 -0
- package/dist/db/tables/routesDepositAddresses.d.ts.map +1 -1
- package/dist/db/tables/routesDepositAddresses.js +84 -31
- package/dist/db/tables/routesDepositAddresses.js.map +1 -1
- package/dist/db/tables/routesDeposits.d.ts.map +1 -1
- package/dist/db/tables/routesDeposits.js +31 -21
- package/dist/db/tables/routesDeposits.js.map +1 -1
- package/dist/db/tables/routesIdempotency.d.ts.map +1 -1
- package/dist/db/tables/routesIdempotency.js +2 -0
- package/dist/db/tables/routesIdempotency.js.map +1 -1
- package/dist/db/tables/routesPolicies.d.ts +58 -0
- package/dist/db/tables/routesPolicies.d.ts.map +1 -0
- package/dist/db/tables/routesPolicies.js +198 -0
- package/dist/db/tables/routesPolicies.js.map +1 -0
- package/dist/db/tables/routesTransferSubsidies.d.ts +22 -0
- package/dist/db/tables/routesTransferSubsidies.d.ts.map +1 -1
- package/dist/db/tables/routesTransferSubsidies.js +41 -0
- package/dist/db/tables/routesTransferSubsidies.js.map +1 -1
- package/dist/db/tables/routesTransferSubsidyNonces.d.ts.map +1 -1
- package/dist/db/tables/routesTransferSubsidyNonces.js +12 -4
- package/dist/db/tables/routesTransferSubsidyNonces.js.map +1 -1
- package/dist/db/tables/routesTransfers.d.ts +26 -1
- package/dist/db/tables/routesTransfers.d.ts.map +1 -1
- package/dist/db/tables/routesTransfers.js +36 -6
- package/dist/db/tables/routesTransfers.js.map +1 -1
- package/dist/db/tables/sponsoredTransactions.d.ts +45 -13
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
- package/dist/db/tables/sponsoredTransactions.js +144 -33
- package/dist/db/tables/sponsoredTransactions.js.map +1 -1
- package/dist/db/tables/users.d.ts +2 -0
- package/dist/db/tables/users.d.ts.map +1 -1
- package/dist/db/tables/users.js +11 -0
- package/dist/db/tables/users.js.map +1 -1
- package/dist/db/tables/verifiedTokenRequests.d.ts +21 -4
- package/dist/db/tables/verifiedTokenRequests.d.ts.map +1 -1
- package/dist/db/tables/verifiedTokenRequests.js +65 -44
- package/dist/db/tables/verifiedTokenRequests.js.map +1 -1
- package/dist/handlers/internal/multisig.d.ts +1 -1
- package/dist/handlers/internal/multisig.d.ts.map +1 -1
- package/dist/handlers/internal/multisig.js +3 -2
- package/dist/handlers/internal/multisig.js.map +1 -1
- package/dist/handlers/relay.d.ts +2 -0
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +34 -15
- package/dist/handlers/relay.js.map +1 -1
- package/dist/internal/Auth.d.ts +73 -6
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +212 -85
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/BetterAuth.d.ts +22 -0
- package/dist/internal/BetterAuth.d.ts.map +1 -1
- package/dist/internal/BetterAuth.js +17 -14
- package/dist/internal/BetterAuth.js.map +1 -1
- package/dist/internal/Cache.d.ts +5 -0
- package/dist/internal/Cache.d.ts.map +1 -1
- package/dist/internal/Cache.js +3 -1
- package/dist/internal/Cache.js.map +1 -1
- package/dist/internal/CliAuth.d.ts +243 -0
- package/dist/internal/CliAuth.d.ts.map +1 -0
- package/dist/internal/CliAuth.js +249 -0
- package/dist/internal/CliAuth.js.map +1 -0
- package/dist/internal/EarnSharePrices.d.ts +1 -1
- package/dist/internal/EarnSharePrices.d.ts.map +1 -1
- package/dist/internal/EarnSharePrices.js +7 -3
- package/dist/internal/EarnSharePrices.js.map +1 -1
- package/dist/internal/EarnVaults.d.ts +47 -0
- package/dist/internal/EarnVaults.d.ts.map +1 -1
- package/dist/internal/EarnVaults.js +188 -4
- package/dist/internal/EarnVaults.js.map +1 -1
- package/dist/internal/EarnWithdrawals.d.ts +73 -0
- package/dist/internal/EarnWithdrawals.d.ts.map +1 -0
- package/dist/internal/EarnWithdrawals.js +189 -0
- package/dist/internal/EarnWithdrawals.js.map +1 -0
- package/dist/internal/ExecutionContext.d.ts +21 -0
- package/dist/internal/ExecutionContext.d.ts.map +1 -0
- package/dist/internal/ExecutionContext.js +16 -0
- package/dist/internal/ExecutionContext.js.map +1 -0
- package/dist/internal/Log.d.ts +7 -3
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +163 -130
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/MetricSink.d.ts.map +1 -1
- package/dist/internal/MetricSink.js +26 -1
- package/dist/internal/MetricSink.js.map +1 -1
- package/dist/internal/RateLimit.d.ts +67 -0
- package/dist/internal/RateLimit.d.ts.map +1 -1
- package/dist/internal/RateLimit.js +174 -27
- package/dist/internal/RateLimit.js.map +1 -1
- package/dist/internal/Store.d.ts +6 -0
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +4 -5
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/Timing.d.ts +6 -0
- package/dist/internal/Timing.d.ts.map +1 -1
- package/dist/internal/Timing.js +21 -1
- package/dist/internal/Timing.js.map +1 -1
- package/dist/internal/Tron.d.ts +124 -0
- package/dist/internal/Tron.d.ts.map +1 -0
- package/dist/internal/Tron.js +202 -0
- package/dist/internal/Tron.js.map +1 -0
- package/dist/internal/Viem.d.ts +4 -0
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Viem.js +25 -6
- package/dist/internal/Viem.js.map +1 -1
- package/dist/internal/rewards/Read.d.ts +2 -2
- package/dist/internal/rewards/Read.d.ts.map +1 -1
- package/dist/internal/rewards/Read.js +11 -2
- package/dist/internal/rewards/Read.js.map +1 -1
- package/dist/internal/routes/Action.d.ts +27 -0
- package/dist/internal/routes/Action.d.ts.map +1 -1
- package/dist/internal/routes/Action.js +49 -1
- package/dist/internal/routes/Action.js.map +1 -1
- package/dist/internal/routes/Chain.d.ts +2 -0
- package/dist/internal/routes/Chain.d.ts.map +1 -1
- package/dist/internal/routes/Chain.js +4 -0
- package/dist/internal/routes/Chain.js.map +1 -1
- package/dist/internal/routes/DepositAddress.d.ts.map +1 -1
- package/dist/internal/routes/DepositAddress.js +5 -0
- package/dist/internal/routes/DepositAddress.js.map +1 -1
- package/dist/internal/routes/Evidence.d.ts.map +1 -1
- package/dist/internal/routes/Evidence.js +6 -2
- package/dist/internal/routes/Evidence.js.map +1 -1
- package/dist/internal/routes/EvmTransferSettlement.d.ts +17 -0
- package/dist/internal/routes/EvmTransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/EvmTransferSettlement.js +196 -0
- package/dist/internal/routes/EvmTransferSettlement.js.map +1 -0
- package/dist/internal/routes/Policy.d.ts +161 -0
- package/dist/internal/routes/Policy.d.ts.map +1 -0
- package/dist/internal/routes/Policy.js +249 -0
- package/dist/internal/routes/Policy.js.map +1 -0
- package/dist/internal/routes/Provider.d.ts +66 -3
- package/dist/internal/routes/Provider.d.ts.map +1 -1
- package/dist/internal/routes/Provider.js +106 -27
- package/dist/internal/routes/Provider.js.map +1 -1
- package/dist/internal/routes/Quota.d.ts +57 -0
- package/dist/internal/routes/Quota.d.ts.map +1 -0
- package/dist/internal/routes/Quota.js +144 -0
- package/dist/internal/routes/Quota.js.map +1 -0
- package/dist/internal/routes/Reconciliation.d.ts.map +1 -1
- package/dist/internal/routes/Reconciliation.js +163 -47
- package/dist/internal/routes/Reconciliation.js.map +1 -1
- package/dist/internal/routes/SolanaTransferSettlement.d.ts +12 -0
- package/dist/internal/routes/SolanaTransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/SolanaTransferSettlement.js +220 -0
- package/dist/internal/routes/SolanaTransferSettlement.js.map +1 -0
- package/dist/internal/routes/SolanaTransferSubsidy.d.ts +172 -0
- package/dist/internal/routes/SolanaTransferSubsidy.d.ts.map +1 -0
- package/dist/internal/routes/SolanaTransferSubsidy.js +564 -0
- package/dist/internal/routes/SolanaTransferSubsidy.js.map +1 -0
- package/dist/internal/routes/Subsidy.d.ts +2 -2
- package/dist/internal/routes/Subsidy.d.ts.map +1 -1
- package/dist/internal/routes/Subsidy.js +2 -2
- package/dist/internal/routes/Subsidy.js.map +1 -1
- package/dist/internal/routes/Transfer.d.ts +229 -1
- package/dist/internal/routes/Transfer.d.ts.map +1 -1
- package/dist/internal/routes/Transfer.js +644 -7
- package/dist/internal/routes/Transfer.js.map +1 -1
- package/dist/internal/routes/TransferReconciliation.d.ts +6 -0
- package/dist/internal/routes/TransferReconciliation.d.ts.map +1 -1
- package/dist/internal/routes/TransferReconciliation.js +83 -159
- package/dist/internal/routes/TransferReconciliation.js.map +1 -1
- package/dist/internal/routes/TransferSettlement.d.ts +45 -0
- package/dist/internal/routes/TransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/TransferSettlement.js +2 -0
- package/dist/internal/routes/TransferSettlement.js.map +1 -0
- package/dist/internal/routes/TransferSubsidy.d.ts +23 -8
- package/dist/internal/routes/TransferSubsidy.d.ts.map +1 -1
- package/dist/internal/routes/TransferSubsidy.js +64 -5
- package/dist/internal/routes/TransferSubsidy.js.map +1 -1
- package/dist/internal/routes/TronTransferSettlement.d.ts +12 -0
- package/dist/internal/routes/TronTransferSettlement.d.ts.map +1 -0
- package/dist/internal/routes/TronTransferSettlement.js +201 -0
- package/dist/internal/routes/TronTransferSettlement.js.map +1 -0
- package/dist/internal/routes/TronTransferSubsidy.d.ts +174 -0
- package/dist/internal/routes/TronTransferSubsidy.d.ts.map +1 -0
- package/dist/internal/routes/TronTransferSubsidy.js +439 -0
- package/dist/internal/routes/TronTransferSubsidy.js.map +1 -0
- package/dist/internal/routes/index.d.ts +3 -0
- package/dist/internal/routes/index.d.ts.map +1 -1
- package/dist/internal/routes/index.js +3 -0
- package/dist/internal/routes/index.js.map +1 -1
- package/dist/internal/routes/providers/across.d.ts +3 -0
- package/dist/internal/routes/providers/across.d.ts.map +1 -1
- package/dist/internal/routes/providers/across.js +11 -0
- package/dist/internal/routes/providers/across.js.map +1 -1
- package/dist/internal/routes/providers/legacyMesh.d.ts +29 -0
- package/dist/internal/routes/providers/legacyMesh.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMesh.js +474 -0
- package/dist/internal/routes/providers/legacyMesh.js.map +1 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.d.ts +59 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.js +229 -0
- package/dist/internal/routes/providers/legacyMeshDelivery.js.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.d.ts +19 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.js +457 -0
- package/dist/internal/routes/providers/legacyMeshOutbound.js.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.d.ts +123 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.d.ts.map +1 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.js +333 -0
- package/dist/internal/routes/providers/legacyMeshOutboundDelivery.js.map +1 -0
- package/dist/internal/routes/providers/propAmm.d.ts +70 -0
- package/dist/internal/routes/providers/propAmm.d.ts.map +1 -0
- package/dist/internal/routes/providers/propAmm.js +524 -0
- package/dist/internal/routes/providers/propAmm.js.map +1 -0
- package/dist/internal/routes/providers/relay.d.ts +4 -1
- package/dist/internal/routes/providers/relay.d.ts.map +1 -1
- package/dist/internal/routes/providers/relay.js +353 -42
- package/dist/internal/routes/providers/relay.js.map +1 -1
- package/dist/internal/routes/providers/rhino.d.ts +3 -0
- package/dist/internal/routes/providers/rhino.d.ts.map +1 -1
- package/dist/internal/routes/providers/rhino.js +11 -0
- package/dist/internal/routes/providers/rhino.js.map +1 -1
- package/dist/internal/routes/providers/squid.d.ts +3 -0
- package/dist/internal/routes/providers/squid.d.ts.map +1 -1
- package/dist/internal/routes/providers/squid.js +19 -0
- package/dist/internal/routes/providers/squid.js.map +1 -1
- package/dist/internal/routes/providers/stargate.d.ts.map +1 -1
- package/dist/internal/routes/providers/stargate.js +22 -9
- package/dist/internal/routes/providers/stargate.js.map +1 -1
- package/dist/internal/routes/providers/symbiosis.d.ts.map +1 -1
- package/dist/internal/routes/providers/symbiosis.js +13 -17
- package/dist/internal/routes/providers/symbiosis.js.map +1 -1
- package/dist/providers/index.d.ts +14 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +6 -0
- package/dist/providers/index.js.map +1 -1
- package/package.json +16 -6
- package/src/ApiKey.ts +7 -3
- package/src/ApiKeys.test.ts +652 -8
- package/src/ApiKeys.ts +191 -11
- package/src/App.test.ts +405 -18
- package/src/App.ts +51 -15
- package/src/Client.test-d.ts +157 -10
- package/src/Client.test.ts +4 -4
- package/src/Scope.ts +1 -2
- package/src/admin/App.ts +11 -5
- package/src/admin/apps/api-keys.test.ts +98 -2
- package/src/admin/apps/api-keys.ts +21 -12
- package/src/admin/apps/earn-vaults.test.ts +76 -7
- package/src/admin/apps/earn-vaults.ts +47 -8
- package/src/admin/apps/organizations.test.ts +147 -31
- package/src/admin/apps/organizations.ts +5 -4
- package/src/admin/apps/route-policies.test.ts +220 -0
- package/src/admin/apps/route-policies.ts +322 -0
- package/src/admin/apps/routes-support.test.ts +107 -2
- package/src/admin/apps/routes-support.ts +43 -3
- package/src/admin/apps/routes.test.ts +150 -0
- package/src/admin/apps/routes.ts +97 -1
- package/src/admin/apps/scopes.test.ts +1 -1
- package/src/admin/apps/verified-tokens.test.ts +32 -0
- package/src/admin/apps/verified-tokens.ts +30 -4
- package/src/admin/index.ts +0 -1
- package/src/admin/ui/plugin.ts +2 -1
- package/src/admin/ui/src/components/Dialog.tsx +1 -1
- package/src/admin/ui/src/components/EarnVaultForm.tsx +45 -0
- package/src/admin/ui/src/components/RoutePicker.tsx +79 -0
- package/src/admin/ui/src/lib/earn-vaults.ts +1 -1
- package/src/admin/ui/src/lib/route-policies.test.ts +452 -0
- package/src/admin/ui/src/lib/route-policies.ts +232 -0
- package/src/admin/ui/src/lib/routes.ts +34 -0
- package/src/admin/ui/src/lib/verified-tokens.ts +24 -9
- package/src/admin/ui/src/routeTree.gen.ts +21 -0
- package/src/admin/ui/src/routes/__root.tsx +1 -1
- package/src/admin/ui/src/routes/api-keys.tsx +21 -2
- package/src/admin/ui/src/routes/early-access.tsx +1 -0
- package/src/admin/ui/src/routes/earn.vaults.tsx +1 -0
- package/src/admin/ui/src/routes/earn.vaults_.$vaultId.edit.tsx +22 -0
- package/src/admin/ui/src/routes/earn.vaults_.new.tsx +10 -0
- package/src/admin/ui/src/routes/organizations.tsx +35 -4
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +18 -3
- package/src/admin/ui/src/routes/route-policies.tsx +678 -0
- package/src/admin/ui/src/routes/routes.tsx +85 -2
- package/src/admin/ui/src/routes/routes_.support.tsx +6 -22
- package/src/admin/ui/src/routes/subsidies.tsx +1 -0
- package/src/admin/ui/src/routes/verified-tokens.tsx +65 -20
- package/src/admin/ui.generated.ts +99 -104
- package/src/analytics/Analytics.test.ts +4 -50
- package/src/analytics/Analytics.ts +65 -1
- package/src/analytics/tables/requestEvents.test.ts +402 -1
- package/src/analytics/tables/requestEvents.ts +62 -93
- package/src/apps/data/App.test.ts +26 -0
- package/src/apps/data/routes/activities.test.ts +315 -14
- package/src/apps/data/routes/activities.ts +60 -0
- package/src/apps/data/routes/balances.ts +5 -7
- package/src/apps/data/routes/earn.bench.ts +18 -0
- package/src/apps/data/routes/earn.local.test.ts +507 -0
- package/src/apps/data/routes/earn.test.ts +405 -127
- package/src/apps/data/routes/earn.ts +660 -270
- package/src/apps/data/routes/exchanges.bench.ts +3 -1
- package/src/apps/data/routes/exchanges.test.ts +166 -2
- package/src/apps/data/routes/exchanges.ts +308 -101
- package/src/apps/data/routes/fee-amm.test.ts +153 -2
- package/src/apps/data/routes/fee-amm.ts +132 -62
- package/src/apps/data/routes/receipts.test.ts +21 -18
- package/src/apps/data/routes/rpc.test.ts +34 -2
- package/src/apps/data/routes/rpc.ts +47 -10
- package/src/apps/data/routes/tokens.provenance.test.ts +157 -0
- package/src/apps/data/routes/tokens.test.ts +4 -4
- package/src/apps/data/routes/tokens.ts +11 -6
- package/src/apps/data/routes/transactions.test.ts +29 -0
- package/src/apps/data/routes/transactions.ts +33 -22
- package/src/apps/data/routes/webhooks.scan.test.ts +29 -0
- package/src/apps/data/routes/webhooks.test.ts +18 -3
- package/src/apps/data/routes/webhooks.ts +27 -13
- package/src/apps/management/App.ts +4 -0
- package/src/apps/management/Billing.test.ts +253 -27
- package/src/apps/management/Billing.ts +83 -29
- package/src/apps/management/routes/api-keys.test.ts +1 -1
- package/src/apps/management/routes/api-keys.ts +85 -11
- package/src/apps/management/routes/billing.test.ts +68 -4
- package/src/apps/management/routes/cli.test.ts +370 -0
- package/src/apps/management/routes/cli.ts +533 -0
- package/src/apps/management/routes/me.test.ts +14 -4
- package/src/apps/management/routes/orgs.test.ts +108 -4
- package/src/apps/management/routes/orgs.ts +7 -2
- package/src/apps/management/routes/usage.test.ts +2 -2
- package/src/apps/management/routes/verified-token-requests.test.ts +16 -2
- package/src/apps/management/routes/verified-token-requests.ts +7 -10
- package/src/apps/mcp.test.ts +108 -25
- package/src/apps/mcp.ts +15 -3
- package/src/apps/mpp/internal/Policy.test.ts +51 -4
- package/src/apps/mpp/internal/Policy.ts +6 -2
- package/src/apps/mpp/internal/Sponsorship.test.ts +29 -0
- package/src/apps/mpp/internal/Sponsorship.ts +6 -4
- package/src/apps/relay/App.test.ts +85 -1
- package/src/apps/relay/App.ts +28 -4
- package/src/apps/relay/Sponsorships.test.ts +97 -1
- package/src/apps/relay/Sponsorships.ts +77 -66
- package/src/apps/routes/Access.test.ts +319 -0
- package/src/apps/routes/Access.ts +147 -0
- package/src/apps/routes/App.ts +10 -0
- package/src/apps/routes/routes/chains.test.ts +3 -2
- package/src/apps/routes/routes/deposit-addresses.test.ts +978 -34
- package/src/apps/routes/routes/deposit-addresses.ts +243 -32
- package/src/apps/routes/routes/propAmm.local.test.ts +951 -0
- package/src/apps/routes/routes/quotes.test.ts +81 -8
- package/src/apps/routes/routes/quotes.ts +109 -27
- package/src/apps/routes/routes/transfers.test.ts +252 -15
- package/src/apps/routes/routes/transfers.ts +212 -33
- package/src/cli/ApiKeys.test.ts +265 -0
- package/src/cli/ApiKeys.ts +189 -0
- package/src/cli/Cli.test.ts +188 -0
- package/src/cli/Cli.ts +280 -12
- package/src/cli/Credentials.test.ts +122 -0
- package/src/cli/Credentials.ts +144 -0
- package/src/cli/Spec.test.ts +133 -0
- package/src/cli/Spec.ts +132 -0
- package/src/cli/bin.test.ts +49 -0
- package/src/cli/bin.ts +5 -1
- package/src/cli/commands/auth.test.ts +138 -0
- package/src/cli/commands/auth.ts +254 -0
- package/src/cli/commands/keys.test.ts +68 -0
- package/src/cli/commands/keys.ts +125 -0
- package/src/cloudflare.ts +184 -36
- package/src/db/Db.test.ts +877 -0
- package/src/db/Db.ts +507 -1
- package/src/db/Schema.ts +75 -4
- package/src/db/tables/apiKeyAdmissions.test.ts +57 -0
- package/src/db/tables/apiKeyAdmissions.ts +101 -11
- package/src/db/tables/apiKeyOwnerTombstones.ts +2 -2
- package/src/db/tables/authAccounts.test.ts +30 -0
- package/src/db/tables/authAccounts.ts +1 -0
- package/src/db/tables/earnVaults.test.ts +34 -0
- package/src/db/tables/earnVaults.ts +17 -2
- package/src/db/tables/organizations.test.ts +148 -84
- package/src/db/tables/organizations.ts +11 -43
- package/src/db/tables/requestUsage.ts +13 -2
- package/src/db/tables/rewardCampaigns.test.ts +163 -0
- package/src/db/tables/rewardEligibilityAssociations.test.ts +14 -0
- package/src/db/tables/rewardEligibilityAssociations.ts +24 -0
- package/src/db/tables/rewardRuns.ts +4 -0
- package/src/db/tables/rewardTransactionAttempts.ts +2 -0
- package/src/db/tables/routesDepositAddresses.test.ts +263 -0
- package/src/db/tables/routesDepositAddresses.ts +118 -34
- package/src/db/tables/routesDeposits.test.ts +133 -0
- package/src/db/tables/routesDeposits.ts +47 -26
- package/src/db/tables/routesIdempotency.test.ts +80 -0
- package/src/db/tables/routesIdempotency.ts +2 -0
- package/src/db/tables/routesPolicies.test.ts +143 -0
- package/src/db/tables/routesPolicies.ts +251 -0
- package/src/db/tables/routesTransferSubsidies.ts +64 -0
- package/src/db/tables/routesTransferSubsidyNonces.ts +16 -4
- package/src/db/tables/routesTransfers.test.ts +183 -2
- package/src/db/tables/routesTransfers.ts +65 -6
- package/src/db/tables/sponsoredTransactions.test.ts +351 -76
- package/src/db/tables/sponsoredTransactions.ts +182 -38
- package/src/db/tables/users.test.ts +51 -0
- package/src/db/tables/users.ts +12 -0
- package/src/db/tables/verifiedTokenRequests.test.ts +39 -20
- package/src/db/tables/verifiedTokenRequests.ts +80 -44
- package/src/handlers/internal/multisig.store.test.ts +120 -0
- package/src/handlers/internal/multisig.test.ts +389 -0
- package/src/handlers/internal/multisig.ts +13 -10
- package/src/handlers/relay.test.ts +259 -83
- package/src/handlers/relay.ts +36 -17
- package/src/internal/Auth.test.ts +383 -8
- package/src/internal/Auth.ts +272 -99
- package/src/internal/BetterAuth.test.ts +58 -22
- package/src/internal/BetterAuth.ts +23 -17
- package/src/internal/Cache.ts +3 -1
- package/src/internal/CliAuth.test.ts +279 -0
- package/src/internal/CliAuth.ts +319 -0
- package/src/internal/EarnSharePrices.test.ts +25 -0
- package/src/internal/EarnSharePrices.ts +9 -2
- package/src/internal/EarnVaults.test.ts +67 -0
- package/src/internal/EarnVaults.ts +299 -4
- package/src/internal/EarnWithdrawals.test.ts +315 -0
- package/src/internal/EarnWithdrawals.ts +266 -0
- package/src/internal/ExecutionContext.ts +31 -0
- package/src/internal/Log.test.ts +210 -0
- package/src/internal/Log.ts +180 -142
- package/src/internal/MetricSink.test.ts +190 -15
- package/src/internal/MetricSink.ts +27 -1
- package/src/internal/RateLimit.test.ts +144 -8
- package/src/internal/RateLimit.ts +254 -26
- package/src/internal/Store.ts +4 -5
- package/src/internal/Timing.test.ts +32 -0
- package/src/internal/Timing.ts +20 -1
- package/src/internal/Tron.test-d.ts +22 -0
- package/src/internal/Tron.test.ts +94 -0
- package/src/internal/Tron.ts +289 -0
- package/src/internal/Viem.rpc.test.ts +76 -0
- package/src/internal/Viem.ts +29 -6
- package/src/internal/rewards/Read.test.ts +109 -0
- package/src/internal/rewards/Read.ts +13 -4
- package/src/internal/routes/Action.test.ts +70 -0
- package/src/internal/routes/Action.ts +76 -1
- package/src/internal/routes/Chain.test.ts +18 -0
- package/src/internal/routes/Chain.ts +5 -0
- package/src/internal/routes/DepositAddress.ts +5 -0
- package/src/internal/routes/Evidence.test.ts +64 -0
- package/src/internal/routes/Evidence.ts +11 -3
- package/src/internal/routes/EvmTransferSettlement.ts +213 -0
- package/src/internal/routes/Policy.test.ts +316 -0
- package/src/internal/routes/Policy.ts +399 -0
- package/src/internal/routes/Provider.test.ts +103 -2
- package/src/internal/routes/Provider.ts +149 -27
- package/src/internal/routes/Quota.test.ts +149 -0
- package/src/internal/routes/Quota.ts +226 -0
- package/src/internal/routes/Reconciliation.local.test.ts +285 -0
- package/src/internal/routes/Reconciliation.test.ts +371 -13
- package/src/internal/routes/Reconciliation.ts +193 -42
- package/src/internal/routes/SolanaTransferSettlement.ts +232 -0
- package/src/internal/routes/SolanaTransferSubsidy.test.ts +471 -0
- package/src/internal/routes/SolanaTransferSubsidy.ts +760 -0
- package/src/internal/routes/SourceObservation.test.ts +221 -0
- package/src/internal/routes/Subsidy.local.test.ts +46 -0
- package/src/internal/routes/Subsidy.ts +4 -2
- package/src/internal/routes/Transfer.solana.test.ts +389 -0
- package/src/internal/routes/Transfer.test.ts +130 -1
- package/src/internal/routes/Transfer.tron.test.ts +172 -0
- package/src/internal/routes/Transfer.ts +866 -8
- package/src/internal/routes/TransferReconciliation.test.ts +26 -4
- package/src/internal/routes/TransferReconciliation.ts +91 -166
- package/src/internal/routes/TransferSettlement.ts +48 -0
- package/src/internal/routes/TransferSubsidy.local.test.ts +143 -0
- package/src/internal/routes/TransferSubsidy.test.ts +34 -4
- package/src/internal/routes/TransferSubsidy.ts +87 -12
- package/src/internal/routes/TronTransferSettlement.ts +212 -0
- package/src/internal/routes/TronTransferSubsidy.test.ts +109 -0
- package/src/internal/routes/TronTransferSubsidy.ts +619 -0
- package/src/internal/routes/index.test.ts +3 -0
- package/src/internal/routes/index.ts +3 -0
- package/src/internal/routes/providers/across.ts +13 -0
- package/src/internal/routes/providers/index.test.ts +141 -0
- package/src/internal/routes/providers/legacyMesh.test.ts +484 -0
- package/src/internal/routes/providers/legacyMesh.ts +633 -0
- package/src/internal/routes/providers/legacyMeshDelivery.test.ts +306 -0
- package/src/internal/routes/providers/legacyMeshDelivery.ts +320 -0
- package/src/internal/routes/providers/legacyMeshOutbound.test.ts +401 -0
- package/src/internal/routes/providers/legacyMeshOutbound.ts +566 -0
- package/src/internal/routes/providers/legacyMeshOutboundDelivery.ts +473 -0
- package/src/internal/routes/providers/propAmm.ts +640 -0
- package/src/internal/routes/providers/relay.test.ts +1299 -18
- package/src/internal/routes/providers/relay.ts +424 -39
- package/src/internal/routes/providers/rhino.ts +14 -1
- package/src/internal/routes/providers/squid.ts +21 -0
- package/src/internal/routes/providers/stargate.test.ts +105 -1
- package/src/internal/routes/providers/stargate.ts +22 -9
- package/src/internal/routes/providers/symbiosis.ts +13 -47
- package/src/providers/index.test.ts +2 -0
- package/src/providers/index.ts +18 -0
- package/dist/admin/Access.d.ts +0 -39
- package/dist/admin/Access.d.ts.map +0 -1
- package/dist/admin/Access.js +0 -73
- package/dist/admin/Access.js.map +0 -1
- package/src/admin/Access.test.ts +0 -130
- package/src/admin/Access.ts +0 -85
package/src/internal/Auth.ts
CHANGED
|
@@ -20,11 +20,11 @@ import * as z from 'zod/mini'
|
|
|
20
20
|
import type * as App from '../App.js'
|
|
21
21
|
import * as ApiKey from '../ApiKey.js'
|
|
22
22
|
import * as ApiKeys from '../ApiKeys.js'
|
|
23
|
-
import * as ApiKeyAdmissions from '../db/tables/apiKeyAdmissions.js'
|
|
24
|
-
import * as ApiKeyOwnerTombstones from '../db/tables/apiKeyOwnerTombstones.js'
|
|
25
23
|
import * as AuthAccounts from '../db/tables/authAccounts.js'
|
|
26
24
|
import * as BetterAuth from './BetterAuth.js'
|
|
25
|
+
import * as CliAuth from './CliAuth.js'
|
|
27
26
|
import * as Db from '../db/Db.js'
|
|
27
|
+
import * as ExecutionContext from './ExecutionContext.js'
|
|
28
28
|
import type * as Email from './Email.js'
|
|
29
29
|
import * as Memberships from '../db/tables/memberships.js'
|
|
30
30
|
import * as IpAllowlist from './IpAllowlist.js'
|
|
@@ -44,29 +44,32 @@ import type * as Viem from './Viem.js'
|
|
|
44
44
|
|
|
45
45
|
const policySymbol = Symbol('tempo-api.auth.policy')
|
|
46
46
|
const mppManagementSymbol = Symbol('tempo-api.auth.mpp-management')
|
|
47
|
+
const trustedClientIps = new WeakMap<Request, string>()
|
|
47
48
|
const defaultApiKeyRateLimit = { limit: 10_000, period: 'minute' } satisfies RateLimit.Limit
|
|
48
49
|
const defaultIdentitySessionTtl = 24 * 60 * 60
|
|
49
50
|
const defaultMppRateLimit = { limit: 100, period: 'minute' } satisfies RateLimit.Limit
|
|
50
51
|
const defaultPublicRateLimit = { limit: 60, period: 'minute' } satisfies RateLimit.Limit
|
|
51
52
|
const identityCookieName = 'tempo_identity'
|
|
53
|
+
const privacyUrl = 'https://tempo.xyz/privacy-policy/'
|
|
54
|
+
const termsUrl = 'https://console.tempo.xyz/legal/terms'
|
|
52
55
|
const walletIdentityIssuer = 'https://wallet.tempo.xyz/api/oidc'
|
|
53
56
|
|
|
54
|
-
type IdentitySession = {
|
|
55
|
-
/** Wallet address asserted by the identity token. */
|
|
56
|
-
address: string
|
|
57
|
-
/** Verified email asserted by the identity token. */
|
|
58
|
-
email?: string | undefined
|
|
57
|
+
type IdentitySession = WalletSession & {
|
|
59
58
|
/** Unix timestamp when the session expires. */
|
|
60
59
|
expiresAt: number
|
|
61
60
|
/** Unix timestamp when the session was issued. */
|
|
62
61
|
issuedAt: number
|
|
62
|
+
/** Immutable user bound when the session was issued. */
|
|
63
|
+
userId: string
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
type WalletSession = {
|
|
66
67
|
/** Wallet address used to resolve the canonical user. */
|
|
67
68
|
address: string
|
|
68
|
-
/** Verified email
|
|
69
|
+
/** Verified email asserted when the session was issued. */
|
|
69
70
|
email?: string | undefined
|
|
71
|
+
/** Immutable user binding, absent only in legacy sessions. */
|
|
72
|
+
userId?: string | undefined
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
function isIdentityTokenError(error: unknown) {
|
|
@@ -144,7 +147,18 @@ export type Payment = {
|
|
|
144
147
|
}
|
|
145
148
|
|
|
146
149
|
/** Host-provided request backstop that returns a rejection response when over quota. */
|
|
147
|
-
export type EdgeRateLimit = (
|
|
150
|
+
export type EdgeRateLimit = (
|
|
151
|
+
request: Request,
|
|
152
|
+
options: EdgeRateLimit.Options,
|
|
153
|
+
) => Promise<Response | undefined>
|
|
154
|
+
|
|
155
|
+
export namespace EdgeRateLimit {
|
|
156
|
+
/** Request-specific edge backstop options. */
|
|
157
|
+
export type Options = {
|
|
158
|
+
/** Resolves a confirmed credential partition when the shared network limit rejects the request. */
|
|
159
|
+
resolvePartition?: (() => Promise<string | undefined>) | undefined
|
|
160
|
+
}
|
|
161
|
+
}
|
|
148
162
|
|
|
149
163
|
/** MPP route-policy types. Distinct from the authentication {@link Session} capability. */
|
|
150
164
|
export declare namespace Mpp {
|
|
@@ -186,6 +200,8 @@ export type PolicyOverride = {
|
|
|
186
200
|
/** API-key lane: pass quota/scopes overrides, or a boolean to enable/disable. */
|
|
187
201
|
apiKey?:
|
|
188
202
|
| {
|
|
203
|
+
/** Optional counter bucket that isolates this route's quota. */
|
|
204
|
+
bucket?: string | undefined
|
|
189
205
|
/** API-key quota override for this route (a protective per-route cap). */
|
|
190
206
|
rateLimit?: RateLimit.Limit | undefined
|
|
191
207
|
/** Required API-key scopes override for this route. */
|
|
@@ -196,6 +212,8 @@ export type PolicyOverride = {
|
|
|
196
212
|
/** MPP paid lane: object to override the Session request, or boolean to enable/disable. */
|
|
197
213
|
mpp?:
|
|
198
214
|
| {
|
|
215
|
+
/** Optional counter bucket that isolates this route's quota. */
|
|
216
|
+
bucket?: string | undefined
|
|
199
217
|
/** Paid-request quota override for this route (a protective per-route cap). */
|
|
200
218
|
rateLimit?: RateLimit.Limit | undefined
|
|
201
219
|
/** Tempo Session request override for this route. */
|
|
@@ -206,6 +224,8 @@ export type PolicyOverride = {
|
|
|
206
224
|
/** Public lane: object to override the quota, or boolean to enable/disable. */
|
|
207
225
|
public?:
|
|
208
226
|
| {
|
|
227
|
+
/** Optional counter bucket that isolates this route's quota. */
|
|
228
|
+
bucket?: string | undefined
|
|
209
229
|
/** Anonymous public quota override for this route. */
|
|
210
230
|
rateLimit?: RateLimit.Limit | undefined
|
|
211
231
|
}
|
|
@@ -215,6 +235,9 @@ export type PolicyOverride = {
|
|
|
215
235
|
session?: boolean | undefined
|
|
216
236
|
}
|
|
217
237
|
|
|
238
|
+
/** Credential kind a request presented, recorded before it is resolved. */
|
|
239
|
+
export type CredentialKind = 'api_key' | 'payment'
|
|
240
|
+
|
|
218
241
|
/** Authenticated or anonymous caller. */
|
|
219
242
|
export type Principal =
|
|
220
243
|
| {
|
|
@@ -242,15 +265,17 @@ export type Principal =
|
|
|
242
265
|
type: 'public'
|
|
243
266
|
}
|
|
244
267
|
| {
|
|
268
|
+
/** Approved API-key scopes and expiry for a console-authorized CLI device. */
|
|
269
|
+
cli?: { expiresAt: string; scopes: readonly string[] } | undefined
|
|
245
270
|
/** Verified email bound to the session, when present. */
|
|
246
271
|
email?: string | undefined
|
|
247
272
|
/** Principal id: the user id (`usr_…`). */
|
|
248
273
|
id: string
|
|
249
274
|
/** Identity that established the session, as a provider/subject pair (OIDC `iss`/`sub` semantics). */
|
|
250
275
|
identity: {
|
|
251
|
-
/** Identity provider: `email`, `wallet`, or an OIDC issuer. */
|
|
276
|
+
/** Identity provider: `email`, `wallet`, `cli` (a console-approved CLI session), or an OIDC issuer. */
|
|
252
277
|
provider: string
|
|
253
|
-
/** Provider-scoped subject
|
|
278
|
+
/** Provider-scoped subject: the wallet address for `wallet`, the CLI session id (`cli_…`) for `cli`. */
|
|
254
279
|
subject: string
|
|
255
280
|
}
|
|
256
281
|
/** Payment metadata for paid overflow requests. */
|
|
@@ -273,6 +298,8 @@ export type Principal =
|
|
|
273
298
|
export type Variables = {
|
|
274
299
|
/** Auth context consumed by protected handlers. */
|
|
275
300
|
auth: Context
|
|
301
|
+
/** Credential kind the request presented, set before resolution so stalled requests stay attributable. */
|
|
302
|
+
credential?: CredentialKind | undefined
|
|
276
303
|
/** Caller's membership resolved by {@link ensureOrg} or {@link ensureProject}; absent for API keys and `super_admin`. */
|
|
277
304
|
membership?: Memberships.Record | undefined
|
|
278
305
|
/** Organization resolved by {@link ensureOrg} or {@link ensureProject} for the current request. */
|
|
@@ -288,6 +315,17 @@ export function getPrincipal<environment extends Environment>(c: hono_Context<en
|
|
|
288
315
|
return c.get('principal') ?? null
|
|
289
316
|
}
|
|
290
317
|
|
|
318
|
+
/** Resolves the caller IP from configured trusted metadata. */
|
|
319
|
+
export function getTrustedClientIp<environment extends Environment>(c: hono_Context<environment>) {
|
|
320
|
+
const auth = c.get('auth')
|
|
321
|
+
return auth ? trustedClientIp(c, auth) : resolveTrustedClientIp(c.req.raw, undefined)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** Marks a synthesized in-process request with its trusted caller IP address. */
|
|
325
|
+
export function trustClientIp(request: Request, address: string) {
|
|
326
|
+
trustedClientIps.set(request, address)
|
|
327
|
+
}
|
|
328
|
+
|
|
291
329
|
/**
|
|
292
330
|
* Guards `:orgId` routes and resolves the organization. Sessions require membership, API keys require ownership, and the super admin bypasses ownership.
|
|
293
331
|
*/
|
|
@@ -627,7 +665,7 @@ function createAuthMiddleware<
|
|
|
627
665
|
...(sessionChainIds ? { sessionChainIds: new Set(sessionChainIds) } : {}),
|
|
628
666
|
},
|
|
629
667
|
}),
|
|
630
|
-
rateLimit:
|
|
668
|
+
rateLimit: rateLimitStore(options.rateLimit),
|
|
631
669
|
...(options.session ? { session: options.session } : {}),
|
|
632
670
|
...(options.superAdmin?.secret
|
|
633
671
|
? { superAdmin: { tokenHash: ApiKey.hash(options.superAdmin.secret) } }
|
|
@@ -635,6 +673,8 @@ function createAuthMiddleware<
|
|
|
635
673
|
}
|
|
636
674
|
|
|
637
675
|
return createMiddleware<environment>((c, next) => {
|
|
676
|
+
// Every route records its credential, including unprotected and unmatched paths.
|
|
677
|
+
recordCredential(c, getApiKeyCredential(c))
|
|
638
678
|
const resolved = resolveRequestPolicy(c, { base, defaults, options })
|
|
639
679
|
if (!resolved) return next()
|
|
640
680
|
|
|
@@ -666,8 +706,9 @@ function resolveRequestPolicy(c: hono_Context, options: resolveRequestPolicy.Opt
|
|
|
666
706
|
const inheritedKey = `${inheritedMethod.toUpperCase()} ${key.slice(key.indexOf(' ') + 1)}`
|
|
667
707
|
return overrides?.[inheritedKey]
|
|
668
708
|
})()
|
|
669
|
-
|
|
670
|
-
|
|
709
|
+
// Generated management routes already materialize the GET's MPP contract.
|
|
710
|
+
// Reapplying its override would also copy GET-only quota controls.
|
|
711
|
+
const routeOverride = management ? undefined : configuredOverride
|
|
671
712
|
return {
|
|
672
713
|
management,
|
|
673
714
|
policy: bindMppScope(
|
|
@@ -692,8 +733,6 @@ declare namespace resolveRequestPolicy {
|
|
|
692
733
|
type ApiKeyResolverOptions = {
|
|
693
734
|
/** API-key authentication and cache configuration. */
|
|
694
735
|
apiKey: middleware.Options['apiKey']
|
|
695
|
-
/** Authoritative owner store used to reject orphaned API keys. */
|
|
696
|
-
db?: Db.Source | undefined
|
|
697
736
|
/** Scope catalog accepted while resolving records. */
|
|
698
737
|
scopeCatalog: Scope.Catalog | undefined
|
|
699
738
|
}
|
|
@@ -707,16 +746,27 @@ type RequestApiKeyResolution = {
|
|
|
707
746
|
|
|
708
747
|
function createApiKeyResolver(options: ApiKeyResolverOptions) {
|
|
709
748
|
const requests = new WeakMap<hono_Context, RequestApiKeyResolution>()
|
|
710
|
-
|
|
749
|
+
// Requests whose key came from KV in this request: `ApiKeys.resolve` already
|
|
750
|
+
// read the fences, so reading them again adds a round trip and nothing else.
|
|
751
|
+
const fenced = new WeakMap<hono_Context, string>()
|
|
752
|
+
const uncached = async (c: hono_Context, token: string) => {
|
|
711
753
|
const kv = contextKv(c)
|
|
712
|
-
return
|
|
713
|
-
|
|
714
|
-
|
|
754
|
+
if (!kv) return null
|
|
755
|
+
const apiKey = await ApiKeys.resolve(kv.store, token, { scopeCatalog: options.scopeCatalog })
|
|
756
|
+
fenced.set(c, ApiKey.hash(token))
|
|
757
|
+
return apiKey
|
|
715
758
|
}
|
|
716
759
|
const cache =
|
|
717
760
|
options.apiKey === false || options.apiKey?.cache === false
|
|
718
761
|
? { invalidate: () => {}, peek: () => undefined, resolve: uncached }
|
|
719
762
|
: cachedResolve(uncached, options.apiKey?.cache ?? {})
|
|
763
|
+
// A cached record still checks its fences every request, so revocation and
|
|
764
|
+
// owner deletion never wait for the isolate cache to expire.
|
|
765
|
+
const active = async (c: hono_Context, token: string, apiKey: ApiKey.ApiKey | null) => {
|
|
766
|
+
const kv = contextKv(c)
|
|
767
|
+
if (!apiKey || !kv || fenced.get(c) === ApiKey.hash(token)) return apiKey
|
|
768
|
+
return (await ApiKeys.isFenced(kv.store, apiKey)) ? null : apiKey
|
|
769
|
+
}
|
|
720
770
|
|
|
721
771
|
return {
|
|
722
772
|
peek: (c: hono_Context, token: string) => {
|
|
@@ -725,18 +775,16 @@ function createApiKeyResolver(options: ApiKeyResolverOptions) {
|
|
|
725
775
|
if (existing?.tokenHash === tokenHash) return existing.apiKey
|
|
726
776
|
return cache.peek(token)
|
|
727
777
|
},
|
|
778
|
+
probe: async (c: hono_Context, token: string) => {
|
|
779
|
+
// Probes must not warm the resolution cache before rate-limit admission.
|
|
780
|
+
return active(c, token, await uncached(c, token))
|
|
781
|
+
},
|
|
728
782
|
resolve: async (c: hono_Context, token: string) => {
|
|
729
783
|
const tokenHash = ApiKey.hash(token)
|
|
730
784
|
const existing = requests.get(c)
|
|
731
785
|
if (existing?.tokenHash === tokenHash) return existing.apiKey
|
|
732
786
|
const cached = await cache.resolve(c, token)
|
|
733
|
-
const
|
|
734
|
-
const apiKey =
|
|
735
|
-
cached &&
|
|
736
|
-
((kv && (await ApiKeys.isOwnerDeleted(kv.store, cached))) ||
|
|
737
|
-
!(await apiKeyOwnerExists(cached, options.db)))
|
|
738
|
-
? null
|
|
739
|
-
: cached
|
|
787
|
+
const apiKey = await active(c, token, cached)
|
|
740
788
|
if (cached && !apiKey) cache.invalidate(token)
|
|
741
789
|
requests.set(c, { apiKey, tokenHash })
|
|
742
790
|
return apiKey
|
|
@@ -744,15 +792,6 @@ function createApiKeyResolver(options: ApiKeyResolverOptions) {
|
|
|
744
792
|
}
|
|
745
793
|
}
|
|
746
794
|
|
|
747
|
-
/** Rejects attributed keys fenced by a committed owner deletion. */
|
|
748
|
-
async function apiKeyOwnerExists(apiKey: ApiKey.ApiKey, source: Db.Source | undefined) {
|
|
749
|
-
if (!source) return true
|
|
750
|
-
const db = Db.get(source)
|
|
751
|
-
if (!(await ApiKeyAdmissions.matches(db, apiKey))) return false
|
|
752
|
-
if (await ApiKeyOwnerTombstones.isDeleted(db, apiKey)) return false
|
|
753
|
-
return true
|
|
754
|
-
}
|
|
755
|
-
|
|
756
795
|
export declare namespace middleware {
|
|
757
796
|
/** Per-route policy overrides keyed by HTTP endpoint. */
|
|
758
797
|
type Overrides<endpoint extends string = string> = Partial<
|
|
@@ -792,8 +831,8 @@ export declare namespace middleware {
|
|
|
792
831
|
}
|
|
793
832
|
| false
|
|
794
833
|
| undefined
|
|
795
|
-
/** Rate-limit store options. */
|
|
796
|
-
rateLimit?: RateLimit.memory.Options | undefined
|
|
834
|
+
/** Rate-limit store, or options for the counter-backed default. */
|
|
835
|
+
rateLimit?: RateLimit.memory.Options | RateLimit.Store | undefined
|
|
797
836
|
/** Scope catalog accepted while resolving API-key records. */
|
|
798
837
|
scopeCatalog?: Scope.Catalog | undefined
|
|
799
838
|
/** Session lane resolution — the session surface's capability; omit to leave the session lane closed. */
|
|
@@ -973,7 +1012,7 @@ export function install(options: install.Options) {
|
|
|
973
1012
|
get email() {
|
|
974
1013
|
return options.email()
|
|
975
1014
|
},
|
|
976
|
-
rateLimit:
|
|
1015
|
+
rateLimit: rateLimitStore(options_middleware.rateLimit),
|
|
977
1016
|
secret: options_session.secret,
|
|
978
1017
|
...(options_session.google ? { google: options_session.google } : {}),
|
|
979
1018
|
...(options_session.trustedOrigins
|
|
@@ -1019,9 +1058,12 @@ export function install(options: install.Options) {
|
|
|
1019
1058
|
return value === null ? undefined : (JSON.parse(value) as never)
|
|
1020
1059
|
},
|
|
1021
1060
|
async set(key, value, options) {
|
|
1061
|
+
const payload = key.startsWith('session:')
|
|
1062
|
+
? { ...(value as WalletSession), ...(await bindWalletSession(value as WalletSession)) }
|
|
1063
|
+
: value
|
|
1022
1064
|
await kv.store.put(
|
|
1023
1065
|
`auth:${key}`,
|
|
1024
|
-
JSON.stringify(
|
|
1066
|
+
JSON.stringify(payload),
|
|
1025
1067
|
options?.ttl ? { ttl: options.ttl * 1_000 } : {},
|
|
1026
1068
|
)
|
|
1027
1069
|
},
|
|
@@ -1064,8 +1106,46 @@ export function install(options: install.Options) {
|
|
|
1064
1106
|
})
|
|
1065
1107
|
}
|
|
1066
1108
|
|
|
1109
|
+
async function bindWalletSession(payload: WalletSession) {
|
|
1110
|
+
const user = await resolveWallet(payload)
|
|
1111
|
+
if (!user) throw new Error('Authenticated wallet user was not found')
|
|
1112
|
+
if (!user.user.termsSharedAt) await Users.recordTermsShared(Db.get(db), user.user.id)
|
|
1113
|
+
return { email: user.email, userId: user.user.id }
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
async function resolveWalletSession(payload: WalletSession) {
|
|
1117
|
+
// Legacy sessions cannot be safely rebound after an email or wallet reassignment.
|
|
1118
|
+
if (!payload.userId) return null
|
|
1119
|
+
const database = Db.get(db)
|
|
1120
|
+
const [user, linkedUserId] = await Promise.all([
|
|
1121
|
+
Users.get(database, payload.userId),
|
|
1122
|
+
AuthAccounts.getWalletUserId(database, payload.address),
|
|
1123
|
+
])
|
|
1124
|
+
if (!user || linkedUserId !== payload.userId) return null
|
|
1125
|
+
if (payload.email && (user.email !== payload.email || !user.emailVerified)) return null
|
|
1126
|
+
return { email: user.emailVerified ? user.email : undefined, user }
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
// CLI sessions act as the approving user; the principal's identity names the
|
|
1130
|
+
// CLI session so handlers never mistake it for a wallet sign-in.
|
|
1131
|
+
const resolveCli = async (token: string): Promise<SessionPrincipal | null> => {
|
|
1132
|
+
const record = await CliAuth.resolve(kv.store, token)
|
|
1133
|
+
if (!record) return null
|
|
1134
|
+
const user = await Users.get(Db.get(db), record.userId)
|
|
1135
|
+
if (!user) return null
|
|
1136
|
+
return {
|
|
1137
|
+
cli: { expiresAt: record.expiresAt, scopes: record.scopes ?? [] },
|
|
1138
|
+
...(user.emailVerified && user.email ? { email: user.email } : {}),
|
|
1139
|
+
id: user.id,
|
|
1140
|
+
identity: { provider: 'cli', subject: record.id },
|
|
1141
|
+
type: 'session',
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1067
1145
|
const session: Session = {
|
|
1068
1146
|
resolve: async (c) => {
|
|
1147
|
+
const bearer = /^Bearer\s+(.+)$/i.exec(c.req.header('authorization') ?? '')?.[1]
|
|
1148
|
+
if (bearer && CliAuth.isToken(bearer)) return resolveCli(bearer)
|
|
1069
1149
|
const [betterAuth, identitySession, wallet] = await Promise.all([
|
|
1070
1150
|
(async () => {
|
|
1071
1151
|
const auth = BetterAuth.fromContext(c, options_betterAuth)
|
|
@@ -1097,7 +1177,7 @@ export function install(options: install.Options) {
|
|
|
1097
1177
|
if (value === null) return null
|
|
1098
1178
|
const payload = JSON.parse(value) as IdentitySession
|
|
1099
1179
|
if (payload.expiresAt <= Math.floor(Date.now() / 1_000)) return null
|
|
1100
|
-
const user = await
|
|
1180
|
+
const user = await resolveWalletSession(payload)
|
|
1101
1181
|
if (!user) return null
|
|
1102
1182
|
return {
|
|
1103
1183
|
...(user.email ? { email: user.email } : {}),
|
|
@@ -1109,7 +1189,7 @@ export function install(options: install.Options) {
|
|
|
1109
1189
|
(async () => {
|
|
1110
1190
|
const payload = await handler.getSession(c.req.raw)
|
|
1111
1191
|
if (!payload) return null
|
|
1112
|
-
const user = await
|
|
1192
|
+
const user = await resolveWalletSession(payload)
|
|
1113
1193
|
if (!user) return null
|
|
1114
1194
|
return {
|
|
1115
1195
|
...(user.email ? { email: user.email } : {}),
|
|
@@ -1130,6 +1210,11 @@ export function install(options: install.Options) {
|
|
|
1130
1210
|
const describe = OpenApi.describeRoute({ hide: true })
|
|
1131
1211
|
|
|
1132
1212
|
const app = new Hono<App.Environment>()
|
|
1213
|
+
.use('*', async (c, next) => {
|
|
1214
|
+
await next()
|
|
1215
|
+
c.header('Tempo-Terms-URL', termsUrl)
|
|
1216
|
+
c.header('Tempo-Privacy-URL', privacyUrl)
|
|
1217
|
+
})
|
|
1133
1218
|
.use('/v1/auth/siwe', policy_public, describe)
|
|
1134
1219
|
.use('/v1/auth/siwe/*', policy_public, describe)
|
|
1135
1220
|
// Documented operations: pre-routes carrying the OpenAPI metadata and the
|
|
@@ -1245,13 +1330,14 @@ export function install(options: install.Options) {
|
|
|
1245
1330
|
|
|
1246
1331
|
const address = Address.checksum(claims.subject)
|
|
1247
1332
|
await Users.upsertByAddress(Db.get(db), { address })
|
|
1333
|
+
const binding = await bindWalletSession({ address, email: claims.email })
|
|
1248
1334
|
const issuedAt = Math.floor(Date.now() / 1_000)
|
|
1249
1335
|
const token = Hex.fromBytes(crypto.getRandomValues(new Uint8Array(32))).slice(2)
|
|
1250
1336
|
await kv.store.put(
|
|
1251
1337
|
identitySessionKey(token),
|
|
1252
1338
|
JSON.stringify({
|
|
1253
1339
|
address,
|
|
1254
|
-
...
|
|
1340
|
+
...binding,
|
|
1255
1341
|
expiresAt: issuedAt + identitySessionTtl,
|
|
1256
1342
|
issuedAt,
|
|
1257
1343
|
} satisfies IdentitySession),
|
|
@@ -1273,10 +1359,14 @@ export function install(options: install.Options) {
|
|
|
1273
1359
|
createMiddleware<App.Environment>(async (c, next) => {
|
|
1274
1360
|
const auth = c.get('auth')
|
|
1275
1361
|
const principal = principalFromPublic(c, auth)
|
|
1276
|
-
const result = await
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1362
|
+
const result = await Timing.time(c as never, 'rate_limit', () =>
|
|
1363
|
+
consumeRateLimit(auth, {
|
|
1364
|
+
key: `public:${principal.id}`,
|
|
1365
|
+
limit: auth.publicRateLimit ?? defaultPublicRateLimit,
|
|
1366
|
+
principal: `public:${principal.id}`,
|
|
1367
|
+
waitUntil: ExecutionContext.waitUntil(c),
|
|
1368
|
+
}),
|
|
1369
|
+
)
|
|
1280
1370
|
if (result) {
|
|
1281
1371
|
setRateLimitHeaders(c, result)
|
|
1282
1372
|
if (!result.allowed) return rateLimitExceeded(c, result)
|
|
@@ -1286,7 +1376,8 @@ export function install(options: install.Options) {
|
|
|
1286
1376
|
return undefined
|
|
1287
1377
|
}),
|
|
1288
1378
|
OpenApi.describeRoute({
|
|
1289
|
-
description:
|
|
1379
|
+
description:
|
|
1380
|
+
'Revokes auth sessions and clears their cookies. A CLI session sent as `Authorization: Bearer` is revoked on its own.',
|
|
1290
1381
|
hide: false,
|
|
1291
1382
|
operationId: 'logout',
|
|
1292
1383
|
responses: {
|
|
@@ -1298,6 +1389,21 @@ export function install(options: install.Options) {
|
|
|
1298
1389
|
tags: ['Authentication'],
|
|
1299
1390
|
}),
|
|
1300
1391
|
async (c) => {
|
|
1392
|
+
// A CLI session carries only its bearer token; revoke it and leave browser sessions alone.
|
|
1393
|
+
const bearer = /^Bearer\s+(.+)$/i.exec(c.req.header('authorization') ?? '')?.[1]
|
|
1394
|
+
if (bearer && CliAuth.isToken(bearer)) {
|
|
1395
|
+
try {
|
|
1396
|
+
await CliAuth.revoke(kv.store, bearer)
|
|
1397
|
+
} catch (cause) {
|
|
1398
|
+
c.error = cause instanceof Error ? cause : new Error('CLI logout failed', { cause })
|
|
1399
|
+
return Response.error(c, {
|
|
1400
|
+
code: 'session_logout_failed',
|
|
1401
|
+
message: 'Session logout failed',
|
|
1402
|
+
status: 500,
|
|
1403
|
+
})
|
|
1404
|
+
}
|
|
1405
|
+
return c.body(null, 204)
|
|
1406
|
+
}
|
|
1301
1407
|
const walletHeaders = (() => {
|
|
1302
1408
|
const authorization = c.req.header('authorization')
|
|
1303
1409
|
const cookie = c.req.header('cookie')
|
|
@@ -1394,7 +1500,7 @@ export function install(options: install.Options) {
|
|
|
1394
1500
|
Metadata.attach(app, {
|
|
1395
1501
|
securitySchemes: {
|
|
1396
1502
|
session: {
|
|
1397
|
-
description: 'Session cookie established by email OTP, Wallet identity, or SIWE sign-in. Browsers send `tempo_auth.session_token`, `tempo_identity`, or `accounts_auth`; Accounts sessions may also use `Authorization: Bearer <token
|
|
1503
|
+
description: 'Session cookie established by email OTP, Wallet identity, or SIWE sign-in. Browsers send `tempo_auth.session_token`, `tempo_identity`, or `accounts_auth`; Accounts sessions may also use `Authorization: Bearer <token>`, and CLI sessions always use `Authorization: Bearer tempo:cli:…`.', // prettier-ignore
|
|
1398
1504
|
in: 'header',
|
|
1399
1505
|
name: 'Cookie',
|
|
1400
1506
|
type: 'apiKey',
|
|
@@ -1408,7 +1514,6 @@ export function install(options: install.Options) {
|
|
|
1408
1514
|
|
|
1409
1515
|
const resolve = createApiKeyResolver({
|
|
1410
1516
|
apiKey: options_middleware.apiKey,
|
|
1411
|
-
db: options.db,
|
|
1412
1517
|
scopeCatalog,
|
|
1413
1518
|
})
|
|
1414
1519
|
const defaults = laneDefaults(options_middleware)
|
|
@@ -1421,14 +1526,17 @@ export function install(options: install.Options) {
|
|
|
1421
1526
|
|
|
1422
1527
|
return createMiddleware(async (c, next) => {
|
|
1423
1528
|
const credential = getApiKeyCredential(c)
|
|
1529
|
+
recordCredential(c, credential)
|
|
1424
1530
|
const resolved = resolveRequestPolicy(c, { base, defaults, options: options_middleware })
|
|
1425
1531
|
const isSuperAdmin =
|
|
1426
1532
|
credential &&
|
|
1427
1533
|
superAdminTokenHash !== undefined &&
|
|
1428
1534
|
ApiKey.hash(credential.token) === superAdminTokenHash
|
|
1535
|
+
// CLI session tokens are never API keys, so they skip key resolution here too.
|
|
1429
1536
|
const canUseApiKeyQuota =
|
|
1430
1537
|
credential &&
|
|
1431
1538
|
!isSuperAdmin &&
|
|
1539
|
+
!CliAuth.isToken(credential.token) &&
|
|
1432
1540
|
!hasPaymentCredential(c) &&
|
|
1433
1541
|
options_middleware.apiKey !== false &&
|
|
1434
1542
|
resolved?.policy?.apiKey &&
|
|
@@ -1437,10 +1545,24 @@ export function install(options: install.Options) {
|
|
|
1437
1545
|
if (cached) return next()
|
|
1438
1546
|
|
|
1439
1547
|
const response = await Timing.time(c, 'edge_rate_limit', () =>
|
|
1440
|
-
options_edgeRateLimit(
|
|
1548
|
+
options_edgeRateLimit(
|
|
1549
|
+
c.req.raw,
|
|
1550
|
+
canUseApiKeyQuota
|
|
1551
|
+
? {
|
|
1552
|
+
resolvePartition: async () => {
|
|
1553
|
+
const apiKey =
|
|
1554
|
+
cached === undefined ? await resolve.probe(c, credential.token) : cached
|
|
1555
|
+
// Rotating invalid credentials stays in the anonymous transport bucket.
|
|
1556
|
+
return apiKey ? `api-key:${ApiKey.hash(credential.token)}` : undefined
|
|
1557
|
+
},
|
|
1558
|
+
}
|
|
1559
|
+
: {},
|
|
1560
|
+
),
|
|
1441
1561
|
)
|
|
1442
1562
|
if (response) return response
|
|
1443
|
-
|
|
1563
|
+
// Cold keys resolve here, ahead of the auth lane, so time both under one name.
|
|
1564
|
+
if (canUseApiKeyQuota && cached === undefined)
|
|
1565
|
+
await Timing.sum(c as never, 'auth_key', () => resolve.resolve(c, credential.token))
|
|
1444
1566
|
return next()
|
|
1445
1567
|
})
|
|
1446
1568
|
})()
|
|
@@ -1612,7 +1734,9 @@ export function installMppManagementRoutes(
|
|
|
1612
1734
|
if (postPaths.has(target.path))
|
|
1613
1735
|
throw new Error(`MPP management POST conflicts with an existing route: ${target.path}`)
|
|
1614
1736
|
|
|
1615
|
-
const management = policy({
|
|
1737
|
+
const management = policy({
|
|
1738
|
+
mpp: { session: mpp.session },
|
|
1739
|
+
}) as MiddlewareHandler & MppManagementHandler
|
|
1616
1740
|
management[mppManagementSymbol] = { description: target.description }
|
|
1617
1741
|
app.post(
|
|
1618
1742
|
stripBasePath(target.path, options.basePath),
|
|
@@ -1776,6 +1900,7 @@ function resolveApiKeyLane(
|
|
|
1776
1900
|
if (override === true) return current ?? default_
|
|
1777
1901
|
const base = current ?? default_
|
|
1778
1902
|
return {
|
|
1903
|
+
bucket: override.bucket ?? base.bucket,
|
|
1779
1904
|
rateLimit: override.rateLimit ?? base.rateLimit,
|
|
1780
1905
|
scopes: override.scopes ?? base.scopes,
|
|
1781
1906
|
}
|
|
@@ -1791,6 +1916,7 @@ function resolveMppLane(
|
|
|
1791
1916
|
if (override === true) return current ?? default_
|
|
1792
1917
|
const base = current ?? default_
|
|
1793
1918
|
return {
|
|
1919
|
+
bucket: override.bucket ?? base.bucket,
|
|
1794
1920
|
rateLimit: override.rateLimit ?? base.rateLimit,
|
|
1795
1921
|
session: { ...base.session, ...override.session },
|
|
1796
1922
|
}
|
|
@@ -1805,7 +1931,10 @@ function resolvePublicLane(
|
|
|
1805
1931
|
if (override === false) return undefined
|
|
1806
1932
|
if (override === true) return current ?? default_
|
|
1807
1933
|
const base = current ?? default_
|
|
1808
|
-
return {
|
|
1934
|
+
return {
|
|
1935
|
+
bucket: override.bucket ?? base.bucket,
|
|
1936
|
+
rateLimit: override.rateLimit ?? base.rateLimit,
|
|
1937
|
+
}
|
|
1809
1938
|
}
|
|
1810
1939
|
|
|
1811
1940
|
function resolveSessionLane(
|
|
@@ -1974,6 +2103,7 @@ export function require<environment extends Environment = Environment>(
|
|
|
1974
2103
|
return createMiddleware<environment>(async (c, next) => {
|
|
1975
2104
|
const auth = c.get('auth')
|
|
1976
2105
|
const credential = getApiKeyCredential(c)
|
|
2106
|
+
recordCredential(c, credential)
|
|
1977
2107
|
const hasQueryApiKey = new URL(c.req.url).searchParams.has('key')
|
|
1978
2108
|
// Auth owns `key`; strict route schemas must not validate it.
|
|
1979
2109
|
stripApiKeyQuery(c)
|
|
@@ -2027,7 +2157,11 @@ export function require<environment extends Environment = Environment>(
|
|
|
2027
2157
|
return proceed()
|
|
2028
2158
|
}
|
|
2029
2159
|
|
|
2030
|
-
|
|
2160
|
+
// CLI session tokens are prefixed, so they skip the API-key lookup.
|
|
2161
|
+
const cliToken = CliAuth.isToken(credential.token)
|
|
2162
|
+
const apiKey_resolved = cliToken
|
|
2163
|
+
? null
|
|
2164
|
+
: await Timing.sum(c as never, 'auth_key', () => auth.apiKey?.resolve(c, credential.token))
|
|
2031
2165
|
if (!apiKey_resolved) {
|
|
2032
2166
|
if (unsupportedChain)
|
|
2033
2167
|
return Response.unsupportedChainId(
|
|
@@ -2045,6 +2179,21 @@ export function require<environment extends Environment = Environment>(
|
|
|
2045
2179
|
return proceed()
|
|
2046
2180
|
}
|
|
2047
2181
|
}
|
|
2182
|
+
if (cliToken)
|
|
2183
|
+
return jsonError(
|
|
2184
|
+
c,
|
|
2185
|
+
policy.session
|
|
2186
|
+
? {
|
|
2187
|
+
code: 'session_invalid',
|
|
2188
|
+
message: 'CLI session is invalid or expired. Sign in again.',
|
|
2189
|
+
status: 401,
|
|
2190
|
+
}
|
|
2191
|
+
: {
|
|
2192
|
+
code: 'forbidden',
|
|
2193
|
+
message: 'CLI sessions cannot call this route. Use an API key.',
|
|
2194
|
+
status: 403,
|
|
2195
|
+
},
|
|
2196
|
+
)
|
|
2048
2197
|
return jsonError(c, {
|
|
2049
2198
|
code: 'api_key_invalid',
|
|
2050
2199
|
message: 'Invalid API key',
|
|
@@ -2085,12 +2234,17 @@ export function require<environment extends Environment = Environment>(
|
|
|
2085
2234
|
? (policy.public?.rateLimit ?? auth.publicRateLimit ?? { limit: 60, period: 'minute' })
|
|
2086
2235
|
: resolveApiKeyLimit({ apiKey, auth, policy: policy.apiKey, scope })
|
|
2087
2236
|
const paid = hasPayment && !throttled
|
|
2237
|
+
const bucket = policy.apiKey.bucket
|
|
2088
2238
|
const result = paid
|
|
2089
2239
|
? null
|
|
2090
|
-
: await
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2240
|
+
: await Timing.time(c as never, 'rate_limit', () =>
|
|
2241
|
+
consumeRateLimit(auth, {
|
|
2242
|
+
key: rateLimitKey(`api_key:${apiKey.id}:scope:${scope}`, bucket),
|
|
2243
|
+
limit,
|
|
2244
|
+
principal: `api_key:${apiKey.id}`,
|
|
2245
|
+
waitUntil: ExecutionContext.waitUntil(c),
|
|
2246
|
+
}),
|
|
2247
|
+
)
|
|
2094
2248
|
if (result) {
|
|
2095
2249
|
setRateLimitHeaders(c, result)
|
|
2096
2250
|
// Surface the bucket so callers can correlate a 429 with the exhausted
|
|
@@ -2135,7 +2289,7 @@ export function require<environment extends Environment = Environment>(
|
|
|
2135
2289
|
if (missing.length > 0)
|
|
2136
2290
|
return jsonError(c, {
|
|
2137
2291
|
code: 'api_key_forbidden',
|
|
2138
|
-
message:
|
|
2292
|
+
message: `API key is missing required permissions: ${missing.join(', ')}. Use an API key with these scopes.`,
|
|
2139
2293
|
status: 403,
|
|
2140
2294
|
})
|
|
2141
2295
|
|
|
@@ -2187,10 +2341,14 @@ export function require<environment extends Environment = Environment>(
|
|
|
2187
2341
|
|
|
2188
2342
|
const limit = policy.public?.rateLimit
|
|
2189
2343
|
if (limit) {
|
|
2190
|
-
const result = await
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2344
|
+
const result = await Timing.time(c as never, 'rate_limit', () =>
|
|
2345
|
+
consumeRateLimit(auth, {
|
|
2346
|
+
key: rateLimitKey(`public:${publicPrincipal.id}`, policy.public?.bucket),
|
|
2347
|
+
limit,
|
|
2348
|
+
principal: `public:${publicPrincipal.id}`,
|
|
2349
|
+
waitUntil: ExecutionContext.waitUntil(c),
|
|
2350
|
+
}),
|
|
2351
|
+
)
|
|
2194
2352
|
if (result) setRateLimitHeaders(c, result)
|
|
2195
2353
|
if (!result || result.allowed) {
|
|
2196
2354
|
c.set('principal', publicPrincipal)
|
|
@@ -2231,6 +2389,8 @@ export declare namespace require {
|
|
|
2231
2389
|
/** API-key access policy. */
|
|
2232
2390
|
apiKey?:
|
|
2233
2391
|
| {
|
|
2392
|
+
/** Optional counter bucket that isolates this route's quota. */
|
|
2393
|
+
bucket?: string | undefined
|
|
2234
2394
|
/** API-key quota override for this route (a protective per-route cap). */
|
|
2235
2395
|
rateLimit?: RateLimit.Limit | undefined
|
|
2236
2396
|
/**
|
|
@@ -2244,6 +2404,8 @@ export declare namespace require {
|
|
|
2244
2404
|
/** MPP payment access policy. */
|
|
2245
2405
|
mpp?:
|
|
2246
2406
|
| {
|
|
2407
|
+
/** Optional counter bucket that isolates this route's quota. */
|
|
2408
|
+
bucket?: string | undefined
|
|
2247
2409
|
/** Paid-request quota override for this route (a protective per-route cap). */
|
|
2248
2410
|
rateLimit?: RateLimit.Limit | undefined
|
|
2249
2411
|
/** Tempo Session request policy. */
|
|
@@ -2253,6 +2415,8 @@ export declare namespace require {
|
|
|
2253
2415
|
/** Public access policy. */
|
|
2254
2416
|
public?:
|
|
2255
2417
|
| {
|
|
2418
|
+
/** Optional counter bucket that isolates this route's quota. */
|
|
2419
|
+
bucket?: string | undefined
|
|
2256
2420
|
/** Anonymous public quota for this route. */
|
|
2257
2421
|
rateLimit: RateLimit.Limit
|
|
2258
2422
|
}
|
|
@@ -2287,6 +2451,11 @@ type RateLimitAccess = PaymentAccess & {
|
|
|
2287
2451
|
*/
|
|
2288
2452
|
const rateLimitConsumeTimeout = 300
|
|
2289
2453
|
|
|
2454
|
+
/** Accepts a ready store or builds the counter-backed default from its options. */
|
|
2455
|
+
function rateLimitStore(options: RateLimit.memory.Options | RateLimit.Store | undefined) {
|
|
2456
|
+
return options && 'consume' in options ? options : RateLimit.memory(options)
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2290
2459
|
/** Consumes one quota and returns null when its counter is unavailable, allowing callers to fail open. */
|
|
2291
2460
|
export function consumeRateLimit(
|
|
2292
2461
|
auth: Context,
|
|
@@ -2396,12 +2565,22 @@ function getApiKeyCredential(c: hono_Context): ApiKeyCredential | false | null {
|
|
|
2396
2565
|
return null
|
|
2397
2566
|
}
|
|
2398
2567
|
|
|
2568
|
+
// Recorded before any lookup: requests that stall or are canceled during
|
|
2569
|
+
// resolution never receive a principal, but still need caller attribution.
|
|
2570
|
+
function recordCredential(c: hono_Context, credential: ApiKeyCredential | false | null) {
|
|
2571
|
+
if (credential) c.set('credential', 'api_key')
|
|
2572
|
+
else if (hasPaymentCredential(c)) c.set('credential', 'payment')
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2399
2575
|
function clientIp(c: hono_Context, auth: Context): string | undefined {
|
|
2400
|
-
return
|
|
2576
|
+
return (
|
|
2577
|
+
trustedClientIps.get(c.req.raw) ??
|
|
2578
|
+
(auth.publicClientIp ? auth.publicClientIp(c.req.raw) : c.req.header('cf-connecting-ip'))
|
|
2579
|
+
)
|
|
2401
2580
|
}
|
|
2402
2581
|
|
|
2403
2582
|
function trustedClientIp(c: hono_Context, auth: Context): string | undefined {
|
|
2404
|
-
return resolveTrustedClientIp(c.req.raw, auth.publicClientIp)
|
|
2583
|
+
return trustedClientIps.get(c.req.raw) ?? resolveTrustedClientIp(c.req.raw, auth.publicClientIp)
|
|
2405
2584
|
}
|
|
2406
2585
|
|
|
2407
2586
|
function resolveTrustedClientIp(
|
|
@@ -2543,10 +2722,17 @@ async function requirePayment<environment extends Environment>(
|
|
|
2543
2722
|
options: PaymentAccess,
|
|
2544
2723
|
) {
|
|
2545
2724
|
if (hasPaymentCredential(c)) {
|
|
2546
|
-
const result = await
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2725
|
+
const result = await Timing.time(c as never, 'rate_limit', () =>
|
|
2726
|
+
consumeRateLimit(options.auth, {
|
|
2727
|
+
key: rateLimitKey(
|
|
2728
|
+
`mpp:${options.principal.type}:${options.principal.id}`,
|
|
2729
|
+
options.policy.mpp?.bucket,
|
|
2730
|
+
),
|
|
2731
|
+
limit: options.policy.mpp?.rateLimit ?? options.auth.mpp?.rateLimit ?? defaultMppRateLimit,
|
|
2732
|
+
principal: `mpp:${options.principal.type}:${options.principal.id}`,
|
|
2733
|
+
waitUntil: ExecutionContext.waitUntil(c),
|
|
2734
|
+
}),
|
|
2735
|
+
)
|
|
2550
2736
|
if (result) {
|
|
2551
2737
|
setRateLimitHeaders(c, result)
|
|
2552
2738
|
c.header('RateLimit-Scope', 'mpp')
|
|
@@ -2601,6 +2787,10 @@ function requirePaymentOrRateLimit<environment extends Environment>(
|
|
|
2601
2787
|
return rateLimitExceeded(c, options.rateLimit)
|
|
2602
2788
|
}
|
|
2603
2789
|
|
|
2790
|
+
function rateLimitKey(key: string, bucket: string | undefined) {
|
|
2791
|
+
return bucket === undefined ? key : `${key}:bucket:${bucket}`
|
|
2792
|
+
}
|
|
2793
|
+
|
|
2604
2794
|
/** Emits a `429` with a `Retry-After` derived from the window reset. */
|
|
2605
2795
|
function rateLimitExceeded(c: hono_Context, result: RateLimit.Result) {
|
|
2606
2796
|
c.header('Retry-After', String(Math.max(result.reset - Math.ceil(Date.now() / 1_000), 1)))
|
|
@@ -2648,22 +2838,16 @@ async function resolveSession(c: hono_Context, auth: Context): Promise<SessionPr
|
|
|
2648
2838
|
const cachedMaxEntries = 10_000
|
|
2649
2839
|
|
|
2650
2840
|
/**
|
|
2651
|
-
*
|
|
2652
|
-
*
|
|
2653
|
-
* (default 60s), negative for `negativeTtl` (default 10s) so a freshly minted
|
|
2654
|
-
* key is usable quickly; concurrent misses for one token are single-flighted.
|
|
2655
|
-
* Entries are keyed by the token's sha256 (`ApiKey.hash`) — never the
|
|
2656
|
-
* plaintext. Key updates may remain stale for up to `ttl`, the accepted
|
|
2657
|
-
* trade-off for removing a backend read from the auth path.
|
|
2841
|
+
* Caches completed resolutions per isolate by token hash, with positive and negative TTLs.
|
|
2842
|
+
* Each miss resolves independently so callers never await another request's pending I/O.
|
|
2658
2843
|
*/
|
|
2659
|
-
function cachedResolve(
|
|
2844
|
+
export function cachedResolve(
|
|
2660
2845
|
resolve: (c: hono_Context, token: string) => Promise<ApiKey.ApiKey | null>,
|
|
2661
2846
|
options: middleware.Cache,
|
|
2662
2847
|
) {
|
|
2663
2848
|
const { negativeTtl = 10_000, now = Date.now, ttl = 60_000 } = options
|
|
2664
2849
|
type Cell = { expiresAt: number; value: ApiKey.ApiKey | null }
|
|
2665
2850
|
const cells = new Map<string, Cell>()
|
|
2666
|
-
const flights = new Map<string, Promise<ApiKey.ApiKey | null>>()
|
|
2667
2851
|
|
|
2668
2852
|
return {
|
|
2669
2853
|
invalidate(token: string) {
|
|
@@ -2684,27 +2868,16 @@ function cachedResolve(
|
|
|
2684
2868
|
if (cell && cell.expiresAt > now()) return cell.value
|
|
2685
2869
|
if (cell) cells.delete(key)
|
|
2686
2870
|
|
|
2687
|
-
const
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
const
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
if (cells.size >= cachedMaxEntries) {
|
|
2695
|
-
const time = now()
|
|
2696
|
-
for (const [name, entry] of cells) if (entry.expiresAt <= time) cells.delete(name)
|
|
2697
|
-
while (cells.size >= cachedMaxEntries) cells.delete(cells.keys().next().value as string)
|
|
2698
|
-
}
|
|
2699
|
-
cells.set(key, { expiresAt: now() + (value ? ttl : negativeTtl), value })
|
|
2700
|
-
return value
|
|
2701
|
-
})()
|
|
2702
|
-
flights.set(key, flight)
|
|
2703
|
-
try {
|
|
2704
|
-
return await flight
|
|
2705
|
-
} finally {
|
|
2706
|
-
flights.delete(key)
|
|
2871
|
+
const value = await resolve(c, token)
|
|
2872
|
+
// Bound the cache: random invalid tokens each add a (negative) entry,
|
|
2873
|
+
// so sweep expired cells at the cap and then drop the oldest.
|
|
2874
|
+
if (cells.size >= cachedMaxEntries) {
|
|
2875
|
+
const time = now()
|
|
2876
|
+
for (const [name, entry] of cells) if (entry.expiresAt <= time) cells.delete(name)
|
|
2877
|
+
while (cells.size >= cachedMaxEntries) cells.delete(cells.keys().next().value as string)
|
|
2707
2878
|
}
|
|
2879
|
+
cells.set(key, { expiresAt: now() + (value ? ttl : negativeTtl), value })
|
|
2880
|
+
return value
|
|
2708
2881
|
},
|
|
2709
2882
|
}
|
|
2710
2883
|
}
|