tapimo 0.0.2 → 0.2.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 +38 -16
- package/dist/ApiKey.d.ts +14 -11
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +11 -12
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +207 -0
- package/dist/ApiKeys.d.ts.map +1 -0
- package/dist/ApiKeys.js +282 -0
- package/dist/ApiKeys.js.map +1 -0
- package/dist/App.d.ts +6771 -3819
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +145 -317
- package/dist/App.js.map +1 -1
- package/dist/Handler.d.ts +86 -0
- package/dist/Handler.d.ts.map +1 -0
- package/dist/Handler.js +83 -0
- package/dist/Handler.js.map +1 -0
- package/dist/Scope.d.ts +14 -4
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +16 -4
- package/dist/Scope.js.map +1 -1
- package/dist/Webhooks.d.ts +5 -7
- package/dist/Webhooks.d.ts.map +1 -1
- package/dist/Webhooks.js +11 -4
- package/dist/Webhooks.js.map +1 -1
- package/dist/admin/Access.d.ts +1 -3
- package/dist/admin/Access.d.ts.map +1 -1
- package/dist/admin/Access.js +1 -3
- package/dist/admin/Access.js.map +1 -1
- package/dist/admin/App.d.ts +167 -205
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +2 -4
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +105 -5
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +75 -9
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/scopes.d.ts +6 -0
- package/dist/admin/apps/scopes.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.d.ts +35 -149
- package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
- package/dist/admin/apps/verified-tokens.js +18 -39
- package/dist/admin/apps/verified-tokens.js.map +1 -1
- package/dist/admin/ui.generated.d.ts +1 -1
- package/dist/admin/ui.generated.js +1 -1
- package/dist/apps/data/App.d.ts +19176 -0
- package/dist/apps/data/App.d.ts.map +1 -0
- package/dist/apps/data/App.js +236 -0
- package/dist/apps/data/App.js.map +1 -0
- package/dist/apps/data/index.d.ts +3 -0
- package/dist/apps/data/index.d.ts.map +1 -0
- package/dist/apps/data/index.js +3 -0
- package/dist/apps/data/index.js.map +1 -0
- package/dist/apps/{activities.d.ts → data/routes/activities.d.ts} +32 -32
- package/dist/apps/{activities.d.ts.map → data/routes/activities.d.ts.map} +1 -1
- package/dist/apps/{activities.js → data/routes/activities.js} +13 -13
- package/dist/apps/data/routes/activities.js.map +1 -0
- package/dist/apps/{addresses.d.ts → data/routes/addresses.d.ts} +22 -22
- package/dist/apps/{addresses.d.ts.map → data/routes/addresses.d.ts.map} +1 -1
- package/dist/apps/{addresses.js → data/routes/addresses.js} +5 -5
- package/dist/apps/data/routes/addresses.js.map +1 -0
- package/dist/apps/{balances.d.ts → data/routes/balances.d.ts} +49 -49
- package/dist/apps/data/routes/balances.d.ts.map +1 -0
- package/dist/apps/{balances.js → data/routes/balances.js} +42 -11
- package/dist/apps/data/routes/balances.js.map +1 -0
- package/dist/apps/{blocks.d.ts → data/routes/blocks.d.ts} +47 -47
- package/dist/apps/data/routes/blocks.d.ts.map +1 -0
- package/dist/apps/{blocks.js → data/routes/blocks.js} +13 -13
- package/dist/apps/data/routes/blocks.js.map +1 -0
- package/dist/apps/{coingecko.d.ts → data/routes/coingecko.d.ts} +183 -183
- package/dist/apps/data/routes/coingecko.d.ts.map +1 -0
- package/dist/apps/{coingecko.js → data/routes/coingecko.js} +13 -13
- package/dist/apps/data/routes/coingecko.js.map +1 -0
- package/dist/apps/{exchanges.d.ts → data/routes/exchanges.d.ts} +460 -460
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -0
- package/dist/apps/{exchanges.js → data/routes/exchanges.js} +19 -19
- package/dist/apps/data/routes/exchanges.js.map +1 -0
- package/dist/apps/{fee-amm.d.ts → data/routes/fee-amm.d.ts} +94 -94
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -0
- package/dist/apps/{fee-amm.js → data/routes/fee-amm.js} +17 -17
- package/dist/apps/data/routes/fee-amm.js.map +1 -0
- package/dist/apps/{indexer.d.ts → data/routes/indexer.d.ts} +4 -4
- package/dist/apps/data/routes/indexer.d.ts.map +1 -0
- package/dist/apps/{indexer.js → data/routes/indexer.js} +13 -9
- package/dist/apps/data/routes/indexer.js.map +1 -0
- package/dist/apps/{receipts.d.ts → data/routes/receipts.d.ts} +6 -6
- package/dist/apps/data/routes/receipts.d.ts.map +1 -0
- package/dist/apps/{receipts.js → data/routes/receipts.js} +12 -12
- package/dist/apps/data/routes/receipts.js.map +1 -0
- package/dist/apps/{rpc.d.ts → data/routes/rpc.d.ts} +4 -4
- package/dist/apps/data/routes/rpc.d.ts.map +1 -0
- package/dist/apps/{rpc.js → data/routes/rpc.js} +6 -6
- package/dist/apps/data/routes/rpc.js.map +1 -0
- package/dist/apps/{tokenlist.d.ts → data/routes/tokenlist.d.ts} +4 -4
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -0
- package/dist/apps/{tokenlist.js → data/routes/tokenlist.js} +8 -8
- package/dist/apps/data/routes/tokenlist.js.map +1 -0
- package/dist/apps/{tokens.d.ts → data/routes/tokens.d.ts} +11 -11
- package/dist/apps/data/routes/tokens.d.ts.map +1 -0
- package/dist/apps/{tokens.js → data/routes/tokens.js} +19 -19
- package/dist/apps/data/routes/tokens.js.map +1 -0
- package/dist/apps/{transactions.d.ts → data/routes/transactions.d.ts} +288 -288
- package/dist/apps/data/routes/transactions.d.ts.map +1 -0
- package/dist/apps/{transactions.js → data/routes/transactions.js} +13 -13
- package/dist/apps/data/routes/transactions.js.map +1 -0
- package/dist/apps/{transfers.d.ts → data/routes/transfers.d.ts} +35 -35
- package/dist/apps/data/routes/transfers.d.ts.map +1 -0
- package/dist/apps/{transfers.js → data/routes/transfers.js} +13 -13
- package/dist/apps/data/routes/transfers.js.map +1 -0
- package/dist/apps/{verified-tokens.d.ts → data/routes/verified-tokens.d.ts} +42 -42
- package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -0
- package/dist/apps/{verified-tokens.js → data/routes/verified-tokens.js} +9 -9
- package/dist/apps/data/routes/verified-tokens.js.map +1 -0
- package/dist/apps/{webhooks.d.ts → data/routes/webhooks.d.ts} +66 -63
- package/dist/apps/{webhooks.d.ts.map → data/routes/webhooks.d.ts.map} +1 -1
- package/dist/apps/{webhooks.js → data/routes/webhooks.js} +67 -59
- package/dist/apps/data/routes/webhooks.js.map +1 -0
- package/dist/apps/docs/App.d.ts +27 -0
- package/dist/apps/docs/App.d.ts.map +1 -0
- package/dist/apps/docs/App.js +122 -0
- package/dist/apps/docs/App.js.map +1 -0
- package/dist/{internal/OpenApi.fonts.d.ts → apps/docs/fonts.d.ts} +1 -1
- package/dist/apps/docs/fonts.d.ts.map +1 -0
- package/dist/{internal/OpenApi.fonts.js → apps/docs/fonts.js} +1 -1
- package/dist/apps/docs/fonts.js.map +1 -0
- package/dist/apps/docs/index.d.ts +2 -0
- package/dist/apps/docs/index.d.ts.map +1 -0
- package/dist/apps/docs/index.js +2 -0
- package/dist/apps/docs/index.js.map +1 -0
- package/dist/{internal/OpenApi.logo.d.ts → apps/docs/logo.d.ts} +1 -1
- package/dist/apps/docs/logo.d.ts.map +1 -0
- package/dist/{internal/OpenApi.logo.js → apps/docs/logo.js} +1 -1
- package/dist/apps/docs/logo.js.map +1 -0
- package/dist/apps/index.d.ts +4 -0
- package/dist/apps/index.d.ts.map +1 -0
- package/dist/apps/index.js +4 -0
- package/dist/apps/index.js.map +1 -0
- package/dist/apps/metadata.d.ts +7 -0
- package/dist/apps/metadata.d.ts.map +1 -0
- package/dist/apps/metadata.js +15 -0
- package/dist/apps/metadata.js.map +1 -0
- package/dist/apps/platform/App.d.ts +2985 -0
- package/dist/apps/platform/App.d.ts.map +1 -0
- package/dist/apps/platform/App.js +74 -0
- package/dist/apps/platform/App.js.map +1 -0
- package/dist/apps/platform/index.d.ts +2 -0
- package/dist/apps/platform/index.d.ts.map +1 -0
- package/dist/apps/platform/index.js +2 -0
- package/dist/apps/platform/index.js.map +1 -0
- package/dist/apps/platform/routes/api-keys.d.ts +681 -0
- package/dist/apps/platform/routes/api-keys.d.ts.map +1 -0
- package/dist/apps/platform/routes/api-keys.js +328 -0
- package/dist/apps/platform/routes/api-keys.js.map +1 -0
- package/dist/apps/platform/routes/invitations.d.ts +733 -0
- package/dist/apps/platform/routes/invitations.d.ts.map +1 -0
- package/dist/apps/platform/routes/invitations.js +413 -0
- package/dist/apps/platform/routes/invitations.js.map +1 -0
- package/dist/apps/platform/routes/me.d.ts +95 -0
- package/dist/apps/platform/routes/me.d.ts.map +1 -0
- package/dist/apps/platform/routes/me.js +81 -0
- package/dist/apps/platform/routes/me.js.map +1 -0
- package/dist/apps/platform/routes/members.d.ts +554 -0
- package/dist/apps/platform/routes/members.d.ts.map +1 -0
- package/dist/apps/platform/routes/members.js +251 -0
- package/dist/apps/platform/routes/members.js.map +1 -0
- package/dist/apps/platform/routes/orgs.d.ts +582 -0
- package/dist/apps/platform/routes/orgs.d.ts.map +1 -0
- package/dist/apps/platform/routes/orgs.js +265 -0
- package/dist/apps/platform/routes/orgs.js.map +1 -0
- package/dist/apps/platform/routes/projects.d.ts +740 -0
- package/dist/apps/platform/routes/projects.d.ts.map +1 -0
- package/dist/apps/platform/routes/projects.js +286 -0
- package/dist/apps/platform/routes/projects.js.map +1 -0
- package/dist/apps/relay/App.d.ts +41 -0
- package/dist/apps/relay/App.d.ts.map +1 -0
- package/dist/apps/relay/App.js +103 -0
- package/dist/apps/relay/App.js.map +1 -0
- package/dist/apps/relay/Sponsorships.d.ts +107 -0
- package/dist/apps/relay/Sponsorships.d.ts.map +1 -0
- package/dist/apps/relay/Sponsorships.js +193 -0
- package/dist/apps/relay/Sponsorships.js.map +1 -0
- package/dist/apps/relay/index.d.ts +3 -0
- package/dist/apps/relay/index.d.ts.map +1 -0
- package/dist/apps/relay/index.js +3 -0
- package/dist/apps/relay/index.js.map +1 -0
- package/dist/{Cli.d.ts → cli/Cli.d.ts} +13 -2
- package/dist/cli/Cli.d.ts.map +1 -0
- package/dist/cli/Cli.js +19 -0
- package/dist/cli/Cli.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +4 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/admin.d.ts +15 -0
- package/dist/cli/commands/admin.d.ts.map +1 -0
- package/dist/cli/commands/admin.js +60 -0
- package/dist/cli/commands/admin.js.map +1 -0
- package/dist/cloudflare.d.ts +7 -0
- package/dist/cloudflare.d.ts.map +1 -1
- package/dist/cloudflare.js +9 -0
- package/dist/cloudflare.js.map +1 -1
- package/dist/db/Db.d.ts +113 -0
- package/dist/db/Db.d.ts.map +1 -0
- package/dist/db/Db.js +402 -0
- package/dist/db/Db.js.map +1 -0
- package/dist/db/Schema.d.ts +168 -0
- package/dist/db/Schema.d.ts.map +1 -0
- package/dist/db/Schema.js +229 -0
- package/dist/db/Schema.js.map +1 -0
- package/dist/db/tables/invitations.d.ts +84 -0
- package/dist/db/tables/invitations.d.ts.map +1 -0
- package/dist/db/tables/invitations.js +165 -0
- package/dist/db/tables/invitations.js.map +1 -0
- package/dist/db/tables/memberships.d.ts +108 -0
- package/dist/db/tables/memberships.d.ts.map +1 -0
- package/dist/db/tables/memberships.js +153 -0
- package/dist/db/tables/memberships.js.map +1 -0
- package/dist/db/tables/organizations.d.ts +123 -0
- package/dist/db/tables/organizations.d.ts.map +1 -0
- package/dist/db/tables/organizations.js +170 -0
- package/dist/db/tables/organizations.js.map +1 -0
- package/dist/db/tables/projects.d.ts +65 -0
- package/dist/db/tables/projects.d.ts.map +1 -0
- package/dist/db/tables/projects.js +75 -0
- package/dist/db/tables/projects.js.map +1 -0
- package/dist/db/tables/sponsoredTransactions.d.ts +120 -0
- package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -0
- package/dist/db/tables/sponsoredTransactions.js +161 -0
- package/dist/db/tables/sponsoredTransactions.js.map +1 -0
- package/dist/db/tables/users.d.ts +48 -0
- package/dist/db/tables/users.d.ts.map +1 -0
- package/dist/db/tables/users.js +65 -0
- package/dist/db/tables/users.js.map +1 -0
- package/dist/db/tables/verifiedTokens.d.ts +53 -0
- package/dist/db/tables/verifiedTokens.d.ts.map +1 -0
- package/dist/db/tables/verifiedTokens.js +74 -0
- package/dist/db/tables/verifiedTokens.js.map +1 -0
- package/dist/db/tables/webhookDeliveries.d.ts +71 -0
- package/dist/db/tables/webhookDeliveries.d.ts.map +1 -0
- package/dist/db/tables/webhookDeliveries.js +119 -0
- package/dist/db/tables/webhookDeliveries.js.map +1 -0
- package/dist/db/tables/webhookSubscriptions.d.ts +158 -0
- package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -0
- package/dist/db/tables/webhookSubscriptions.js +272 -0
- package/dist/db/tables/webhookSubscriptions.js.map +1 -0
- package/dist/handlers/internal/executionError.d.ts +25 -0
- package/dist/handlers/internal/executionError.d.ts.map +1 -0
- package/dist/handlers/internal/executionError.js +186 -0
- package/dist/handlers/internal/executionError.js.map +1 -0
- package/dist/handlers/internal/multisig.d.ts +233 -0
- package/dist/handlers/internal/multisig.d.ts.map +1 -0
- package/dist/handlers/internal/multisig.js +542 -0
- package/dist/handlers/internal/multisig.js.map +1 -0
- package/dist/handlers/internal/requestListener.d.ts +124 -0
- package/dist/handlers/internal/requestListener.d.ts.map +1 -0
- package/dist/handlers/internal/requestListener.js +173 -0
- package/dist/handlers/internal/requestListener.js.map +1 -0
- package/dist/handlers/internal/sponsorship.d.ts +113 -0
- package/dist/handlers/internal/sponsorship.d.ts.map +1 -0
- package/dist/handlers/internal/sponsorship.js +128 -0
- package/dist/handlers/internal/sponsorship.js.map +1 -0
- package/dist/handlers/internal/types.d.ts +284 -0
- package/dist/handlers/internal/types.d.ts.map +1 -0
- package/dist/handlers/internal/types.js +2 -0
- package/dist/handlers/internal/types.js.map +1 -0
- package/dist/handlers/internal/utils.d.ts +34 -0
- package/dist/handlers/internal/utils.d.ts.map +1 -0
- package/dist/handlers/internal/utils.js +131 -0
- package/dist/handlers/internal/utils.js.map +1 -0
- package/dist/handlers/relay.d.ts +123 -0
- package/dist/handlers/relay.d.ts.map +1 -0
- package/dist/handlers/relay.js +1278 -0
- package/dist/handlers/relay.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/internal/Auth.d.ts +224 -16
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +572 -33
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/Log.d.ts +7 -3
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +4 -0
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/OpenApi.d.ts +0 -19
- package/dist/internal/OpenApi.d.ts.map +1 -1
- package/dist/internal/OpenApi.js +0 -57
- package/dist/internal/OpenApi.js.map +1 -1
- package/dist/internal/RpcSchema.d.ts +10 -0
- package/dist/internal/RpcSchema.d.ts.map +1 -0
- package/dist/internal/RpcSchema.js +2 -0
- package/dist/internal/RpcSchema.js.map +1 -0
- package/dist/internal/Store.d.ts +49 -4
- package/dist/internal/Store.d.ts.map +1 -1
- package/dist/internal/Store.js +81 -5
- package/dist/internal/Store.js.map +1 -1
- package/dist/internal/VerifiedTokens.d.ts +15 -34
- package/dist/internal/VerifiedTokens.d.ts.map +1 -1
- package/dist/internal/VerifiedTokens.js +115 -159
- package/dist/internal/VerifiedTokens.js.map +1 -1
- package/dist/internal/Viem.d.ts +84 -0
- package/dist/internal/Viem.d.ts.map +1 -1
- package/dist/internal/Webhooks.d.ts +50 -36
- package/dist/internal/Webhooks.d.ts.map +1 -1
- package/dist/internal/Webhooks.js +92 -205
- package/dist/internal/Webhooks.js.map +1 -1
- package/package.json +37 -6
- package/src/ApiKey.test.ts +3 -3
- package/src/ApiKey.ts +11 -12
- package/src/ApiKeys.test.ts +278 -0
- package/src/ApiKeys.ts +358 -0
- package/src/App.test-d.ts +1 -1
- package/src/App.test.ts +40508 -19083
- package/src/App.ts +239 -416
- package/src/Client.test-d.ts +307 -16
- package/src/Handler.ts +154 -0
- package/src/Scope.ts +17 -4
- package/src/Webhooks.test.ts +8 -7
- package/src/Webhooks.ts +13 -7
- package/src/admin/Access.ts +1 -3
- package/src/admin/App.ts +19 -24
- package/src/admin/apps/api-keys.test.ts +70 -18
- package/src/admin/apps/api-keys.ts +92 -9
- package/src/admin/apps/scopes.test.ts +8 -0
- package/src/admin/apps/verified-tokens.test.ts +3 -30
- package/src/admin/apps/verified-tokens.ts +18 -37
- package/src/admin/ui.generated.ts +1 -1
- package/src/apps/composition.test.ts +66 -0
- package/src/apps/data/App.ts +295 -0
- package/src/apps/data/index.ts +2 -0
- package/src/apps/{activities.test.ts → data/routes/activities.test.ts} +3 -3
- package/src/apps/{activities.ts → data/routes/activities.ts} +15 -15
- package/src/apps/{addresses.ts → data/routes/addresses.ts} +6 -6
- package/src/apps/{balances.test.ts → data/routes/balances.test.ts} +6 -5
- package/src/apps/{balances.ts → data/routes/balances.ts} +46 -12
- package/src/apps/{blocks.test.ts → data/routes/blocks.test.ts} +4 -4
- package/src/apps/{blocks.ts → data/routes/blocks.ts} +14 -14
- package/src/apps/{coingecko.test.ts → data/routes/coingecko.test.ts} +2 -2
- package/src/apps/{coingecko.ts → data/routes/coingecko.ts} +14 -14
- package/src/apps/{exchanges.test.ts → data/routes/exchanges.test.ts} +2 -2
- package/src/apps/{exchanges.ts → data/routes/exchanges.ts} +20 -20
- package/src/apps/{fee-amm.test.ts → data/routes/fee-amm.test.ts} +3 -3
- package/src/apps/{fee-amm.ts → data/routes/fee-amm.ts} +18 -18
- package/src/apps/{indexer.test.ts → data/routes/indexer.test.ts} +27 -6
- package/src/apps/{indexer.ts → data/routes/indexer.ts} +13 -10
- package/src/apps/{receipts.test.ts → data/routes/receipts.test.ts} +4 -4
- package/src/apps/{receipts.ts → data/routes/receipts.ts} +13 -13
- package/src/apps/{rpc.test.ts → data/routes/rpc.test.ts} +142 -13
- package/src/apps/{rpc.ts → data/routes/rpc.ts} +7 -7
- package/src/apps/{tokenlist.test.ts → data/routes/tokenlist.test.ts} +8 -10
- package/src/apps/{tokenlist.ts → data/routes/tokenlist.ts} +9 -9
- package/src/apps/{tokens.test.ts → data/routes/tokens.test.ts} +6 -5
- package/src/apps/{tokens.ts → data/routes/tokens.ts} +20 -20
- package/src/apps/{transactions.test.ts → data/routes/transactions.test.ts} +4 -4
- package/src/apps/{transactions.ts → data/routes/transactions.ts} +15 -15
- package/src/apps/{transfers.test.ts → data/routes/transfers.test.ts} +3 -3
- package/src/apps/{transfers.ts → data/routes/transfers.ts} +15 -15
- package/src/apps/{verified-tokens.test.ts → data/routes/verified-tokens.test.ts} +27 -15
- package/src/apps/{verified-tokens.ts → data/routes/verified-tokens.ts} +10 -10
- package/src/apps/{webhooks.test.ts → data/routes/webhooks.test.ts} +137 -150
- package/src/apps/{webhooks.ts → data/routes/webhooks.ts} +83 -81
- package/src/apps/docs/App.ts +136 -0
- package/src/apps/docs/index.ts +1 -0
- package/src/apps/index.ts +3 -0
- package/src/apps/metadata.ts +23 -0
- package/src/apps/platform/App.ts +130 -0
- package/src/apps/platform/index.ts +1 -0
- package/src/apps/platform/routes/api-keys.test.ts +330 -0
- package/src/apps/platform/routes/api-keys.ts +427 -0
- package/src/apps/platform/routes/invitations.test.ts +361 -0
- package/src/apps/platform/routes/invitations.ts +519 -0
- package/src/apps/platform/routes/me.test.ts +121 -0
- package/src/apps/platform/routes/me.ts +106 -0
- package/src/apps/platform/routes/members.test.ts +195 -0
- package/src/apps/platform/routes/members.ts +313 -0
- package/src/apps/platform/routes/orgs.test.ts +313 -0
- package/src/apps/platform/routes/orgs.ts +343 -0
- package/src/apps/platform/routes/projects.test.ts +181 -0
- package/src/apps/platform/routes/projects.ts +367 -0
- package/src/apps/relay/App.test.ts +484 -0
- package/src/apps/relay/App.ts +128 -0
- package/src/apps/relay/Sponsorships.test.ts +375 -0
- package/src/apps/relay/Sponsorships.ts +305 -0
- package/src/apps/relay/index.ts +2 -0
- package/src/{Cli.test.ts → cli/Cli.test.ts} +10 -9
- package/src/{Cli.ts → cli/Cli.ts} +16 -9
- package/src/cli/bin.ts +4 -0
- package/src/cli/commands/admin.test.ts +71 -0
- package/src/cli/commands/admin.ts +60 -0
- package/src/cloudflare.ts +10 -0
- package/src/db/Db.test.ts +84 -0
- package/src/db/Db.ts +542 -0
- package/src/db/Schema.ts +301 -0
- package/src/db/tables/invitations.ts +198 -0
- package/src/db/tables/memberships.ts +208 -0
- package/src/db/tables/organizations.test.ts +160 -0
- package/src/db/tables/organizations.ts +232 -0
- package/src/db/tables/projects.ts +107 -0
- package/src/db/tables/sponsoredTransactions.test.ts +218 -0
- package/src/db/tables/sponsoredTransactions.ts +236 -0
- package/src/db/tables/users.ts +85 -0
- package/src/db/tables/verifiedTokens.ts +111 -0
- package/src/db/tables/webhookDeliveries.ts +159 -0
- package/src/db/tables/webhookSubscriptions.ts +358 -0
- package/src/handlers/internal/executionError.ts +207 -0
- package/src/handlers/internal/multisig.test.ts +818 -0
- package/src/handlers/internal/multisig.ts +823 -0
- package/src/handlers/internal/requestListener.ts +273 -0
- package/src/handlers/internal/sponsorship.ts +245 -0
- package/src/handlers/internal/types.ts +378 -0
- package/src/handlers/internal/utils.ts +153 -0
- package/src/handlers/relay.test.ts +2035 -0
- package/src/handlers/relay.ts +1623 -0
- package/src/index.ts +4 -2
- package/src/internal/Auth.test.ts +337 -21
- package/src/internal/Auth.ts +783 -44
- package/src/internal/Cursor.test.ts +3 -2
- package/src/internal/Log.test.ts +1 -1
- package/src/internal/Log.ts +11 -3
- package/src/internal/MetricSink.ts +1 -1
- package/src/internal/OpenApi.ts +0 -59
- package/src/internal/RateLimit.test.ts +1 -1
- package/src/internal/RpcSchema.ts +10 -0
- package/src/internal/Store.test.ts +150 -10
- package/src/internal/Store.ts +136 -11
- package/src/internal/Tidx.local.test.ts +1 -1
- package/src/internal/VerifiedTokens.test.ts +99 -115
- package/src/internal/VerifiedTokens.ts +123 -175
- package/src/internal/WebhookDestination.test.ts +1 -1
- package/src/internal/Webhooks.test.ts +111 -111
- package/src/internal/Webhooks.ts +103 -221
- package/dist/ApiKeySource.d.ts +0 -166
- package/dist/ApiKeySource.d.ts.map +0 -1
- package/dist/ApiKeySource.js +0 -234
- package/dist/ApiKeySource.js.map +0 -1
- package/dist/Cli.d.ts.map +0 -1
- package/dist/Cli.js +0 -13
- package/dist/Cli.js.map +0 -1
- package/dist/apps/activities.js.map +0 -1
- package/dist/apps/addresses.js.map +0 -1
- package/dist/apps/balances.d.ts.map +0 -1
- package/dist/apps/balances.js.map +0 -1
- package/dist/apps/blocks.d.ts.map +0 -1
- package/dist/apps/blocks.js.map +0 -1
- package/dist/apps/coingecko.d.ts.map +0 -1
- package/dist/apps/coingecko.js.map +0 -1
- package/dist/apps/exchanges.d.ts.map +0 -1
- package/dist/apps/exchanges.js.map +0 -1
- package/dist/apps/fee-amm.d.ts.map +0 -1
- package/dist/apps/fee-amm.js.map +0 -1
- package/dist/apps/indexer.d.ts.map +0 -1
- package/dist/apps/indexer.js.map +0 -1
- package/dist/apps/receipts.d.ts.map +0 -1
- package/dist/apps/receipts.js.map +0 -1
- package/dist/apps/rpc.d.ts.map +0 -1
- package/dist/apps/rpc.js.map +0 -1
- package/dist/apps/tokenlist.d.ts.map +0 -1
- package/dist/apps/tokenlist.js.map +0 -1
- package/dist/apps/tokens.d.ts.map +0 -1
- package/dist/apps/tokens.js.map +0 -1
- package/dist/apps/transactions.d.ts.map +0 -1
- package/dist/apps/transactions.js.map +0 -1
- package/dist/apps/transfers.d.ts.map +0 -1
- package/dist/apps/transfers.js.map +0 -1
- package/dist/apps/verified-tokens.d.ts.map +0 -1
- package/dist/apps/verified-tokens.js.map +0 -1
- package/dist/apps/webhooks.js.map +0 -1
- package/dist/internal/OpenApi.fonts.d.ts.map +0 -1
- package/dist/internal/OpenApi.fonts.js.map +0 -1
- package/dist/internal/OpenApi.logo.d.ts.map +0 -1
- package/dist/internal/OpenApi.logo.js.map +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000000.svg +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000001.svg +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000002.svg +0 -1
- package/seeds/31318/icons/0x20c0000000000000000000000000000000000003.svg +0 -1
- package/seeds/31318/verified-tokens.json +0 -30
- package/seeds/4217/icons/0x20c0000000000000000000000000000000000000.svg +0 -25
- package/seeds/4217/icons/0x20c000000000000000000000048c8f36df1c9a4a.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000000520792dcccccccc.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000000a6da882d075a4c3.svg +0 -4
- package/seeds/4217/icons/0x20c000000000000000000000111111111e910f0f.svg +0 -30
- package/seeds/4217/icons/0x20c00000000000000000000014f22ca97301eb73.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000001621e21f71cf12fb.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000002f52d5cc21a3207b.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000003158081efd85bfc2.svg +0 -11
- package/seeds/4217/icons/0x20c0000000000000000000003554d28269e0f3c2.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000383a23bacb546ab9.svg +0 -1
- package/seeds/4217/icons/0x20c00000000000000000000042109aef2f8b28e1.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000005c0bac7cef389a11.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000006fd9a167923ba194.png +0 -0
- package/seeds/4217/icons/0x20c0000000000000000000007f7ba549dd0251b9.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000008191667423f70e67.svg +0 -5
- package/seeds/4217/icons/0x20c0000000000000000000008ee4fcff88888888.svg +0 -1
- package/seeds/4217/icons/0x20c0000000000000000000009a4a4b17e0dc6651.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000ab02d39df30bd17e.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000ae247a1130450f09.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000aeed2ec36a54d0e5.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000b9537d11c60e8b50.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000bd95bfb69fbe6ce3.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000c412ec89d0c08be5.svg +0 -1
- package/seeds/4217/icons/0x20c000000000000000000000f047dd7018e50367.png +0 -0
- package/seeds/4217/verified-tokens.json +0 -177
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000000.svg +0 -25
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000001.svg +0 -1
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000002.svg +0 -1
- package/seeds/42431/icons/0x20c0000000000000000000000000000000000003.svg +0 -1
- package/seeds/42431/icons/0x20c0000000000000000000009e8d7eb59b783726.svg +0 -1
- package/seeds/42431/icons/0x20c000000000000000000000d72572838bbee59c.svg +0 -1
- package/seeds/42431/verified-tokens.json +0 -44
- package/seeds/openrpc/README.md +0 -27
- package/seeds/openrpc/execution-apis.json +0 -8989
- package/src/ApiKeySource.test-d.ts +0 -11
- package/src/ApiKeySource.test.ts +0 -295
- package/src/ApiKeySource.ts +0 -303
- /package/src/{internal/OpenApi.fonts.ts → apps/docs/fonts.ts} +0 -0
- /package/src/{internal/OpenApi.logo.ts → apps/docs/logo.ts} +0 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Hono } from 'hono'
|
|
2
|
+
|
|
3
|
+
import type * as App from '../../App.js'
|
|
4
|
+
import * as Metadata from '../metadata.js'
|
|
5
|
+
|
|
6
|
+
import { apiKeys } from './routes/api-keys.js'
|
|
7
|
+
import { invitations } from './routes/invitations.js'
|
|
8
|
+
import { me } from './routes/me.js'
|
|
9
|
+
import { members } from './routes/members.js'
|
|
10
|
+
import { orgs } from './routes/orgs.js'
|
|
11
|
+
import { projects } from './routes/projects.js'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Minimal transactional email sender. Cloudflare deployments wrap the Email
|
|
15
|
+
* Service binding (`{ from, send: (m) => env.EMAIL.send(m) }`); other hosts
|
|
16
|
+
* pass any compatible sender. Dispatch is always best-effort.
|
|
17
|
+
*/
|
|
18
|
+
export type Email = {
|
|
19
|
+
/** Console URL embedded in email links (e.g. sign-in URLs). Defaults to the hosted console; self-hosts point it at their own. */
|
|
20
|
+
consoleUrl?: string | undefined
|
|
21
|
+
/** Sender address for platform emails (e.g. `noreply@tempo.xyz`). */
|
|
22
|
+
from: string
|
|
23
|
+
/** Sends one message. */
|
|
24
|
+
send: (message: Email.Message) => Promise<unknown>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export declare namespace Email {
|
|
28
|
+
/** One transactional message. */
|
|
29
|
+
type Message = {
|
|
30
|
+
/** Sender address. */
|
|
31
|
+
from: string
|
|
32
|
+
/** HTML body. */
|
|
33
|
+
html?: string | undefined
|
|
34
|
+
/** Subject line. */
|
|
35
|
+
subject: string
|
|
36
|
+
/** Plain-text body. */
|
|
37
|
+
text: string
|
|
38
|
+
/** Recipient address. */
|
|
39
|
+
to: string
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Request environment for platform routes: the shared app environment plus the
|
|
45
|
+
* `email` sender this group publishes on context. Owned here, not in core
|
|
46
|
+
* `App.Environment`, since email is a platform concern.
|
|
47
|
+
*/
|
|
48
|
+
export type Environment = {
|
|
49
|
+
Variables: App.Environment['Variables'] & {
|
|
50
|
+
/** Transactional email sender for platform emails; undefined when dispatch is disabled. */
|
|
51
|
+
email: Email | undefined
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The tenant-platform route group: the current user, orgs, projects, members,
|
|
57
|
+
* invitations, and API-key management. Every route reads its dependencies from
|
|
58
|
+
* request context set by {@link App.create}.
|
|
59
|
+
*
|
|
60
|
+
* The session-auth surface (`/v1/auth/siwe` + `session` capability) is owned by
|
|
61
|
+
* {@link App.create}, so platform routes gate on a session without owning it.
|
|
62
|
+
*
|
|
63
|
+
* ```ts
|
|
64
|
+
* App.create(options).route('/', platform())
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export function platform(options: platform.Options = {}) {
|
|
68
|
+
const app = new Hono<Environment>()
|
|
69
|
+
// Publish the transactional email sender for this group's handlers
|
|
70
|
+
// (invitations read it off context); undefined disables dispatch.
|
|
71
|
+
.use('*', async (c, next) => {
|
|
72
|
+
c.set('email', options.email)
|
|
73
|
+
await next()
|
|
74
|
+
})
|
|
75
|
+
.route('/', apiKeys({ enabled: options.apiKeys !== false }))
|
|
76
|
+
.route('/', invitations())
|
|
77
|
+
.route('/', me())
|
|
78
|
+
.route('/', members())
|
|
79
|
+
.route('/', orgs())
|
|
80
|
+
.route('/', projects())
|
|
81
|
+
return Metadata.attach(app, openapi)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export declare namespace platform {
|
|
85
|
+
/** Options for the platform route group. */
|
|
86
|
+
type Options = {
|
|
87
|
+
/** Expose the API-key management routes in the OpenAPI document. @default true */
|
|
88
|
+
apiKeys?: boolean | undefined
|
|
89
|
+
/** Transactional email sender for platform emails (e.g. invitations); omit to disable dispatch — notified flows still work in-product. */
|
|
90
|
+
email?: Email | undefined
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The OpenAPI metadata this group owns: platform operation tags and the
|
|
96
|
+
* `session` security scheme. Tagged onto the {@link platform} instance so
|
|
97
|
+
* `App.create` collects it.
|
|
98
|
+
*/
|
|
99
|
+
const openapi = {
|
|
100
|
+
securitySchemes: {
|
|
101
|
+
session: {
|
|
102
|
+
description: 'Cookie session established by sign-in (`POST /v1/auth/siwe`). Clients may also send the session token as `Authorization: Bearer <token>`.', // prettier-ignore
|
|
103
|
+
in: 'cookie',
|
|
104
|
+
name: 'accounts_auth',
|
|
105
|
+
type: 'apiKey',
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
tags: [
|
|
109
|
+
{ name: 'API Keys', description: 'Credentials for accessing the Tempo API.' },
|
|
110
|
+
{ name: 'Invitations', description: 'Pending organization invitations.' },
|
|
111
|
+
{ name: 'Members', description: 'Organization team membership.' },
|
|
112
|
+
{ name: 'Organizations', description: 'Teams that own application workspaces and members.' },
|
|
113
|
+
{ name: 'Projects', description: 'Application workspaces within an organization.' },
|
|
114
|
+
{ name: 'Users', description: 'Users on the Tempo Platform.' },
|
|
115
|
+
],
|
|
116
|
+
'x-tagGroups': [
|
|
117
|
+
{
|
|
118
|
+
name: 'Platform API',
|
|
119
|
+
tags: [
|
|
120
|
+
'API Keys',
|
|
121
|
+
'Authentication',
|
|
122
|
+
'Invitations',
|
|
123
|
+
'Members',
|
|
124
|
+
'Organizations',
|
|
125
|
+
'Projects',
|
|
126
|
+
'Users',
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
} satisfies App.create.Metadata
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { platform } from './App.js'
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
|
|
2
|
+
|
|
3
|
+
import * as TestApp from '../../../../test/App.js'
|
|
4
|
+
import * as Keys from './api-keys.js'
|
|
5
|
+
import * as Orgs from './orgs.js'
|
|
6
|
+
import * as Projects from './projects.js'
|
|
7
|
+
|
|
8
|
+
/** Origin pinned for SIWE domain binding; Hono test requests use this host. */
|
|
9
|
+
const origin = 'http://localhost'
|
|
10
|
+
|
|
11
|
+
/** Super admin secret configured on the test app. */
|
|
12
|
+
const secret = 'tempo:sk:c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2c2'
|
|
13
|
+
|
|
14
|
+
/** RequestInit for a JSON mutation carrying the session cookie. */
|
|
15
|
+
function json(method: 'PATCH' | 'POST', cookie: string, body: unknown) {
|
|
16
|
+
return {
|
|
17
|
+
body: JSON.stringify(body),
|
|
18
|
+
headers: { 'content-type': 'application/json', cookie },
|
|
19
|
+
method,
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** RequestInit for a JSON mutation authenticated as the super admin. */
|
|
24
|
+
function superAdminJson(method: 'PATCH' | 'POST', body: unknown) {
|
|
25
|
+
return {
|
|
26
|
+
body: JSON.stringify(body),
|
|
27
|
+
headers: { 'content-type': 'application/json', 'tempo-api-key': secret },
|
|
28
|
+
method,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Resolve-cache disabled so revocation assertions observe the store directly.
|
|
33
|
+
type State = ReturnType<typeof TestApp.kvStore>
|
|
34
|
+
|
|
35
|
+
function createApp(options: { kv?: { store: State } } = {}) {
|
|
36
|
+
return TestApp.create({
|
|
37
|
+
auth: { cache: false, superAdmin: { secret } },
|
|
38
|
+
...(options.kv ? { kv: options.kv } : {}),
|
|
39
|
+
session: { wallet: { origin } },
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function failRecordDeletes(store: State) {
|
|
44
|
+
const delete_ = store.delete.bind(store)
|
|
45
|
+
store.delete = async (key) => {
|
|
46
|
+
if (key.startsWith('apikey:')) throw new Error('KV delete failed.')
|
|
47
|
+
await delete_(key)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Signs in a fresh scripted account; returns its session cookie. */
|
|
52
|
+
async function session(app: TestApp.signIn.App) {
|
|
53
|
+
const account = privateKeyToAccount(generatePrivateKey())
|
|
54
|
+
const { cookie } = await TestApp.signIn(app, account)
|
|
55
|
+
return cookie!
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Creates an org and a project owned by the session. */
|
|
59
|
+
async function fixture(app: ReturnType<typeof createApp>, cookie: string) {
|
|
60
|
+
const org = await TestApp.json(
|
|
61
|
+
await app.request('/v1/orgs', json('POST', cookie, { name: 'Acme' })),
|
|
62
|
+
Orgs.schema.Organization,
|
|
63
|
+
)
|
|
64
|
+
const project = await TestApp.json(
|
|
65
|
+
await app.request(`/v1/orgs/${org.id}/projects`, json('POST', cookie, { name: 'Checkout' })),
|
|
66
|
+
Projects.schema.Project,
|
|
67
|
+
)
|
|
68
|
+
return { org, project }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
describe('keys', () => {
|
|
72
|
+
test('mints, lists, authenticates, and revokes a project key', async () => {
|
|
73
|
+
const app = createApp()
|
|
74
|
+
const cookie = await session(app)
|
|
75
|
+
const { org, project } = await fixture(app, cookie)
|
|
76
|
+
const base = `/v1/orgs/${org.id}/projects/${project.id}/api-keys`
|
|
77
|
+
|
|
78
|
+
// Scoped keys mint through the super admin: no scope is self-issuable.
|
|
79
|
+
const minted = await app.request(
|
|
80
|
+
base,
|
|
81
|
+
superAdminJson('POST', { environment: 'sandbox', name: 'CI', scopes: ['data:read'] }),
|
|
82
|
+
)
|
|
83
|
+
expect(minted.status).toBe(200)
|
|
84
|
+
const created = await TestApp.json(minted, Keys.schema.createApiKey.Response)
|
|
85
|
+
expect(created.id).toMatch(/^key_/)
|
|
86
|
+
expect(created.token).toMatch(/^tempo_sandbox:sk:[a-f0-9]{48}$/)
|
|
87
|
+
expect(created.orgId).toBe(org.id)
|
|
88
|
+
expect(created.projectId).toBe(project.id)
|
|
89
|
+
expect(created.createdBy).toBe('super_admin')
|
|
90
|
+
|
|
91
|
+
// The minted key authenticates data API requests. `no-store` forces an
|
|
92
|
+
// origin pass — an edge-cache hit would skip auth and mask the assertion.
|
|
93
|
+
const data = await app.request('/v1/tokens', {
|
|
94
|
+
headers: { 'cache-control': 'no-store', 'tempo-api-key': created.token },
|
|
95
|
+
})
|
|
96
|
+
expect(data.status).toBe(200)
|
|
97
|
+
|
|
98
|
+
// Listing exposes metadata only — never the token.
|
|
99
|
+
const listed = await app.request(base, { headers: { cookie } })
|
|
100
|
+
expect(listed.status).toBe(200)
|
|
101
|
+
const list = await TestApp.json(listed, Keys.schema.listApiKeys.Response)
|
|
102
|
+
expect(list.data.map(({ id }) => id)).toEqual([created.id])
|
|
103
|
+
expect(JSON.stringify(list)).not.toContain(created.token)
|
|
104
|
+
expect(list.data[0]!.tokenLast4).toBe(created.token.slice(-4))
|
|
105
|
+
|
|
106
|
+
const revoked = await app.request(`${base}/${created.id}`, {
|
|
107
|
+
headers: { cookie },
|
|
108
|
+
method: 'DELETE',
|
|
109
|
+
})
|
|
110
|
+
expect(revoked.status).toBe(200)
|
|
111
|
+
expect(await TestApp.json(revoked, Keys.schema.revokeApiKey.Response)).toEqual({
|
|
112
|
+
id: created.id,
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
// With the resolve cache disabled, revocation is immediate.
|
|
116
|
+
const after = await app.request('/v1/tokens', {
|
|
117
|
+
headers: { 'cache-control': 'no-store', 'tempo-api-key': created.token },
|
|
118
|
+
})
|
|
119
|
+
expect(after.status).toBe(401)
|
|
120
|
+
const empty = await TestApp.json(
|
|
121
|
+
await app.request(base, { headers: { cookie } }),
|
|
122
|
+
Keys.schema.listApiKeys.Response,
|
|
123
|
+
)
|
|
124
|
+
expect(empty).toEqual({ data: [] })
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
test('rejects the wildcard scope at mint', async () => {
|
|
128
|
+
const app = createApp()
|
|
129
|
+
const cookie = await session(app)
|
|
130
|
+
const { org, project } = await fixture(app, cookie)
|
|
131
|
+
|
|
132
|
+
const response = await app.request(
|
|
133
|
+
`/v1/orgs/${org.id}/projects/${project.id}/api-keys`,
|
|
134
|
+
json('POST', cookie, { scopes: ['*'] }),
|
|
135
|
+
)
|
|
136
|
+
expect(response.status).toBe(400)
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
test('rejects session mints while no scope is self-issuable', async () => {
|
|
140
|
+
const app = createApp()
|
|
141
|
+
const cookie = await session(app)
|
|
142
|
+
const { org, project } = await fixture(app, cookie)
|
|
143
|
+
|
|
144
|
+
const response = await app.request(
|
|
145
|
+
`/v1/orgs/${org.id}/projects/${project.id}/api-keys`,
|
|
146
|
+
json('POST', cookie, { scopes: ['data:read'] }),
|
|
147
|
+
)
|
|
148
|
+
expect(response.status).toBe(403)
|
|
149
|
+
const { requestId, ...body } = (await response.json()) as { requestId?: string }
|
|
150
|
+
expect(requestId).toBeDefined()
|
|
151
|
+
expect(body).toMatchInlineSnapshot(`
|
|
152
|
+
{
|
|
153
|
+
"error": {
|
|
154
|
+
"code": "scope_not_issuable",
|
|
155
|
+
"message": "The requested scopes are not issuable.",
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
`)
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
test('binds keys to their project on every verb', async () => {
|
|
162
|
+
const app = createApp()
|
|
163
|
+
const owner = await session(app)
|
|
164
|
+
const { org, project } = await fixture(app, owner)
|
|
165
|
+
const other = await TestApp.json(
|
|
166
|
+
await app.request(`/v1/orgs/${org.id}/projects`, json('POST', owner, { name: 'Payments' })),
|
|
167
|
+
Projects.schema.Project,
|
|
168
|
+
)
|
|
169
|
+
const minted = await TestApp.json(
|
|
170
|
+
await app.request(
|
|
171
|
+
`/v1/orgs/${org.id}/projects/${project.id}/api-keys`,
|
|
172
|
+
superAdminJson('POST', { scopes: ['data:read'] }),
|
|
173
|
+
),
|
|
174
|
+
Keys.schema.createApiKey.Response,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
// Same org, sibling project: the key id must not resolve through it.
|
|
178
|
+
const crossList = await app.request(`/v1/orgs/${org.id}/projects/${other.id}/api-keys`, {
|
|
179
|
+
headers: { cookie: owner },
|
|
180
|
+
})
|
|
181
|
+
expect((await TestApp.json(crossList, Keys.schema.listApiKeys.Response)).data).toEqual([])
|
|
182
|
+
const crossRevoke = await app.request(
|
|
183
|
+
`/v1/orgs/${org.id}/projects/${other.id}/api-keys/${minted.id}`,
|
|
184
|
+
{ headers: { cookie: owner }, method: 'DELETE' },
|
|
185
|
+
)
|
|
186
|
+
expect(crossRevoke.status).toBe(404)
|
|
187
|
+
|
|
188
|
+
// Foreign session: the whole surface 404s at the org-ownership link.
|
|
189
|
+
const stranger = await session(app)
|
|
190
|
+
const foreignMint = await app.request(
|
|
191
|
+
`/v1/orgs/${org.id}/projects/${project.id}/api-keys`,
|
|
192
|
+
json('POST', stranger, { scopes: ['data:read'] }),
|
|
193
|
+
)
|
|
194
|
+
expect(foreignMint.status).toBe(404)
|
|
195
|
+
const foreignRevoke = await app.request(
|
|
196
|
+
`/v1/orgs/${org.id}/projects/${project.id}/api-keys/${minted.id}`,
|
|
197
|
+
{ headers: { cookie: stranger }, method: 'DELETE' },
|
|
198
|
+
)
|
|
199
|
+
expect(foreignRevoke.status).toBe(404)
|
|
200
|
+
|
|
201
|
+
// The key survives every attempt, still listed for the owner.
|
|
202
|
+
const listed = await app.request(`/v1/orgs/${org.id}/projects/${project.id}/api-keys`, {
|
|
203
|
+
headers: { cookie: owner },
|
|
204
|
+
})
|
|
205
|
+
const list = await TestApp.json(listed, Keys.schema.listApiKeys.Response)
|
|
206
|
+
expect(list.data.map(({ id }) => id)).toEqual([minted.id])
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
test('revokes keys when their project or organization is deleted', async () => {
|
|
210
|
+
const app = createApp()
|
|
211
|
+
const cookie = await session(app)
|
|
212
|
+
const { org, project } = await fixture(app, cookie)
|
|
213
|
+
const minted = await TestApp.json(
|
|
214
|
+
await app.request(
|
|
215
|
+
`/v1/orgs/${org.id}/projects/${project.id}/api-keys`,
|
|
216
|
+
superAdminJson('POST', { scopes: ['data:read'] }),
|
|
217
|
+
),
|
|
218
|
+
Keys.schema.createApiKey.Response,
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
const deletedProject = await app.request(`/v1/orgs/${org.id}/projects/${project.id}`, {
|
|
222
|
+
headers: { cookie },
|
|
223
|
+
method: 'DELETE',
|
|
224
|
+
})
|
|
225
|
+
expect(deletedProject.status).toBe(200)
|
|
226
|
+
const afterProject = await app.request('/v1/tokens', {
|
|
227
|
+
headers: { 'cache-control': 'no-store', 'tempo-api-key': minted.token },
|
|
228
|
+
})
|
|
229
|
+
expect(afterProject.status).toBe(401)
|
|
230
|
+
|
|
231
|
+
// Org deletion revokes keys of every remaining project.
|
|
232
|
+
const other = await TestApp.json(
|
|
233
|
+
await app.request(`/v1/orgs/${org.id}/projects`, json('POST', cookie, { name: 'Payments' })),
|
|
234
|
+
Projects.schema.Project,
|
|
235
|
+
)
|
|
236
|
+
const survivor = await TestApp.json(
|
|
237
|
+
await app.request(
|
|
238
|
+
`/v1/orgs/${org.id}/projects/${other.id}/api-keys`,
|
|
239
|
+
superAdminJson('POST', { scopes: ['data:read'] }),
|
|
240
|
+
),
|
|
241
|
+
Keys.schema.createApiKey.Response,
|
|
242
|
+
)
|
|
243
|
+
const deletedOrg = await app.request(`/v1/orgs/${org.id}`, {
|
|
244
|
+
headers: { cookie },
|
|
245
|
+
method: 'DELETE',
|
|
246
|
+
})
|
|
247
|
+
expect(deletedOrg.status).toBe(200)
|
|
248
|
+
const afterOrg = await app.request('/v1/tokens', {
|
|
249
|
+
headers: { 'cache-control': 'no-store', 'tempo-api-key': survivor.token },
|
|
250
|
+
})
|
|
251
|
+
expect(afterOrg.status).toBe(401)
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
test('keeps the project when key revocation fails during project deletion', async () => {
|
|
255
|
+
const store = TestApp.kvStore({ keys: [] })
|
|
256
|
+
const app = createApp({ kv: { store } })
|
|
257
|
+
const cookie = await session(app)
|
|
258
|
+
const { org, project } = await fixture(app, cookie)
|
|
259
|
+
await TestApp.json(
|
|
260
|
+
await app.request(
|
|
261
|
+
`/v1/orgs/${org.id}/projects/${project.id}/api-keys`,
|
|
262
|
+
superAdminJson('POST', { scopes: ['data:read'] }),
|
|
263
|
+
),
|
|
264
|
+
Keys.schema.createApiKey.Response,
|
|
265
|
+
)
|
|
266
|
+
failRecordDeletes(store)
|
|
267
|
+
|
|
268
|
+
const deletedProject = await app.request(`/v1/orgs/${org.id}/projects/${project.id}`, {
|
|
269
|
+
headers: { cookie },
|
|
270
|
+
method: 'DELETE',
|
|
271
|
+
})
|
|
272
|
+
expect(deletedProject.status).toBe(502)
|
|
273
|
+
|
|
274
|
+
const projectStill = await app.request(`/v1/orgs/${org.id}/projects/${project.id}`, {
|
|
275
|
+
headers: { cookie },
|
|
276
|
+
})
|
|
277
|
+
expect(projectStill.status).toBe(200)
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
test('keeps the organization when key revocation fails during organization deletion', async () => {
|
|
281
|
+
const store = TestApp.kvStore({ keys: [] })
|
|
282
|
+
const app = createApp({ kv: { store } })
|
|
283
|
+
const cookie = await session(app)
|
|
284
|
+
const { org, project } = await fixture(app, cookie)
|
|
285
|
+
await TestApp.json(
|
|
286
|
+
await app.request(
|
|
287
|
+
`/v1/orgs/${org.id}/projects/${project.id}/api-keys`,
|
|
288
|
+
superAdminJson('POST', { scopes: ['data:read'] }),
|
|
289
|
+
),
|
|
290
|
+
Keys.schema.createApiKey.Response,
|
|
291
|
+
)
|
|
292
|
+
failRecordDeletes(store)
|
|
293
|
+
|
|
294
|
+
const deletedOrg = await app.request(`/v1/orgs/${org.id}`, {
|
|
295
|
+
headers: { cookie },
|
|
296
|
+
method: 'DELETE',
|
|
297
|
+
})
|
|
298
|
+
expect(deletedOrg.status).toBe(502)
|
|
299
|
+
|
|
300
|
+
const orgStill = await app.request(`/v1/orgs/${org.id}`, { headers: { cookie } })
|
|
301
|
+
expect(orgStill.status).toBe(200)
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
test('mints as the super admin with super admin attribution', async () => {
|
|
305
|
+
const app = createApp()
|
|
306
|
+
const cookie = await session(app)
|
|
307
|
+
const { org, project } = await fixture(app, cookie)
|
|
308
|
+
|
|
309
|
+
const minted = await app.request(`/v1/orgs/${org.id}/projects/${project.id}/api-keys`, {
|
|
310
|
+
body: JSON.stringify({ scopes: ['data:read'] }),
|
|
311
|
+
headers: { 'content-type': 'application/json', 'tempo-api-key': secret },
|
|
312
|
+
method: 'POST',
|
|
313
|
+
})
|
|
314
|
+
expect(minted.status).toBe(200)
|
|
315
|
+
const created = await TestApp.json(minted, Keys.schema.createApiKey.Response)
|
|
316
|
+
expect(created.createdBy).toBe('super_admin')
|
|
317
|
+
expect(created.environment).toBe('production')
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
test('rejects API keys on the keys surface', async () => {
|
|
321
|
+
const app = createApp()
|
|
322
|
+
const cookie = await session(app)
|
|
323
|
+
const { org, project } = await fixture(app, cookie)
|
|
324
|
+
|
|
325
|
+
const response = await app.request(`/v1/orgs/${org.id}/projects/${project.id}/api-keys`, {
|
|
326
|
+
headers: { 'tempo-api-key': TestApp.key.token },
|
|
327
|
+
})
|
|
328
|
+
expect(response.status).toBe(403)
|
|
329
|
+
})
|
|
330
|
+
})
|