tapimo 0.19.0 → 0.20.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 +13 -5
- package/dist/ApiKey.d.ts +2 -2
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +2 -2
- package/dist/ApiKey.js.map +1 -1
- package/dist/ApiKeys.d.ts +85 -11
- package/dist/ApiKeys.d.ts.map +1 -1
- package/dist/ApiKeys.js +218 -56
- package/dist/ApiKeys.js.map +1 -1
- package/dist/App.d.ts +12543 -13912
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +4 -5
- package/dist/App.js.map +1 -1
- package/dist/Scope.d.ts +12 -20
- package/dist/Scope.d.ts.map +1 -1
- package/dist/Scope.js +20 -36
- package/dist/Scope.js.map +1 -1
- package/dist/admin/App.d.ts +871 -828
- package/dist/admin/App.d.ts.map +1 -1
- package/dist/admin/App.js +14 -26
- package/dist/admin/App.js.map +1 -1
- package/dist/admin/apps/api-keys.d.ts +93 -186
- package/dist/admin/apps/api-keys.d.ts.map +1 -1
- package/dist/admin/apps/api-keys.js +3 -5
- package/dist/admin/apps/api-keys.js.map +1 -1
- package/dist/admin/apps/audit-logs.d.ts +18 -18
- package/dist/admin/apps/audit-logs.js +1 -1
- package/dist/admin/apps/audit-logs.js.map +1 -1
- package/dist/admin/apps/earn-vaults.d.ts +27 -27
- package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
- package/dist/admin/apps/earn-vaults.js +11 -5
- package/dist/admin/apps/earn-vaults.js.map +1 -1
- package/dist/admin/apps/organizations.d.ts +17 -17
- package/dist/admin/apps/prop-amms.d.ts +4 -4
- package/dist/admin/apps/routes-support.js +1 -38
- package/dist/admin/apps/routes-support.js.map +1 -1
- package/dist/admin/apps/routes.d.ts +153 -153
- package/dist/admin/apps/sentinel.d.ts +4 -4
- package/dist/admin/apps/verified-tokens.d.ts +24 -24
- package/dist/admin/apps/zone-delegation-requests.d.ts +332 -0
- package/dist/admin/apps/zone-delegation-requests.d.ts.map +1 -0
- package/dist/admin/apps/zone-delegation-requests.js +200 -0
- package/dist/admin/apps/zone-delegation-requests.js.map +1 -0
- package/dist/admin/apps/zone-delegations.d.ts +512 -52
- package/dist/admin/apps/zone-delegations.d.ts.map +1 -1
- package/dist/admin/apps/zone-delegations.js +134 -44
- package/dist/admin/apps/zone-delegations.js.map +1 -1
- package/dist/admin/index.d.ts +1 -1
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +1 -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 +341 -397
- package/dist/admin/ui.generated.js.map +1 -1
- package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
- package/dist/analytics/tables/requestEvents.js +4 -2
- package/dist/analytics/tables/requestEvents.js.map +1 -1
- package/dist/apps/data/App.d.ts +11932 -13214
- package/dist/apps/data/App.d.ts.map +1 -1
- package/dist/apps/data/App.js +32 -13
- package/dist/apps/data/App.js.map +1 -1
- package/dist/apps/data/ZoneSelection.d.ts +1 -1
- package/dist/apps/data/ZoneSelection.d.ts.map +1 -1
- package/dist/apps/data/ZoneSelection.js +2 -2
- package/dist/apps/data/ZoneSelection.js.map +1 -1
- package/dist/apps/data/routes/activities.d.ts +60 -27
- package/dist/apps/data/routes/activities.d.ts.map +1 -1
- package/dist/apps/data/routes/activities.js +91 -16
- package/dist/apps/data/routes/activities.js.map +1 -1
- package/dist/apps/data/routes/addresses.d.ts +893 -875
- package/dist/apps/data/routes/addresses.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.d.ts +36 -36
- package/dist/apps/data/routes/balances.d.ts.map +1 -1
- package/dist/apps/data/routes/balances.js +3 -1
- package/dist/apps/data/routes/balances.js.map +1 -1
- package/dist/apps/data/routes/blocks.d.ts +40 -40
- package/dist/apps/data/routes/blocks.d.ts.map +1 -1
- package/dist/apps/data/routes/blocks.js +3 -7
- package/dist/apps/data/routes/blocks.js.map +1 -1
- package/dist/apps/data/routes/coingecko.d.ts +236 -236
- package/dist/apps/data/routes/earn-transactions.d.ts +14 -14
- package/dist/apps/data/routes/earn.d.ts +261 -1445
- package/dist/apps/data/routes/earn.d.ts.map +1 -1
- package/dist/apps/data/routes/earn.js +64 -490
- package/dist/apps/data/routes/earn.js.map +1 -1
- package/dist/apps/data/routes/exchanges.d.ts +144 -144
- package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
- package/dist/apps/data/routes/exchanges.js +5 -15
- package/dist/apps/data/routes/exchanges.js.map +1 -1
- package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
- package/dist/apps/data/routes/fee-amm.js +3 -9
- package/dist/apps/data/routes/fee-amm.js.map +1 -1
- package/dist/apps/data/routes/indexer.d.ts +13 -13
- package/dist/apps/data/routes/receipts.d.ts +53 -53
- package/dist/apps/data/routes/receipts.js +1 -1
- package/dist/apps/data/routes/receipts.js.map +1 -1
- package/dist/apps/data/routes/rpc.d.ts +52 -0
- package/dist/apps/data/routes/rpc.d.ts.map +1 -1
- package/dist/apps/data/routes/rpc.js +19 -18
- package/dist/apps/data/routes/rpc.js.map +1 -1
- package/dist/apps/data/routes/tokenlist.d.ts +14 -14
- package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
- package/dist/apps/data/routes/tokenlist.js +1 -3
- package/dist/apps/data/routes/tokenlist.js.map +1 -1
- package/dist/apps/data/routes/tokens.d.ts.map +1 -1
- package/dist/apps/data/routes/tokens.js +7 -5
- package/dist/apps/data/routes/tokens.js.map +1 -1
- package/dist/apps/data/routes/transactions.d.ts +281 -281
- package/dist/apps/data/routes/transactions.js +3 -3
- 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/transfers.d.ts.map +1 -1
- package/dist/apps/data/routes/transfers.js +1 -3
- package/dist/apps/data/routes/transfers.js.map +1 -1
- package/dist/apps/data/routes/valuation.d.ts +30 -30
- package/dist/apps/data/routes/valuation.d.ts.map +1 -1
- package/dist/apps/data/routes/valuation.js +1 -3
- package/dist/apps/data/routes/valuation.js.map +1 -1
- package/dist/apps/data/routes/verified-tokens.d.ts +86 -86
- package/dist/apps/data/routes/webhooks.d.ts +102 -102
- package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
- package/dist/apps/data/routes/webhooks.js +9 -23
- package/dist/apps/data/routes/webhooks.js.map +1 -1
- package/dist/apps/data/routes/zone-deposits.d.ts +16 -16
- package/dist/apps/data/routes/zone-withdrawals.d.ts +31 -31
- package/dist/apps/data/routes/zones.d.ts +28 -28
- package/dist/apps/management/App.d.ts +18 -102
- package/dist/apps/management/App.d.ts.map +1 -1
- package/dist/apps/management/App.js +1 -1
- package/dist/apps/management/App.js.map +1 -1
- package/dist/apps/management/routes/api-keys.d.ts +253 -339
- package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
- package/dist/apps/management/routes/api-keys.js +25 -11
- package/dist/apps/management/routes/api-keys.js.map +1 -1
- package/dist/apps/management/routes/billing.d.ts +92 -92
- package/dist/apps/management/routes/billing.d.ts.map +1 -1
- package/dist/apps/management/routes/billing.js +5 -13
- package/dist/apps/management/routes/billing.js.map +1 -1
- package/dist/apps/management/routes/cli.d.ts.map +1 -1
- package/dist/apps/management/routes/cli.js +3 -9
- package/dist/apps/management/routes/cli.js.map +1 -1
- package/dist/apps/management/routes/faucet.d.ts +16 -16
- package/dist/apps/management/routes/fee-payer-usage.d.ts +38 -38
- package/dist/apps/management/routes/fee-payer-usage.d.ts.map +1 -1
- package/dist/apps/management/routes/fee-payer-usage.js +2 -4
- package/dist/apps/management/routes/fee-payer-usage.js.map +1 -1
- package/dist/apps/management/routes/invitations.d.ts +52 -52
- package/dist/apps/management/routes/invitations.d.ts.map +1 -1
- package/dist/apps/management/routes/invitations.js +4 -12
- package/dist/apps/management/routes/invitations.js.map +1 -1
- package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
- package/dist/apps/management/routes/invite-links.js +6 -14
- package/dist/apps/management/routes/invite-links.js.map +1 -1
- package/dist/apps/management/routes/me.d.ts +6 -6
- package/dist/apps/management/routes/me.d.ts.map +1 -1
- package/dist/apps/management/routes/me.js +3 -7
- package/dist/apps/management/routes/me.js.map +1 -1
- package/dist/apps/management/routes/members.d.ts +84 -84
- package/dist/apps/management/routes/members.d.ts.map +1 -1
- package/dist/apps/management/routes/members.js +2 -4
- package/dist/apps/management/routes/members.js.map +1 -1
- package/dist/apps/management/routes/orgs.d.ts +44 -44
- package/dist/apps/management/routes/orgs.d.ts.map +1 -1
- package/dist/apps/management/routes/orgs.js +2 -6
- package/dist/apps/management/routes/orgs.js.map +1 -1
- package/dist/apps/management/routes/projects.d.ts.map +1 -1
- package/dist/apps/management/routes/projects.js +2 -6
- package/dist/apps/management/routes/projects.js.map +1 -1
- package/dist/apps/management/routes/route-usage.d.ts +34 -34
- package/dist/apps/management/routes/route-usage.d.ts.map +1 -1
- package/dist/apps/management/routes/route-usage.js +2 -4
- package/dist/apps/management/routes/route-usage.js.map +1 -1
- package/dist/apps/management/routes/routes-access-requests.d.ts +120 -91
- package/dist/apps/management/routes/routes-access-requests.d.ts.map +1 -1
- package/dist/apps/management/routes/routes-access-requests.js +49 -9
- package/dist/apps/management/routes/routes-access-requests.js.map +1 -1
- package/dist/apps/management/routes/usage.d.ts.map +1 -1
- package/dist/apps/management/routes/usage.js +8 -16
- package/dist/apps/management/routes/usage.js.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.d.ts +39 -39
- package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
- package/dist/apps/management/routes/verified-token-requests.js +3 -7
- package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
- package/dist/apps/management/routes/webhooks.d.ts +2089 -2089
- package/dist/apps/management/routes/zone-delegations.d.ts +14 -17
- package/dist/apps/management/routes/zone-delegations.d.ts.map +1 -1
- package/dist/apps/management/routes/zone-delegations.js +1 -6
- package/dist/apps/management/routes/zone-delegations.js.map +1 -1
- package/dist/apps/mpp/App.d.ts +44 -44
- package/dist/apps/mpp/App.js +3 -3
- package/dist/apps/mpp/App.js.map +1 -1
- package/dist/apps/mpp/internal/Adapter.js +1 -1
- package/dist/apps/mpp/internal/Adapter.js.map +1 -1
- package/dist/apps/mpp/internal/Error.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Error.js +1 -0
- package/dist/apps/mpp/internal/Error.js.map +1 -1
- package/dist/apps/mpp/internal/Policy.d.ts +5 -1
- package/dist/apps/mpp/internal/Policy.d.ts.map +1 -1
- package/dist/apps/mpp/internal/Policy.js +35 -13
- package/dist/apps/mpp/internal/Policy.js.map +1 -1
- package/dist/apps/relay/App.d.ts +2 -2
- package/dist/apps/relay/App.d.ts.map +1 -1
- package/dist/apps/relay/App.js +25 -16
- package/dist/apps/relay/App.js.map +1 -1
- package/dist/apps/routes/App.d.ts +311 -311
- package/dist/apps/routes/routes/deposit-addresses.d.ts +1099 -1099
- package/dist/apps/routes/routes/list.d.ts +74 -74
- package/dist/apps/routes/routes/transfers.d.ts +94 -94
- package/dist/cli/ApiKeys.d.ts +19 -26
- package/dist/cli/ApiKeys.d.ts.map +1 -1
- package/dist/db/Db.d.ts +3 -3
- package/dist/db/Db.d.ts.map +1 -1
- package/dist/db/Db.js +27 -0
- package/dist/db/Db.js.map +1 -1
- package/dist/db/Schema.d.ts +28 -62
- package/dist/db/Schema.d.ts.map +1 -1
- package/dist/db/Schema.js +18 -18
- package/dist/db/Schema.js.map +1 -1
- package/dist/db/tables/rewardRuns.d.ts +21 -0
- package/dist/db/tables/rewardRuns.d.ts.map +1 -1
- package/dist/db/tables/rewardRuns.js +19 -0
- package/dist/db/tables/rewardRuns.js.map +1 -1
- package/dist/db/tables/routesAccessRequests.d.ts +13 -0
- package/dist/db/tables/routesAccessRequests.d.ts.map +1 -1
- package/dist/db/tables/routesAccessRequests.js +12 -0
- package/dist/db/tables/routesAccessRequests.js.map +1 -1
- package/dist/db/tables/zoneDelegationRequests.d.ts +165 -0
- package/dist/db/tables/zoneDelegationRequests.d.ts.map +1 -0
- package/dist/db/tables/{zoneKeyRequests.js → zoneDelegationRequests.js} +43 -42
- package/dist/db/tables/zoneDelegationRequests.js.map +1 -0
- package/dist/db/tables/zoneDelegations.d.ts +11 -5
- package/dist/db/tables/zoneDelegations.d.ts.map +1 -1
- package/dist/db/tables/zoneDelegations.js +21 -3
- package/dist/db/tables/zoneDelegations.js.map +1 -1
- package/dist/handlers/internal/accounts.d.ts +7 -0
- package/dist/handlers/internal/accounts.d.ts.map +1 -0
- package/dist/handlers/internal/{multisig.js → accounts.js} +10 -10
- package/dist/handlers/internal/{multisig.js.map → accounts.js.map} +1 -1
- package/dist/handlers/internal/sponsorship.js +17 -17
- package/dist/handlers/internal/sponsorship.js.map +1 -1
- package/dist/handlers/relay.d.ts +6 -6
- package/dist/handlers/relay.d.ts.map +1 -1
- package/dist/handlers/relay.js +15 -15
- package/dist/handlers/relay.js.map +1 -1
- package/dist/internal/Auth.d.ts.map +1 -1
- package/dist/internal/Auth.js +4 -8
- package/dist/internal/Auth.js.map +1 -1
- package/dist/internal/EarnRates.d.ts.map +1 -1
- package/dist/internal/EarnRates.js +1 -3
- package/dist/internal/EarnRates.js.map +1 -1
- package/dist/internal/EarnVaults.js +2 -2
- package/dist/internal/Log.d.ts +2 -4
- package/dist/internal/Log.d.ts.map +1 -1
- package/dist/internal/Log.js +0 -3
- package/dist/internal/Log.js.map +1 -1
- package/dist/internal/Response.d.ts +1 -1
- package/dist/internal/Response.d.ts.map +1 -1
- package/dist/internal/Response.js +0 -3
- package/dist/internal/Response.js.map +1 -1
- package/dist/internal/Schema.d.ts +11 -0
- package/dist/internal/Schema.d.ts.map +1 -1
- package/dist/internal/Schema.js +24 -1
- package/dist/internal/Schema.js.map +1 -1
- package/dist/internal/ZoneAccess.d.ts +70 -35
- package/dist/internal/ZoneAccess.d.ts.map +1 -1
- package/dist/internal/ZoneAccess.js +312 -131
- package/dist/internal/ZoneAccess.js.map +1 -1
- package/dist/internal/ZoneDelegation.d.ts +7 -19
- package/dist/internal/ZoneDelegation.d.ts.map +1 -1
- package/dist/internal/ZoneDelegation.js +8 -29
- package/dist/internal/ZoneDelegation.js.map +1 -1
- package/dist/internal/{ZoneKeyApproval.d.ts → ZoneDelegationApproval.d.ts} +3 -5
- package/dist/internal/ZoneDelegationApproval.d.ts.map +1 -0
- package/dist/internal/ZoneDelegationApproval.js +16 -0
- package/dist/internal/ZoneDelegationApproval.js.map +1 -0
- package/dist/internal/ZoneKeyRewrite.d.ts +98 -0
- package/dist/internal/ZoneKeyRewrite.d.ts.map +1 -0
- package/dist/internal/ZoneKeyRewrite.js +151 -0
- package/dist/internal/ZoneKeyRewrite.js.map +1 -0
- package/dist/internal/rewards/Campaigns.d.ts +2 -0
- package/dist/internal/rewards/Campaigns.d.ts.map +1 -1
- package/dist/internal/rewards/Campaigns.js.map +1 -1
- package/dist/internal/rewards/Distributions.d.ts.map +1 -1
- package/dist/internal/rewards/Distributions.js +2 -6
- package/dist/internal/rewards/Distributions.js.map +1 -1
- package/dist/internal/rewards/Monitor.d.ts +4 -1
- package/dist/internal/rewards/Monitor.d.ts.map +1 -1
- package/dist/internal/rewards/Monitor.js +19 -2
- package/dist/internal/rewards/Monitor.js.map +1 -1
- package/dist/internal/rewards/Runner.d.ts.map +1 -1
- package/dist/internal/rewards/Runner.js +9 -1
- package/dist/internal/rewards/Runner.js.map +1 -1
- package/dist/internal/routes/Action.d.ts.map +1 -1
- package/dist/internal/routes/Action.js +2 -3
- package/dist/internal/routes/Action.js.map +1 -1
- package/dist/internal/routes/Deposit.d.ts.map +1 -1
- package/dist/internal/routes/Deposit.js +2 -6
- package/dist/internal/routes/Deposit.js.map +1 -1
- package/dist/internal/routes/DepositAddress.d.ts.map +1 -1
- package/dist/internal/routes/DepositAddress.js +4 -10
- package/dist/internal/routes/DepositAddress.js.map +1 -1
- package/dist/internal/routes/Policy.d.ts.map +1 -1
- package/dist/internal/routes/Policy.js +2 -1
- package/dist/internal/routes/Policy.js.map +1 -1
- package/dist/internal/routes/Provider.js +8 -8
- package/dist/internal/routes/Provider.js.map +1 -1
- package/dist/internal/routes/Reconciliation.d.ts.map +1 -1
- package/dist/internal/routes/Reconciliation.js +3 -2
- package/dist/internal/routes/Reconciliation.js.map +1 -1
- package/dist/internal/routes/Transfer.d.ts.map +1 -1
- package/dist/internal/routes/Transfer.js +4 -12
- package/dist/internal/routes/Transfer.js.map +1 -1
- package/dist/internal/routes/UniversalDepositAddress.d.ts.map +1 -1
- package/dist/internal/routes/UniversalDepositAddress.js +3 -6
- package/dist/internal/routes/UniversalDepositAddress.js.map +1 -1
- package/dist/internal/routes/providers/SquidOrder.d.ts.map +1 -1
- package/dist/internal/routes/providers/SquidOrder.js +3 -2
- package/dist/internal/routes/providers/SquidOrder.js.map +1 -1
- package/dist/internal/routes/providers/relay.d.ts.map +1 -1
- package/dist/internal/routes/providers/relay.js +4 -3
- package/dist/internal/routes/providers/relay.js.map +1 -1
- package/package.json +20 -5
- package/src/ApiKey.ts +2 -2
- package/src/ApiKeys.test.ts +284 -51
- package/src/ApiKeys.ts +297 -64
- package/src/App.ts +4 -5
- package/src/Client.test-d.ts +33 -126
- package/src/Scope.test.ts +26 -45
- package/src/Scope.ts +24 -37
- package/src/admin/App.test.ts +51 -4
- package/src/admin/App.ts +25 -33
- package/src/admin/Mcp.test.ts +2 -1
- package/src/admin/apps/api-keys.test.ts +90 -20
- package/src/admin/apps/api-keys.ts +5 -8
- package/src/admin/apps/audit-logs.ts +1 -1
- package/src/admin/apps/earn-vaults.test.ts +19 -19
- package/src/admin/apps/earn-vaults.ts +11 -5
- package/src/admin/apps/routes-support.test.ts +254 -3
- package/src/admin/apps/routes-support.ts +1 -44
- package/src/admin/apps/scopes.test.ts +3 -3
- package/src/admin/apps/zone-delegation-requests.test.ts +246 -0
- package/src/admin/apps/zone-delegation-requests.ts +240 -0
- package/src/admin/apps/zone-delegations.test.ts +218 -58
- package/src/admin/apps/zone-delegations.ts +146 -46
- package/src/admin/index.ts +1 -1
- package/src/admin/ui/src/components/ApiKeyForm.tsx +4 -3
- package/src/admin/ui/src/lib/config.ts +3 -3
- package/src/admin/ui/src/lib/query-client.ts +1 -1
- package/src/admin/ui/src/lib/review-queues.ts +10 -10
- package/src/admin/ui/src/lib/routes-setup.test.ts +1 -2
- package/src/admin/ui/src/lib/routes-setup.ts +3 -5
- package/src/admin/ui/src/lib/scopes.test.ts +3 -6
- package/src/admin/ui/src/lib/scopes.ts +2 -9
- package/src/admin/ui/src/lib/{zone-key-requests.ts → zone-delegation-requests.ts} +27 -31
- package/src/admin/ui/src/routeTree.gen.ts +17 -17
- package/src/admin/ui/src/routes/__root.tsx +1 -1
- package/src/admin/ui/src/routes/api-keys.tsx +2 -15
- package/src/admin/ui/src/routes/audit-logs.tsx +2 -2
- package/src/admin/ui/src/routes/index.tsx +11 -11
- package/src/admin/ui/src/routes/organizations.tsx +3 -1
- package/src/admin/ui/src/routes/organizations_.$orgId.tsx +3 -1
- package/src/admin/ui/src/routes/organizations_.$orgId_.setup.tsx +1 -3
- package/src/admin/ui/src/routes/{zone-key-requests.tsx → zone-delegation-requests.tsx} +228 -172
- package/src/admin/ui/vite.config.ts +14 -1
- package/src/admin/ui.generated.ts +412 -583
- package/src/analytics/tables/requestEvents.test.ts +13 -3
- package/src/analytics/tables/requestEvents.ts +4 -3
- package/src/apps/data/App.test.ts +72 -35
- package/src/apps/data/App.ts +29 -13
- package/src/apps/data/ZoneSelection.test.ts +53 -70
- package/src/apps/data/ZoneSelection.ts +2 -2
- package/src/apps/data/routes/activities.test.ts +140 -6
- package/src/apps/data/routes/activities.ts +124 -18
- package/src/apps/data/routes/balances.ts +5 -1
- package/src/apps/data/routes/blocks.ts +9 -13
- package/src/apps/data/routes/earn-transactions.local.test.ts +6 -1
- package/src/apps/data/routes/earn-transactions.test.ts +7 -3
- package/src/apps/data/routes/earn.bench.ts +0 -14
- package/src/apps/data/routes/earn.discovery.test.ts +4 -39
- package/src/apps/data/routes/earn.local.test.ts +27 -34
- package/src/apps/data/routes/earn.test.ts +172 -490
- package/src/apps/data/routes/earn.ts +103 -652
- package/src/apps/data/routes/exchanges.ts +20 -30
- package/src/apps/data/routes/fee-amm.ts +12 -18
- package/src/apps/data/routes/indexer.test.ts +14 -12
- package/src/apps/data/routes/receipts.ts +1 -1
- package/src/apps/data/routes/rpc.test.ts +23 -18
- package/src/apps/data/routes/rpc.ts +21 -21
- package/src/apps/data/routes/rpc.zone.test.ts +60 -6
- package/src/apps/data/routes/tokenlist.ts +4 -6
- package/src/apps/data/routes/tokens.test.ts +20 -0
- package/src/apps/data/routes/tokens.ts +10 -5
- package/src/apps/data/routes/transactions.ts +3 -3
- package/src/apps/data/routes/transfers.ts +4 -6
- package/src/apps/data/routes/valuation.test.ts +2 -4
- package/src/apps/data/routes/valuation.ts +4 -6
- package/src/apps/data/routes/webhooks.test.ts +1 -5
- package/src/apps/data/routes/webhooks.ts +30 -44
- package/src/apps/data/routes/zones.test.ts +35 -19
- package/src/apps/management/App.ts +3 -1
- package/src/apps/management/routes/api-keys.test.ts +112 -22
- package/src/apps/management/routes/api-keys.ts +30 -15
- package/src/apps/management/routes/billing.ts +17 -25
- package/src/apps/management/routes/cli.ts +12 -18
- package/src/apps/management/routes/fee-payer-usage.ts +5 -4
- package/src/apps/management/routes/invitations.ts +16 -21
- package/src/apps/management/routes/invite-links.ts +18 -26
- package/src/apps/management/routes/me.ts +9 -13
- package/src/apps/management/routes/members.ts +5 -7
- package/src/apps/management/routes/orgs.ts +8 -12
- package/src/apps/management/routes/projects.ts +8 -12
- package/src/apps/management/routes/route-usage.ts +5 -4
- package/src/apps/management/routes/routes-access-requests.test.ts +64 -2
- package/src/apps/management/routes/routes-access-requests.ts +99 -15
- package/src/apps/management/routes/scopes.test.ts +3 -3
- package/src/apps/management/routes/usage.ts +20 -28
- package/src/apps/management/routes/verified-token-requests.ts +9 -13
- package/src/apps/management/routes/zone-delegations.test.ts +3 -5
- package/src/apps/management/routes/zone-delegations.ts +4 -9
- package/src/apps/mpp/App.ts +3 -3
- package/src/apps/mpp/Mpp.zone.test.ts +49 -18
- package/src/apps/mpp/internal/Adapter.ts +1 -1
- package/src/apps/mpp/internal/Error.test.ts +3 -0
- package/src/apps/mpp/internal/Error.ts +1 -0
- package/src/apps/mpp/internal/Policy.test.ts +9 -8
- package/src/apps/mpp/internal/Policy.ts +37 -14
- package/src/apps/relay/App.sandbox.test.ts +15 -14
- package/src/apps/relay/App.test.ts +120 -61
- package/src/apps/relay/App.ts +28 -18
- package/src/apps/relay/App.zone-billing.test.ts +9 -4
- package/src/apps/routes/App.test.ts +21 -22
- package/src/db/Db.ts +34 -3
- package/src/db/Schema.ts +26 -26
- package/src/db/tables/rewardRuns.ts +39 -0
- package/src/db/tables/routesAccessRequests.test.ts +65 -0
- package/src/db/tables/routesAccessRequests.ts +25 -0
- package/src/db/tables/{zoneKeyRequests.test.ts → zoneDelegationRequests.test.ts} +36 -77
- package/src/db/tables/{zoneKeyRequests.ts → zoneDelegationRequests.ts} +69 -52
- package/src/db/tables/zoneDelegations.test.ts +5 -6
- package/src/db/tables/zoneDelegations.ts +25 -8
- package/src/handlers/internal/{multisig.store.test.ts → accounts.store.test.ts} +16 -16
- package/src/handlers/internal/{multisig.test.ts → accounts.test.ts} +85 -82
- package/src/handlers/internal/{multisig.ts → accounts.ts} +9 -9
- package/src/handlers/internal/sponsorship.ts +20 -20
- package/src/handlers/relay.test.ts +48 -46
- package/src/handlers/relay.ts +26 -26
- package/src/internal/Auth.test.ts +6 -2
- package/src/internal/Auth.ts +4 -10
- package/src/internal/EarnRates.ts +4 -6
- package/src/internal/EarnVaults.ts +2 -2
- package/src/internal/Log.test-d.ts +1 -0
- package/src/internal/Log.test.ts +4 -6
- package/src/internal/Log.ts +2 -6
- package/src/internal/Response.ts +0 -3
- package/src/internal/Schema.test.ts +42 -0
- package/src/internal/Schema.ts +36 -1
- package/src/internal/ZoneAccess.test.ts +515 -312
- package/src/internal/ZoneAccess.ts +410 -158
- package/src/internal/ZoneDelegation.test.ts +1 -41
- package/src/internal/ZoneDelegation.ts +10 -48
- package/src/internal/ZoneDelegationApproval.test.ts +22 -0
- package/src/internal/{ZoneKeyApproval.ts → ZoneDelegationApproval.ts} +4 -11
- package/src/internal/ZoneKeyRewrite.ts +231 -0
- package/src/internal/rewards/Campaigns.ts +2 -0
- package/src/internal/rewards/Distributions.ts +8 -12
- package/src/internal/rewards/Monitor.test.ts +64 -0
- package/src/internal/rewards/Monitor.ts +27 -4
- package/src/internal/rewards/Runner.ts +9 -1
- package/src/internal/routes/Action.ts +5 -6
- package/src/internal/routes/Deposit.ts +8 -12
- package/src/internal/routes/DepositAddress.ts +13 -19
- package/src/internal/routes/Policy.ts +2 -1
- package/src/internal/routes/Provider.ts +8 -8
- package/src/internal/routes/Reconciliation.ts +3 -2
- package/src/internal/routes/Transfer.ts +16 -24
- package/src/internal/routes/UniversalDepositAddress.ts +9 -12
- package/src/internal/routes/providers/SquidOrder.ts +3 -2
- package/src/internal/routes/providers/relay.ts +4 -3
- package/dist/admin/apps/zone-key-requests.d.ts +0 -406
- package/dist/admin/apps/zone-key-requests.d.ts.map +0 -1
- package/dist/admin/apps/zone-key-requests.js +0 -183
- package/dist/admin/apps/zone-key-requests.js.map +0 -1
- package/dist/db/tables/zoneKeyRequests.d.ts +0 -289
- package/dist/db/tables/zoneKeyRequests.d.ts.map +0 -1
- package/dist/db/tables/zoneKeyRequests.js.map +0 -1
- package/dist/handlers/internal/multisig.d.ts +0 -7
- package/dist/handlers/internal/multisig.d.ts.map +0 -1
- package/dist/internal/ZoneKeyApproval.d.ts.map +0 -1
- package/dist/internal/ZoneKeyApproval.js +0 -21
- package/dist/internal/ZoneKeyApproval.js.map +0 -1
- package/src/admin/apps/zone-key-requests.test.ts +0 -272
- package/src/admin/apps/zone-key-requests.ts +0 -231
- package/src/internal/ZoneKeyApproval.test.ts +0 -46
|
@@ -643,12 +643,10 @@ export namespace schema {
|
|
|
643
643
|
context: z
|
|
644
644
|
.optional(Context)
|
|
645
645
|
.check(z.meta({ examples: [{ title: 'Prod USDC large transfers' }] })),
|
|
646
|
-
createdAt:
|
|
647
|
-
.
|
|
648
|
-
.
|
|
649
|
-
|
|
650
|
-
z.meta({ examples: ['2024-01-01T00:00:00Z'] }),
|
|
651
|
-
),
|
|
646
|
+
createdAt: Schema.dateTime().check(
|
|
647
|
+
z.describe('When the subscription was created, as an ISO 8601 timestamp.'),
|
|
648
|
+
z.meta({ examples: ['2024-01-01T00:00:00Z'] }),
|
|
649
|
+
),
|
|
652
650
|
destination: PublicDestination,
|
|
653
651
|
environment: z
|
|
654
652
|
.optional(z.enum(['production', 'sandbox']))
|
|
@@ -658,7 +656,7 @@ export namespace schema {
|
|
|
658
656
|
),
|
|
659
657
|
eventType: EventType.check(z.meta({ examples: ['token:transfer'] })),
|
|
660
658
|
expiresAt: z
|
|
661
|
-
.optional(
|
|
659
|
+
.optional(Schema.dateTime())
|
|
662
660
|
.check(
|
|
663
661
|
z.describe(
|
|
664
662
|
'When the subscription expires, as an ISO 8601 timestamp. Only MPP-paid subscriptions expire.',
|
|
@@ -686,7 +684,7 @@ export namespace schema {
|
|
|
686
684
|
z.meta({ examples: ['wh_001718668800000_2ZPE2gvateYEQ0dQslgvkhjx'] }),
|
|
687
685
|
),
|
|
688
686
|
lastDeliveryAt: z
|
|
689
|
-
.optional(
|
|
687
|
+
.optional(Schema.dateTime())
|
|
690
688
|
.check(
|
|
691
689
|
z.describe(
|
|
692
690
|
'When Tempo last delivered an event successfully, as an ISO 8601 timestamp. Refreshed at most once per minute during sustained delivery.',
|
|
@@ -694,12 +692,10 @@ export namespace schema {
|
|
|
694
692
|
z.meta({ examples: ['2024-01-01T00:00:00Z'] }),
|
|
695
693
|
),
|
|
696
694
|
status: Status.check(z.meta({ examples: ['active'] })),
|
|
697
|
-
updatedAt:
|
|
698
|
-
.
|
|
699
|
-
.
|
|
700
|
-
|
|
701
|
-
z.meta({ examples: ['2024-01-01T00:00:00Z'] }),
|
|
702
|
-
),
|
|
695
|
+
updatedAt: Schema.dateTime().check(
|
|
696
|
+
z.describe('When the subscription was last changed, as an ISO 8601 timestamp.'),
|
|
697
|
+
z.meta({ examples: ['2024-01-01T00:00:00Z'] }),
|
|
698
|
+
),
|
|
703
699
|
})
|
|
704
700
|
.check(
|
|
705
701
|
z.describe(
|
|
@@ -729,12 +725,10 @@ export namespace schema {
|
|
|
729
725
|
z.describe('Retry attempt number for this delivery, starting at 1.'),
|
|
730
726
|
z.meta({ examples: [1] }),
|
|
731
727
|
),
|
|
732
|
-
createdAt:
|
|
733
|
-
.
|
|
734
|
-
.
|
|
735
|
-
|
|
736
|
-
z.meta({ examples: ['2024-01-01T00:00:00Z'] }),
|
|
737
|
-
),
|
|
728
|
+
createdAt: Schema.dateTime().check(
|
|
729
|
+
z.describe('When this delivery attempt was created, as an ISO 8601 timestamp.'),
|
|
730
|
+
z.meta({ examples: ['2024-01-01T00:00:00Z'] }),
|
|
731
|
+
),
|
|
738
732
|
error: z
|
|
739
733
|
.optional(z.string())
|
|
740
734
|
.check(
|
|
@@ -822,12 +816,10 @@ export namespace schema {
|
|
|
822
816
|
z.describe('Address that sent the transfer.'),
|
|
823
817
|
z.meta({ examples: ['0xe7687128b0a808c2831ff94d4f7b2fb35c65af38'] }),
|
|
824
818
|
),
|
|
825
|
-
timestamp:
|
|
826
|
-
.
|
|
827
|
-
.
|
|
828
|
-
|
|
829
|
-
z.meta({ examples: ['2026-01-14T18:38:03.685Z'] }),
|
|
830
|
-
),
|
|
819
|
+
timestamp: Schema.dateTime().check(
|
|
820
|
+
z.describe('Block timestamp as an ISO 8601 string.'),
|
|
821
|
+
z.meta({ examples: ['2026-01-14T18:38:03.685Z'] }),
|
|
822
|
+
),
|
|
831
823
|
token: z.optional(
|
|
832
824
|
z
|
|
833
825
|
.object({
|
|
@@ -954,12 +946,10 @@ export namespace schema {
|
|
|
954
946
|
z.describe('Index of the log within its block.'),
|
|
955
947
|
z.meta({ examples: [0] }),
|
|
956
948
|
),
|
|
957
|
-
timestamp:
|
|
958
|
-
.
|
|
959
|
-
.
|
|
960
|
-
|
|
961
|
-
z.meta({ examples: ['2026-01-14T18:38:03.685Z'] }),
|
|
962
|
-
),
|
|
949
|
+
timestamp: Schema.dateTime().check(
|
|
950
|
+
z.describe('When the block was produced, as an ISO 8601 timestamp.'),
|
|
951
|
+
z.meta({ examples: ['2026-01-14T18:38:03.685Z'] }),
|
|
952
|
+
),
|
|
963
953
|
topics: z.array(Schema.Hash).check(
|
|
964
954
|
z.describe(
|
|
965
955
|
'Zero to four log topics; non-anonymous events start with the event signature hash.',
|
|
@@ -1051,12 +1041,10 @@ export namespace schema {
|
|
|
1051
1041
|
z.describe('Number of transactions included in this block.'),
|
|
1052
1042
|
z.meta({ examples: [3] }),
|
|
1053
1043
|
),
|
|
1054
|
-
timestamp:
|
|
1055
|
-
.
|
|
1056
|
-
.
|
|
1057
|
-
|
|
1058
|
-
z.meta({ examples: ['2026-01-14T18:38:03.685Z'] }),
|
|
1059
|
-
),
|
|
1044
|
+
timestamp: Schema.dateTime().check(
|
|
1045
|
+
z.describe('When the block was produced, as an ISO 8601 timestamp.'),
|
|
1046
|
+
z.meta({ examples: ['2026-01-14T18:38:03.685Z'] }),
|
|
1047
|
+
),
|
|
1060
1048
|
})
|
|
1061
1049
|
.check(z.describe('Payload for a `block:created` event (a new block header).')),
|
|
1062
1050
|
'WebhookBlockEvent',
|
|
@@ -1089,12 +1077,10 @@ export namespace schema {
|
|
|
1089
1077
|
context: z
|
|
1090
1078
|
.optional(Context)
|
|
1091
1079
|
.check(z.meta({ examples: [{ title: 'Prod USDC large transfers' }] })),
|
|
1092
|
-
createdAt:
|
|
1093
|
-
.
|
|
1094
|
-
.
|
|
1095
|
-
|
|
1096
|
-
z.meta({ examples: ['2026-01-14T18:38:03.000Z'] }),
|
|
1097
|
-
),
|
|
1080
|
+
createdAt: Schema.dateTime().check(
|
|
1081
|
+
z.describe('When Tempo built this delivery envelope, as an ISO 8601 timestamp.'),
|
|
1082
|
+
z.meta({ examples: ['2026-01-14T18:38:03.000Z'] }),
|
|
1083
|
+
),
|
|
1098
1084
|
id: z
|
|
1099
1085
|
.string()
|
|
1100
1086
|
.check(
|
|
@@ -95,16 +95,23 @@ function errorCodes(
|
|
|
95
95
|
return resolveSchema(document, envelope?.properties?.['error'])?.properties?.['code']?.enum
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
const zoneReader =
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
const zoneReader = TestApp.zoneReader(
|
|
99
|
+
{
|
|
100
|
+
id: 'key_zone_withdrawal',
|
|
101
|
+
orgId: 'org_test',
|
|
102
|
+
scopes: ['data:read'],
|
|
103
|
+
token: 'secret_zone_withdrawal',
|
|
104
|
+
},
|
|
105
|
+
[runtime.zone.chainId],
|
|
106
|
+
)
|
|
107
|
+
/** Holds the readers' organization delegation for the Zone. */
|
|
108
|
+
const db = TestApp.database()
|
|
109
|
+
await TestApp.delegateZone(db, { chainIds: [runtime.zone.chainId, runtime.zone.chainId + 1] })
|
|
104
110
|
|
|
105
111
|
function client(options: { keys?: readonly TestApp.kvStore.Key[] | undefined } = {}) {
|
|
106
112
|
return TestApp.client({
|
|
107
113
|
auth: { keys: options.keys ?? [zoneReader] },
|
|
114
|
+
db,
|
|
108
115
|
zones: [
|
|
109
116
|
TestApp.zone({
|
|
110
117
|
chainId: runtime.zone.chainId,
|
|
@@ -330,12 +337,15 @@ describe('GET /v1/zones/withdrawals/:senderTag', () => {
|
|
|
330
337
|
)
|
|
331
338
|
|
|
332
339
|
test('requires the matching Zone read scope', async () => {
|
|
333
|
-
const otherReader =
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
340
|
+
const otherReader = TestApp.zoneReader(
|
|
341
|
+
{
|
|
342
|
+
id: 'key_other_zone_withdrawal',
|
|
343
|
+
orgId: 'org_test',
|
|
344
|
+
scopes: ['data:read'],
|
|
345
|
+
token: 'secret_other_zone_withdrawal',
|
|
346
|
+
},
|
|
347
|
+
[runtime.zone.chainId + 1],
|
|
348
|
+
)
|
|
339
349
|
const response = await client({ keys: [otherReader] }).v1.zones.withdrawals[':senderTag'].$get(
|
|
340
350
|
{
|
|
341
351
|
param: { senderTag },
|
|
@@ -348,7 +358,7 @@ describe('GET /v1/zones/withdrawals/:senderTag', () => {
|
|
|
348
358
|
expect(response.status).toBe(403)
|
|
349
359
|
expect(body.error.code).toBe('api_key_forbidden')
|
|
350
360
|
expect(body.error.message).toBe(
|
|
351
|
-
`Chain ID ${runtime.zone.chainId} is a Zone. Use an API key granting \`zone
|
|
361
|
+
`Chain ID ${runtime.zone.chainId} is a Zone. Use an API key granting \`zone:read\` and tagged for Zone ${runtime.zone.chainId}, issued to an organization delegated that Zone.`,
|
|
352
362
|
)
|
|
353
363
|
})
|
|
354
364
|
|
|
@@ -369,6 +379,7 @@ describe('GET /v1/zones/withdrawals/:senderTag', () => {
|
|
|
369
379
|
test('rejects invalid sender tags and chain ids', async () => {
|
|
370
380
|
const app = TestApp.create({
|
|
371
381
|
auth: { keys: [zoneReader] },
|
|
382
|
+
db,
|
|
372
383
|
zones: [
|
|
373
384
|
TestApp.zone({
|
|
374
385
|
chainId: runtime.zone.chainId,
|
|
@@ -408,6 +419,7 @@ describe('GET /v1/zones/withdrawals/:senderTag', () => {
|
|
|
408
419
|
test('maps parent indexer failures to the upstream error contract', async () => {
|
|
409
420
|
const app = TestApp.create({
|
|
410
421
|
auth: { keys: [zoneReader] },
|
|
422
|
+
db,
|
|
411
423
|
tidx: { baseUrl: 'http://127.0.0.1:1' },
|
|
412
424
|
zones: [
|
|
413
425
|
TestApp.zone({
|
|
@@ -571,12 +583,15 @@ describe('GET /v1/zones/deposits/:depositHash', () => {
|
|
|
571
583
|
expect(response.status).toBe(401)
|
|
572
584
|
expect(body.error.code).toBe('api_key_invalid')
|
|
573
585
|
|
|
574
|
-
const otherReader =
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
586
|
+
const otherReader = TestApp.zoneReader(
|
|
587
|
+
{
|
|
588
|
+
id: 'key_other_zone_deposit',
|
|
589
|
+
orgId: 'org_test',
|
|
590
|
+
scopes: ['data:read'],
|
|
591
|
+
token: 'secret_other_zone_deposit',
|
|
592
|
+
},
|
|
593
|
+
[runtime.zone.chainId + 1],
|
|
594
|
+
)
|
|
580
595
|
const denied = await client({ keys: [otherReader] }).v1.zones.deposits[':depositHash'].$get(
|
|
581
596
|
{ param: { depositHash }, query: { chainId: String(runtime.zone.chainId) } },
|
|
582
597
|
auth(otherReader),
|
|
@@ -589,6 +604,7 @@ describe('GET /v1/zones/deposits/:depositHash', () => {
|
|
|
589
604
|
test('rejects invalid hashes and unsupported Zones', async () => {
|
|
590
605
|
const app = TestApp.create({
|
|
591
606
|
auth: { keys: [zoneReader] },
|
|
607
|
+
db,
|
|
592
608
|
zones: [
|
|
593
609
|
TestApp.zone({
|
|
594
610
|
chainId: runtime.zone.chainId,
|
|
@@ -90,7 +90,7 @@ export function management(options: management.Options = {}) {
|
|
|
90
90
|
.route('/', orgs())
|
|
91
91
|
.route('/', projects())
|
|
92
92
|
.route('/', routeUsage())
|
|
93
|
-
.route('/', routesAccessRequests())
|
|
93
|
+
.route('/', routesAccessRequests(options.routesAccessRequests))
|
|
94
94
|
.route('/', scopes())
|
|
95
95
|
.route('/', usage())
|
|
96
96
|
.route('/', verifiedTokenRequests())
|
|
@@ -110,6 +110,8 @@ export declare namespace management {
|
|
|
110
110
|
consoleUrl?: string | undefined
|
|
111
111
|
/** Legacy group-level transactional email sender. Prefer `App.create({ email })`. */
|
|
112
112
|
email?: Email.Sender | undefined
|
|
113
|
+
/** Routes access request options, such as a reviewer notifier; omit to send no notices. */
|
|
114
|
+
routesAccessRequests?: routesAccessRequests.Options | undefined
|
|
113
115
|
/** Webhook capability shared with the data group and host poller; omit or pass false to disable management. */
|
|
114
116
|
webhook?: App.Webhook | false | undefined
|
|
115
117
|
}
|
|
@@ -9,6 +9,7 @@ import * as TestApp from '../../../../test/App.js'
|
|
|
9
9
|
import * as Containers from '../../../../test/containers.js'
|
|
10
10
|
import * as ApiKeyAdmissions from '../../../db/tables/apiKeyAdmissions.js'
|
|
11
11
|
import * as Memberships from '../../../db/tables/memberships.js'
|
|
12
|
+
import * as ZoneDelegations from '../../../db/tables/zoneDelegations.js'
|
|
12
13
|
import * as Keys from './api-keys.js'
|
|
13
14
|
import * as Me from './me.js'
|
|
14
15
|
import * as Orgs from './orgs.js'
|
|
@@ -244,7 +245,7 @@ test('publishes generator-ready OpenAPI contracts', async () => {
|
|
|
244
245
|
"$ref": "#/components/schemas/ApiKeyMalformedOrBodyInvalidOrParamInvalidError",
|
|
245
246
|
},
|
|
246
247
|
"403": {
|
|
247
|
-
"$ref": "#/components/schemas/
|
|
248
|
+
"$ref": "#/components/schemas/ApiKeyForbiddenOrApiKeyIpForbiddenOrForbiddenOrScopeNotIssuableError",
|
|
248
249
|
},
|
|
249
250
|
"404": {
|
|
250
251
|
"$ref": "#/components/schemas/ApiKeysNotEnabledOrOrganizationNotFoundOrProjectNotFoundError",
|
|
@@ -337,7 +338,7 @@ test('publishes generator-ready OpenAPI contracts', async () => {
|
|
|
337
338
|
"$ref": "#/components/schemas/ApiKeyMalformedOrBodyInvalidOrParamInvalidError",
|
|
338
339
|
},
|
|
339
340
|
"403": {
|
|
340
|
-
"$ref": "#/components/schemas/
|
|
341
|
+
"$ref": "#/components/schemas/ForbiddenError",
|
|
341
342
|
},
|
|
342
343
|
"404": {
|
|
343
344
|
"$ref": "#/components/schemas/ApiKeyNotFoundOrApiKeysNotEnabledOrOrganizationNotFoundOrProjectNotFoundError",
|
|
@@ -554,6 +555,7 @@ describe('keys', () => {
|
|
|
554
555
|
await Memberships.create(db, { orgId: org.id, role: 'admin', userId: user.id })
|
|
555
556
|
const base = `/v1/orgs/${org.id}/projects/${project.id}/api-keys`
|
|
556
557
|
const expiresAt = new Date(Date.now() + 86_400_000).toISOString()
|
|
558
|
+
await TestApp.delegateZone(db, { chainIds: [421700001, 421700002], orgId: org.id })
|
|
557
559
|
|
|
558
560
|
// Tags and expiry only narrow a key an admin could mint anyway, so they need no owner.
|
|
559
561
|
const created = await TestApp.json(
|
|
@@ -617,8 +619,9 @@ describe('keys', () => {
|
|
|
617
619
|
)
|
|
618
620
|
await Memberships.create(db, { orgId: org.id, role: 'admin', userId: user.id })
|
|
619
621
|
const base = `/v1/orgs/${org.id}/projects/${project.id}/api-keys`
|
|
622
|
+
await TestApp.delegateZone(db, { chainIds: [421700001], orgId: org.id })
|
|
620
623
|
|
|
621
|
-
// Tags name the Zones the key reads
|
|
624
|
+
// Tags name the Zones the key reads, and must stay within the organization's delegations.
|
|
622
625
|
const response = await app.request(
|
|
623
626
|
base,
|
|
624
627
|
json('POST', admin, { scopes: ['zone:read'], zoneTags: [421700001] }),
|
|
@@ -630,6 +633,80 @@ describe('keys', () => {
|
|
|
630
633
|
})
|
|
631
634
|
})
|
|
632
635
|
|
|
636
|
+
test('generic Zone scopes are self-serve and bounded by delegated tags', async () => {
|
|
637
|
+
const db = TestApp.database()
|
|
638
|
+
const store = TestApp.kvStore({ keys: [] })
|
|
639
|
+
const app = createApp({ db, kv: { store } })
|
|
640
|
+
const owner = await session(app)
|
|
641
|
+
const { org, project } = await fixture(app, owner)
|
|
642
|
+
const admin = await session(app)
|
|
643
|
+
const user = await TestApp.json(
|
|
644
|
+
await app.request('/v1/me', { headers: { cookie: admin } }),
|
|
645
|
+
Me.schema.User,
|
|
646
|
+
)
|
|
647
|
+
await Memberships.create(db, { orgId: org.id, role: 'admin', userId: user.id })
|
|
648
|
+
const base = `/v1/orgs/${org.id}/projects/${project.id}/api-keys`
|
|
649
|
+
await TestApp.delegateZone(db, { chainIds: [421700001], orgId: org.id })
|
|
650
|
+
const revoked = await ZoneDelegations.create(db, { accountsAll: true, chainId: 421700002, environment: 'production', orgId: org.id, tokensAll: true }) // prettier-ignore
|
|
651
|
+
await ZoneDelegations.revoke(db, revoked.id)
|
|
652
|
+
await TestApp.delegateZone(db, { chainIds: [421700003], environment: 'sandbox', orgId: org.id })
|
|
653
|
+
const mint = async (body: unknown) => {
|
|
654
|
+
const response = await app.request(base, json('POST', admin, body))
|
|
655
|
+
return { body: (await response.json()) as { error?: { code: string; message: string } }, status: response.status } // prettier-ignore
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// Broadcasts need no delegation coverage at request time, so the delegation's existence bounds the tags at mint.
|
|
659
|
+
expect(await mint({ scopes: ['zone:write'] })).toMatchObject({
|
|
660
|
+
body: {
|
|
661
|
+
error: {
|
|
662
|
+
code: 'body_invalid',
|
|
663
|
+
message:
|
|
664
|
+
'invalid API key input: Zone scopes require `zoneTags` naming Zones the organization is delegated',
|
|
665
|
+
},
|
|
666
|
+
},
|
|
667
|
+
status: 400,
|
|
668
|
+
})
|
|
669
|
+
// Revoked, other-environment, and unknown Zones are all undelegated, for reads and writes alike.
|
|
670
|
+
for (const scope of ['zone:read', 'zone:write'])
|
|
671
|
+
for (const zoneTags of [[421700002], [421700003], [421700001, 421700009]])
|
|
672
|
+
expect(await mint({ scopes: [scope], zoneTags })).toMatchObject({
|
|
673
|
+
body: {
|
|
674
|
+
error: { code: 'body_invalid', message: expect.stringContaining('not delegated') },
|
|
675
|
+
},
|
|
676
|
+
status: 400,
|
|
677
|
+
})
|
|
678
|
+
expect((await mint({ scopes: ['zone:read'] })).status).toBe(400)
|
|
679
|
+
expect((await mint({ scopes: ['zone:read'], zoneTags: [421700001] })).status).toBe(200)
|
|
680
|
+
|
|
681
|
+
const created = await TestApp.json(
|
|
682
|
+
await app.request(
|
|
683
|
+
base,
|
|
684
|
+
json('POST', admin, { scopes: ['zone:read', 'zone:write'], zoneTags: [421700001] }),
|
|
685
|
+
),
|
|
686
|
+
Keys.schema.createApiKey.Response,
|
|
687
|
+
)
|
|
688
|
+
expect(created).toMatchObject({ scopes: ['zone:read', 'zone:write'], zoneTags: [421700001] })
|
|
689
|
+
expect(await ApiKeys.resolve(store, created.token)).toMatchObject({ zoneTags: [421700001] })
|
|
690
|
+
|
|
691
|
+
// Edits keep a Zone key inside its delegations; clearing the tags leaves a broadcasting key nowhere to broadcast.
|
|
692
|
+
const widened = await app.request(`${base}/${created.id}`, json('PATCH', admin, { zoneTags: [421700001, 421700002] })) // prettier-ignore
|
|
693
|
+
expect(widened.status).toBe(400)
|
|
694
|
+
expect(await widened.json()).toMatchObject({ error: { code: 'body_invalid' } })
|
|
695
|
+
const cleared = await app.request(`${base}/${created.id}`, json('PATCH', admin, { zoneTags: null })) // prettier-ignore
|
|
696
|
+
expect(cleared.status).toBe(400)
|
|
697
|
+
expect(await ApiKeys.resolve(store, created.token)).toMatchObject({ zoneTags: [421700001] })
|
|
698
|
+
const reader = await TestApp.json(
|
|
699
|
+
await app.request(base, json('POST', admin, { scopes: ['zone:read'], zoneTags: [421700001] })), // prettier-ignore
|
|
700
|
+
Keys.schema.createApiKey.Response,
|
|
701
|
+
)
|
|
702
|
+
const readerWidened = await app.request(`${base}/${reader.id}`, json('PATCH', admin, { zoneTags: [421700002] })) // prettier-ignore
|
|
703
|
+
expect(readerWidened.status).toBe(400)
|
|
704
|
+
// A read key may drop its tags: it then reads no Zone.
|
|
705
|
+
const readerCleared = await app.request(`${base}/${reader.id}`, json('PATCH', admin, { zoneTags: null })) // prettier-ignore
|
|
706
|
+
expect(readerCleared.status).toBe(200)
|
|
707
|
+
expect(await ApiKeys.resolve(store, reader.token)).not.toHaveProperty('zoneTags')
|
|
708
|
+
})
|
|
709
|
+
|
|
633
710
|
test('derives CLI keys from the source tags and keeps their expiry within the session', async () => {
|
|
634
711
|
const db = TestApp.database()
|
|
635
712
|
const store = TestApp.kvStore({ keys: [] })
|
|
@@ -637,6 +714,7 @@ describe('keys', () => {
|
|
|
637
714
|
const owner = await session(app)
|
|
638
715
|
const { org, project } = await fixture(app, owner)
|
|
639
716
|
const base = `/v1/orgs/${org.id}/projects/${project.id}/api-keys`
|
|
717
|
+
await TestApp.delegateZone(db, { chainIds: [421700002], orgId: org.id })
|
|
640
718
|
const cli = await cliSession(app, owner, ['data:read', 'zone:read'])
|
|
641
719
|
const mint = (body: unknown) =>
|
|
642
720
|
app.request(base, { body: JSON.stringify(body), headers: cli.bearer, method: 'POST' })
|
|
@@ -675,7 +753,7 @@ describe('keys', () => {
|
|
|
675
753
|
expect(shortened.expiresAt).toBe(sooner)
|
|
676
754
|
})
|
|
677
755
|
|
|
678
|
-
test('
|
|
756
|
+
test('refuses retired per-Zone read scopes and rotates tagged Zone read keys', async () => {
|
|
679
757
|
const db = TestApp.database()
|
|
680
758
|
const store = TestApp.kvStore({ keys: [] })
|
|
681
759
|
const app = createApp({ db, kv: { store } })
|
|
@@ -686,15 +764,16 @@ describe('keys', () => {
|
|
|
686
764
|
base,
|
|
687
765
|
superAdminJson('POST', { scopes: ['zone:421700001:read'] }),
|
|
688
766
|
)
|
|
689
|
-
expect(response.status).toBe(
|
|
690
|
-
expect(await response.json()).toMatchObject({ error: { code: '
|
|
767
|
+
expect(response.status).toBe(400)
|
|
768
|
+
expect(await response.json()).toMatchObject({ error: { code: 'body_invalid' } })
|
|
691
769
|
for (const projectId of [project.id, undefined]) {
|
|
692
770
|
const { record, token } = await ApiKeys.mint(store, {
|
|
693
771
|
orgId: org.id,
|
|
694
772
|
...(projectId ? { projectId } : {}),
|
|
695
|
-
scopes: ['zone:
|
|
773
|
+
scopes: ['zone:read'],
|
|
774
|
+
zoneTags: [421700001],
|
|
696
775
|
})
|
|
697
|
-
//
|
|
776
|
+
// Rotation copies policies only from admitted keys.
|
|
698
777
|
await db.transaction((tx) =>
|
|
699
778
|
ApiKeyAdmissions.admit(tx, {
|
|
700
779
|
expiresAt: null,
|
|
@@ -707,18 +786,17 @@ describe('keys', () => {
|
|
|
707
786
|
}),
|
|
708
787
|
)
|
|
709
788
|
const path = projectId ? `${base}/${record.id}` : `/v1/orgs/${org.id}/api-keys/${record.id}`
|
|
710
|
-
// Rotation copies the approved scopes unchanged, so it needs no second approval.
|
|
711
789
|
const rotation = await app.request(`${path}/rotate`, {
|
|
712
790
|
headers: { cookie: owner },
|
|
713
791
|
method: 'POST',
|
|
714
792
|
})
|
|
715
793
|
expect(rotation.status).toBe(200)
|
|
716
794
|
const rotated = await TestApp.json(rotation, Keys.schema.rotateApiKey.Response)
|
|
717
|
-
expect(rotated.scopes).toEqual(['zone:
|
|
795
|
+
expect([rotated.scopes, rotated.zoneTags]).toEqual([['zone:read'], [421700001]])
|
|
718
796
|
expect(await ApiKeys.resolve(store, rotated.token)).not.toBeNull()
|
|
719
797
|
if (projectId) {
|
|
720
798
|
const update = await app.request(path, json('PATCH', owner, { allowedIps: [] }))
|
|
721
|
-
expect(update.status).toBe(
|
|
799
|
+
expect(update.status).toBe(200)
|
|
722
800
|
}
|
|
723
801
|
expect(await ApiKeys.resolve(store, token)).not.toBeNull()
|
|
724
802
|
expect(
|
|
@@ -729,11 +807,13 @@ describe('keys', () => {
|
|
|
729
807
|
})
|
|
730
808
|
|
|
731
809
|
test('rotates a super-admin-issued Zone write key without delegating scope issuance', async () => {
|
|
810
|
+
const db = TestApp.database()
|
|
732
811
|
const store = TestApp.kvStore({ keys: [] })
|
|
733
|
-
const app = createApp({ kv: { store } })
|
|
812
|
+
const app = createApp({ db, kv: { store } })
|
|
734
813
|
const owner = await session(app)
|
|
735
814
|
const { org, project } = await fixture(app, owner)
|
|
736
815
|
const base = `/v1/orgs/${org.id}/projects/${project.id}/api-keys`
|
|
816
|
+
await TestApp.delegateZone(db, { chainIds: [421700001], orgId: org.id })
|
|
737
817
|
const source = await TestApp.json(
|
|
738
818
|
await app.request(
|
|
739
819
|
base,
|
|
@@ -741,7 +821,8 @@ describe('keys', () => {
|
|
|
741
821
|
allowedIps: ['203.0.113.0/24'],
|
|
742
822
|
environment: 'production',
|
|
743
823
|
name: 'Privy',
|
|
744
|
-
scopes: ['zone:
|
|
824
|
+
scopes: ['zone:write'],
|
|
825
|
+
zoneTags: [421700001],
|
|
745
826
|
}),
|
|
746
827
|
),
|
|
747
828
|
Keys.schema.createApiKey.Response,
|
|
@@ -759,7 +840,8 @@ describe('keys', () => {
|
|
|
759
840
|
name: 'Privy',
|
|
760
841
|
orgId: org.id,
|
|
761
842
|
projectId: project.id,
|
|
762
|
-
scopes: ['zone:
|
|
843
|
+
scopes: ['zone:write'],
|
|
844
|
+
zoneTags: [421700001],
|
|
763
845
|
})
|
|
764
846
|
expect(replacement.createdBy).not.toBe('super_admin')
|
|
765
847
|
expect(replacement.id).not.toBe(source.id)
|
|
@@ -834,10 +916,12 @@ describe('keys', () => {
|
|
|
834
916
|
)
|
|
835
917
|
|
|
836
918
|
test('rotates an organization-level super-admin-issued zone key', async () => {
|
|
919
|
+
const db = TestApp.database()
|
|
837
920
|
const store = TestApp.kvStore({ keys: [] })
|
|
838
|
-
const app = createApp({ kv: { store } })
|
|
921
|
+
const app = createApp({ db, kv: { store } })
|
|
839
922
|
const owner = await session(app)
|
|
840
923
|
const { org, project } = await fixture(app, owner)
|
|
924
|
+
await TestApp.delegateZone(db, { chainIds: [421700001], orgId: org.id })
|
|
841
925
|
const { record: projectSource } = await ApiKeys.mint(store, {
|
|
842
926
|
orgId: org.id,
|
|
843
927
|
projectId: project.id,
|
|
@@ -859,7 +943,8 @@ describe('keys', () => {
|
|
|
859
943
|
environment: 'production',
|
|
860
944
|
name: 'Privy',
|
|
861
945
|
orgId: org.id,
|
|
862
|
-
scopes: ['zone:
|
|
946
|
+
scopes: ['zone:write'],
|
|
947
|
+
zoneTags: [421700001],
|
|
863
948
|
})
|
|
864
949
|
|
|
865
950
|
const response = await app.request(`/v1/orgs/${org.id}/api-keys/${source.id}/rotate`, {
|
|
@@ -872,7 +957,8 @@ describe('keys', () => {
|
|
|
872
957
|
environment: 'production',
|
|
873
958
|
name: 'Privy',
|
|
874
959
|
orgId: org.id,
|
|
875
|
-
scopes: ['zone:
|
|
960
|
+
scopes: ['zone:write'],
|
|
961
|
+
zoneTags: [421700001],
|
|
876
962
|
})
|
|
877
963
|
expect(replacement.projectId).toBeUndefined()
|
|
878
964
|
expect(replacement.createdBy).not.toBe('super_admin')
|
|
@@ -913,10 +999,12 @@ describe('keys', () => {
|
|
|
913
999
|
projectId: project.id,
|
|
914
1000
|
scopes: ['data:read', 'webhooks:write'],
|
|
915
1001
|
})
|
|
1002
|
+
await TestApp.delegateZone(db, { chainIds: [421700001], orgId: org.id })
|
|
916
1003
|
const { record: zone } = await ApiKeys.mintBounded(db, store, {
|
|
917
1004
|
createdBy: 'super_admin',
|
|
918
1005
|
orgId: org.id,
|
|
919
|
-
scopes: ['zone:
|
|
1006
|
+
scopes: ['zone:write'],
|
|
1007
|
+
zoneTags: [421700001],
|
|
920
1008
|
})
|
|
921
1009
|
const paths = [`${base}/${webhooks.id}`, `/v1/orgs/${org.id}/api-keys/${zone.id}`]
|
|
922
1010
|
|
|
@@ -950,8 +1038,10 @@ describe('keys', () => {
|
|
|
950
1038
|
},
|
|
951
1039
|
{
|
|
952
1040
|
"caller": "admin",
|
|
953
|
-
"
|
|
954
|
-
|
|
1041
|
+
"scopes": [
|
|
1042
|
+
"zone:write",
|
|
1043
|
+
],
|
|
1044
|
+
"status": 200,
|
|
955
1045
|
},
|
|
956
1046
|
{
|
|
957
1047
|
"caller": "owner",
|
|
@@ -964,7 +1054,7 @@ describe('keys', () => {
|
|
|
964
1054
|
{
|
|
965
1055
|
"caller": "owner",
|
|
966
1056
|
"scopes": [
|
|
967
|
-
"zone:
|
|
1057
|
+
"zone:write",
|
|
968
1058
|
],
|
|
969
1059
|
"status": 200,
|
|
970
1060
|
},
|
|
@@ -1047,7 +1137,7 @@ describe('keys', () => {
|
|
|
1047
1137
|
const source = await TestApp.json(
|
|
1048
1138
|
await app.request(
|
|
1049
1139
|
`/v1/orgs/${org.id}/projects/${project.id}/api-keys`,
|
|
1050
|
-
superAdminJson('POST', { scopes: ['
|
|
1140
|
+
superAdminJson('POST', { scopes: ['webhooks:write'] }),
|
|
1051
1141
|
),
|
|
1052
1142
|
Keys.schema.createApiKey.Response,
|
|
1053
1143
|
)
|
|
@@ -37,12 +37,10 @@ export namespace schema {
|
|
|
37
37
|
),
|
|
38
38
|
z.meta({ examples: [['203.0.113.0/24', '2001:db8::1']] }),
|
|
39
39
|
),
|
|
40
|
-
createdAt:
|
|
41
|
-
.
|
|
42
|
-
.
|
|
43
|
-
|
|
44
|
-
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
45
|
-
),
|
|
40
|
+
createdAt: Schema.dateTime().check(
|
|
41
|
+
z.describe('When the key was minted (ISO 8601).'),
|
|
42
|
+
z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
|
|
43
|
+
),
|
|
46
44
|
createdBy: z
|
|
47
45
|
.optional(z.string())
|
|
48
46
|
.check(
|
|
@@ -53,7 +51,7 @@ export namespace schema {
|
|
|
53
51
|
.enum(['production', 'sandbox'])
|
|
54
52
|
.check(z.describe('Key environment.'), z.meta({ examples: ['sandbox'] })),
|
|
55
53
|
expiresAt: z
|
|
56
|
-
.optional(
|
|
54
|
+
.optional(Schema.dateTime())
|
|
57
55
|
.check(
|
|
58
56
|
z.describe('When the key expires (ISO 8601). Absent for a non-expiring key.'),
|
|
59
57
|
z.meta({ examples: ['2027-01-01T00:00:00.000Z'] }),
|
|
@@ -64,7 +62,7 @@ export namespace schema {
|
|
|
64
62
|
z.describe('Opaque key id (`key_…`).'),
|
|
65
63
|
z.meta({ examples: ['key_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
|
|
66
64
|
),
|
|
67
|
-
lastUsedAt: z.optional(
|
|
65
|
+
lastUsedAt: z.optional(Schema.dateTime()).check(
|
|
68
66
|
z.describe('When the key last authenticated a request (ISO 8601). Omitted with `include=` or when no usage is available.'), // prettier-ignore
|
|
69
67
|
z.meta({ examples: ['2026-07-21T12:34:56.000Z'] }),
|
|
70
68
|
),
|
|
@@ -220,7 +218,7 @@ export namespace schema {
|
|
|
220
218
|
),
|
|
221
219
|
zoneTags: ApiKey.schema.ApiKey.shape.zoneTags.check(
|
|
222
220
|
z.describe(
|
|
223
|
-
"Zone chain ids the key may read among the organization's delegations. Omit for a key that
|
|
221
|
+
"Zone chain ids the key may read or broadcast to among the organization's delegations. Required with `zone:read` or `zone:write`, naming only delegated Zones. Omit for a key that uses no Zone.",
|
|
224
222
|
),
|
|
225
223
|
),
|
|
226
224
|
})
|
|
@@ -342,7 +340,9 @@ export namespace schema {
|
|
|
342
340
|
zoneTags: z
|
|
343
341
|
.optional(z.nullable(ApiKey.schema.ZoneTags))
|
|
344
342
|
.check(
|
|
345
|
-
z.describe(
|
|
343
|
+
z.describe(
|
|
344
|
+
'Replacement Zone chain id tags, or `null` to use no Zone. Tags stay within delegated Zones.',
|
|
345
|
+
),
|
|
346
346
|
z.meta({ examples: [[421700001]] }),
|
|
347
347
|
),
|
|
348
348
|
})
|
|
@@ -382,7 +382,7 @@ export function apiKeys(options: apiKeys.Options = {}) {
|
|
|
382
382
|
description: 'Malformed API key, invalid path, or invalid body.',
|
|
383
383
|
},
|
|
384
384
|
403: {
|
|
385
|
-
codes: ['scope_not_issuable'
|
|
385
|
+
codes: ['scope_not_issuable'],
|
|
386
386
|
description: 'The requested scopes are not issuable.',
|
|
387
387
|
},
|
|
388
388
|
404: {
|
|
@@ -454,6 +454,14 @@ export function apiKeys(options: apiKeys.Options = {}) {
|
|
|
454
454
|
})
|
|
455
455
|
try {
|
|
456
456
|
const orgId = Auth.org(c).id
|
|
457
|
+
// Self-serve Zone read keys name only delegated Zones; derived keys copy their
|
|
458
|
+
// source's already bounded tags, and `zone:write` is checked inside the mint.
|
|
459
|
+
if (!source && body.scopes.includes('zone:read'))
|
|
460
|
+
await ApiKeys.ensureDelegatedTags(Db.get(c.get('db')), {
|
|
461
|
+
environment: body.environment,
|
|
462
|
+
orgId,
|
|
463
|
+
zoneTags: body.zoneTags,
|
|
464
|
+
})
|
|
457
465
|
// Snapshot billing onto the record so the auth path throttles a
|
|
458
466
|
// sandbox key to the public quota without a per-request billing read.
|
|
459
467
|
// Only sandbox is gated; production keys carry no snapshot.
|
|
@@ -796,9 +804,8 @@ export function apiKeys(options: apiKeys.Options = {}) {
|
|
|
796
804
|
description: 'Malformed API key, invalid path, or invalid body.',
|
|
797
805
|
},
|
|
798
806
|
403: {
|
|
799
|
-
codes: ['forbidden'
|
|
800
|
-
description:
|
|
801
|
-
'Widening a reviewed Zone key, or changing anything but its tags and expiry, needs a new approved issuance request.',
|
|
807
|
+
codes: ['forbidden'],
|
|
808
|
+
description: 'The caller may not change this key.',
|
|
802
809
|
},
|
|
803
810
|
404: {
|
|
804
811
|
codes: [
|
|
@@ -855,6 +862,14 @@ export function apiKeys(options: apiKeys.Options = {}) {
|
|
|
855
862
|
message: 'An expiry can only move earlier. Mint a new key to extend it.',
|
|
856
863
|
status: 400,
|
|
857
864
|
})
|
|
865
|
+
// Replacement tags on a Zone key stay within the organization's delegations; `null`
|
|
866
|
+
// leaves it using no Zone, which narrows (and a write key refuses it inside the update).
|
|
867
|
+
if (body.zoneTags && record.scopes.some((scope) => scope.startsWith('zone:')))
|
|
868
|
+
await ApiKeys.ensureDelegatedTags(Db.get(c.get('db')), {
|
|
869
|
+
environment: record.environment,
|
|
870
|
+
orgId: record.orgId,
|
|
871
|
+
zoneTags: body.zoneTags,
|
|
872
|
+
})
|
|
858
873
|
const updated = await ApiKeys.updateBounded(Db.get(c.get('db')), kv.store, keyId, body, {
|
|
859
874
|
expectedOwner: { orgId: Auth.org(c).id, projectId: Auth.project(c).id },
|
|
860
875
|
scopeCatalog: c.get('scopeCatalog'),
|
|
@@ -1091,7 +1106,7 @@ function canRotate(c: Context<App.Environment>, scopes: readonly Scope.Id[]) {
|
|
|
1091
1106
|
if (principal?.type === 'super_admin') return true
|
|
1092
1107
|
if (principal?.type !== 'session') return false
|
|
1093
1108
|
const selfServe = Scope.selfServeFrom(c.get('scopeCatalog'))
|
|
1094
|
-
// Rotation returns a new token, so copying restricted grants (Routes, webhooks, Zone, wildcard) stays owner-only.
|
|
1109
|
+
// Rotation returns a new token, so copying restricted grants (Routes, webhooks, per-Zone, wildcard) stays owner-only.
|
|
1095
1110
|
return (
|
|
1096
1111
|
(!principal.cli || scopes.every((scope) => principal.cli!.scopes.includes(scope))) &&
|
|
1097
1112
|
((scopes.every((scope) => selfServe.includes(scope)) && !scopes.includes('management:write')) ||
|