tapimo 0.11.0 → 0.13.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.
Files changed (443) hide show
  1. package/dist/App.d.ts +6396 -4575
  2. package/dist/App.d.ts.map +1 -1
  3. package/dist/App.js +39 -4
  4. package/dist/App.js.map +1 -1
  5. package/dist/Assets.d.ts +15 -0
  6. package/dist/Assets.d.ts.map +1 -1
  7. package/dist/Assets.js +7 -0
  8. package/dist/Assets.js.map +1 -1
  9. package/dist/Scope.d.ts +2 -0
  10. package/dist/Scope.d.ts.map +1 -1
  11. package/dist/Scope.js +17 -0
  12. package/dist/Scope.js.map +1 -1
  13. package/dist/admin/App.d.ts +176 -78
  14. package/dist/admin/App.d.ts.map +1 -1
  15. package/dist/admin/apps/api-keys.d.ts +84 -4
  16. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  17. package/dist/admin/apps/api-keys.js +54 -0
  18. package/dist/admin/apps/api-keys.js.map +1 -1
  19. package/dist/admin/apps/earn-vaults.d.ts +123 -9
  20. package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
  21. package/dist/admin/apps/earn-vaults.js +60 -7
  22. package/dist/admin/apps/earn-vaults.js.map +1 -1
  23. package/dist/admin/apps/organizations.d.ts.map +1 -1
  24. package/dist/admin/apps/organizations.js +4 -2
  25. package/dist/admin/apps/organizations.js.map +1 -1
  26. package/dist/admin/apps/verified-tokens.d.ts +90 -90
  27. package/dist/admin/ui.generated.d.ts +1 -1
  28. package/dist/admin/ui.generated.js +71 -71
  29. package/dist/admin/ui.generated.js.map +1 -1
  30. package/dist/apps/Zones.d.ts +16 -16
  31. package/dist/apps/Zones.js +4 -4
  32. package/dist/apps/data/App.d.ts +1699 -749
  33. package/dist/apps/data/App.d.ts.map +1 -1
  34. package/dist/apps/data/App.js +58 -9
  35. package/dist/apps/data/App.js.map +1 -1
  36. package/dist/apps/data/ZoneSelection.d.ts +62 -0
  37. package/dist/apps/data/ZoneSelection.d.ts.map +1 -0
  38. package/dist/apps/data/ZoneSelection.js +44 -0
  39. package/dist/apps/data/ZoneSelection.js.map +1 -0
  40. package/dist/apps/data/routes/activities.d.ts +2417 -50
  41. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  42. package/dist/apps/data/routes/activities.js +1896 -1293
  43. package/dist/apps/data/routes/activities.js.map +1 -1
  44. package/dist/apps/data/routes/addresses.d.ts +471 -340
  45. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  46. package/dist/apps/data/routes/balances.d.ts +12 -12
  47. package/dist/apps/data/routes/balances.d.ts.map +1 -1
  48. package/dist/apps/data/routes/balances.js +44 -17
  49. package/dist/apps/data/routes/balances.js.map +1 -1
  50. package/dist/apps/data/routes/blocks.d.ts +42 -42
  51. package/dist/apps/data/routes/blocks.d.ts.map +1 -1
  52. package/dist/apps/data/routes/blocks.js +22 -12
  53. package/dist/apps/data/routes/blocks.js.map +1 -1
  54. package/dist/apps/data/routes/coingecko.d.ts +179 -179
  55. package/dist/apps/data/routes/earn.d.ts +144 -19
  56. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  57. package/dist/apps/data/routes/earn.js +160 -28
  58. package/dist/apps/data/routes/earn.js.map +1 -1
  59. package/dist/apps/data/routes/exchanges.d.ts +719 -13
  60. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  61. package/dist/apps/data/routes/exchanges.js +16 -13
  62. package/dist/apps/data/routes/exchanges.js.map +1 -1
  63. package/dist/apps/data/routes/fee-amm.d.ts +2 -2
  64. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  65. package/dist/apps/data/routes/fee-amm.js +9 -11
  66. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  67. package/dist/apps/data/routes/indexer.d.ts +34 -34
  68. package/dist/apps/data/routes/receipts.d.ts +363 -263
  69. package/dist/apps/data/routes/receipts.d.ts.map +1 -1
  70. package/dist/apps/data/routes/receipts.js +29 -11
  71. package/dist/apps/data/routes/receipts.js.map +1 -1
  72. package/dist/apps/data/routes/rpc.js +24 -10
  73. package/dist/apps/data/routes/rpc.js.map +1 -1
  74. package/dist/apps/data/routes/tokenlist.d.ts +13 -13
  75. package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
  76. package/dist/apps/data/routes/tokenlist.js +16 -15
  77. package/dist/apps/data/routes/tokenlist.js.map +1 -1
  78. package/dist/apps/data/routes/tokens.d.ts +112 -98
  79. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  80. package/dist/apps/data/routes/tokens.js +85 -35
  81. package/dist/apps/data/routes/tokens.js.map +1 -1
  82. package/dist/apps/data/routes/transactions.d.ts +7 -2
  83. package/dist/apps/data/routes/transactions.d.ts.map +1 -1
  84. package/dist/apps/data/routes/transactions.js +38 -18
  85. package/dist/apps/data/routes/transactions.js.map +1 -1
  86. package/dist/apps/data/routes/transfers.d.ts +1 -1
  87. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  88. package/dist/apps/data/routes/transfers.js +25 -21
  89. package/dist/apps/data/routes/transfers.js.map +1 -1
  90. package/dist/apps/data/routes/valuation.d.ts +1 -1
  91. package/dist/apps/data/routes/valuation.d.ts.map +1 -1
  92. package/dist/apps/data/routes/valuation.js +12 -7
  93. package/dist/apps/data/routes/valuation.js.map +1 -1
  94. package/dist/apps/data/routes/verified-tokens.d.ts +3 -3
  95. package/dist/apps/data/routes/webhooks.d.ts +15 -15
  96. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  97. package/dist/apps/data/routes/webhooks.js +2 -2
  98. package/dist/apps/data/routes/webhooks.js.map +1 -1
  99. package/dist/apps/data/routes/zones.d.ts +32 -32
  100. package/dist/apps/data/routes/zones.js +1 -1
  101. package/dist/apps/funding/App.d.ts +38 -27
  102. package/dist/apps/funding/App.d.ts.map +1 -1
  103. package/dist/apps/funding/routes/chains.d.ts.map +1 -1
  104. package/dist/apps/funding/routes/chains.js +5 -4
  105. package/dist/apps/funding/routes/chains.js.map +1 -1
  106. package/dist/apps/funding/routes/deposit-addresses.d.ts +16 -16
  107. package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
  108. package/dist/apps/funding/routes/deposit-addresses.js +24 -19
  109. package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
  110. package/dist/apps/funding/routes/providers.d.ts +13 -13
  111. package/dist/apps/funding/routes/providers.d.ts.map +1 -1
  112. package/dist/apps/funding/routes/providers.js +3 -2
  113. package/dist/apps/funding/routes/providers.js.map +1 -1
  114. package/dist/apps/funding/routes/quotes.d.ts.map +1 -1
  115. package/dist/apps/funding/routes/quotes.js +2 -2
  116. package/dist/apps/funding/routes/quotes.js.map +1 -1
  117. package/dist/apps/funding/routes/transfers.d.ts +60 -48
  118. package/dist/apps/funding/routes/transfers.d.ts.map +1 -1
  119. package/dist/apps/funding/routes/transfers.js +27 -19
  120. package/dist/apps/funding/routes/transfers.js.map +1 -1
  121. package/dist/apps/management/App.d.ts +4558 -3700
  122. package/dist/apps/management/App.d.ts.map +1 -1
  123. package/dist/apps/management/Billing.d.ts.map +1 -1
  124. package/dist/apps/management/Billing.js +19 -6
  125. package/dist/apps/management/Billing.js.map +1 -1
  126. package/dist/apps/management/routes/api-keys.d.ts +786 -175
  127. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  128. package/dist/apps/management/routes/api-keys.js +312 -34
  129. package/dist/apps/management/routes/api-keys.js.map +1 -1
  130. package/dist/apps/management/routes/billing.d.ts +103 -30
  131. package/dist/apps/management/routes/billing.d.ts.map +1 -1
  132. package/dist/apps/management/routes/billing.js +91 -32
  133. package/dist/apps/management/routes/billing.js.map +1 -1
  134. package/dist/apps/management/routes/faucet.d.ts +35 -35
  135. package/dist/apps/management/routes/faucet.d.ts.map +1 -1
  136. package/dist/apps/management/routes/faucet.js +23 -12
  137. package/dist/apps/management/routes/faucet.js.map +1 -1
  138. package/dist/apps/management/routes/invitations.d.ts +46 -13
  139. package/dist/apps/management/routes/invitations.d.ts.map +1 -1
  140. package/dist/apps/management/routes/invitations.js +79 -29
  141. package/dist/apps/management/routes/invitations.js.map +1 -1
  142. package/dist/apps/management/routes/invite-links.d.ts +120 -75
  143. package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
  144. package/dist/apps/management/routes/invite-links.js +100 -41
  145. package/dist/apps/management/routes/invite-links.js.map +1 -1
  146. package/dist/apps/management/routes/me.d.ts +5 -5
  147. package/dist/apps/management/routes/me.d.ts.map +1 -1
  148. package/dist/apps/management/routes/me.js +14 -10
  149. package/dist/apps/management/routes/me.js.map +1 -1
  150. package/dist/apps/management/routes/members.d.ts +99 -78
  151. package/dist/apps/management/routes/members.d.ts.map +1 -1
  152. package/dist/apps/management/routes/members.js +37 -18
  153. package/dist/apps/management/routes/members.js.map +1 -1
  154. package/dist/apps/management/routes/orgs.d.ts +48 -8
  155. package/dist/apps/management/routes/orgs.d.ts.map +1 -1
  156. package/dist/apps/management/routes/orgs.js +48 -19
  157. package/dist/apps/management/routes/orgs.js.map +1 -1
  158. package/dist/apps/management/routes/projects.d.ts +108 -46
  159. package/dist/apps/management/routes/projects.d.ts.map +1 -1
  160. package/dist/apps/management/routes/projects.js +72 -21
  161. package/dist/apps/management/routes/projects.js.map +1 -1
  162. package/dist/apps/management/routes/scopes.d.ts.map +1 -1
  163. package/dist/apps/management/routes/scopes.js +8 -5
  164. package/dist/apps/management/routes/scopes.js.map +1 -1
  165. package/dist/apps/management/routes/usage.d.ts +82 -82
  166. package/dist/apps/management/routes/usage.d.ts.map +1 -1
  167. package/dist/apps/management/routes/usage.js +41 -31
  168. package/dist/apps/management/routes/usage.js.map +1 -1
  169. package/dist/apps/management/routes/verified-token-requests.d.ts +35 -7
  170. package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
  171. package/dist/apps/management/routes/verified-token-requests.js +36 -17
  172. package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
  173. package/dist/apps/management/routes/webhooks.d.ts +200 -183
  174. package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
  175. package/dist/apps/management/routes/webhooks.js +80 -35
  176. package/dist/apps/management/routes/webhooks.js.map +1 -1
  177. package/dist/apps/mpp/internal/Adapter.d.ts +1 -1
  178. package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
  179. package/dist/apps/mpp/internal/Adapter.js +12 -0
  180. package/dist/apps/mpp/internal/Adapter.js.map +1 -1
  181. package/dist/db/Db.d.ts +2 -0
  182. package/dist/db/Db.d.ts.map +1 -1
  183. package/dist/db/Db.js +52 -1
  184. package/dist/db/Db.js.map +1 -1
  185. package/dist/db/Schema.d.ts +26 -3
  186. package/dist/db/Schema.d.ts.map +1 -1
  187. package/dist/db/Schema.js +24 -5
  188. package/dist/db/Schema.js.map +1 -1
  189. package/dist/db/tables/earnVaults.d.ts +5 -1
  190. package/dist/db/tables/earnVaults.d.ts.map +1 -1
  191. package/dist/db/tables/earnVaults.js +5 -0
  192. package/dist/db/tables/earnVaults.js.map +1 -1
  193. package/dist/db/tables/fundingCatalog.d.ts +4 -2
  194. package/dist/db/tables/fundingCatalog.d.ts.map +1 -1
  195. package/dist/db/tables/fundingCatalog.js +5 -1
  196. package/dist/db/tables/fundingCatalog.js.map +1 -1
  197. package/dist/db/tables/webhookDeliveries.d.ts.map +1 -1
  198. package/dist/db/tables/webhookDeliveries.js +10 -0
  199. package/dist/db/tables/webhookDeliveries.js.map +1 -1
  200. package/dist/db/tables/webhookQueueCompletions.d.ts +15 -0
  201. package/dist/db/tables/webhookQueueCompletions.d.ts.map +1 -0
  202. package/dist/db/tables/webhookQueueCompletions.js +32 -0
  203. package/dist/db/tables/webhookQueueCompletions.js.map +1 -0
  204. package/dist/db/tables/webhookQueueEvents.d.ts +14 -20
  205. package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
  206. package/dist/db/tables/webhookQueueEvents.js +68 -47
  207. package/dist/db/tables/webhookQueueEvents.js.map +1 -1
  208. package/dist/db/tables/webhookSubscriptions.d.ts +16 -5
  209. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  210. package/dist/db/tables/webhookSubscriptions.js +29 -5
  211. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  212. package/dist/handlers/internal/utils.d.ts.map +1 -1
  213. package/dist/handlers/internal/utils.js +9 -0
  214. package/dist/handlers/internal/utils.js.map +1 -1
  215. package/dist/internal/Auth.d.ts +11 -2
  216. package/dist/internal/Auth.d.ts.map +1 -1
  217. package/dist/internal/Auth.js +19 -6
  218. package/dist/internal/Auth.js.map +1 -1
  219. package/dist/internal/Cache.d.ts.map +1 -1
  220. package/dist/internal/Cache.js +11 -7
  221. package/dist/internal/Cache.js.map +1 -1
  222. package/dist/internal/EarnVaults.d.ts +43 -4
  223. package/dist/internal/EarnVaults.d.ts.map +1 -1
  224. package/dist/internal/EarnVaults.js +167 -0
  225. package/dist/internal/EarnVaults.js.map +1 -1
  226. package/dist/internal/Fetch.d.ts +23 -0
  227. package/dist/internal/Fetch.d.ts.map +1 -0
  228. package/dist/internal/Fetch.js +26 -0
  229. package/dist/internal/Fetch.js.map +1 -0
  230. package/dist/internal/Log.d.ts +3 -1
  231. package/dist/internal/Log.d.ts.map +1 -1
  232. package/dist/internal/Log.js +16 -3
  233. package/dist/internal/Log.js.map +1 -1
  234. package/dist/internal/OpenApi.d.ts +30 -24
  235. package/dist/internal/OpenApi.d.ts.map +1 -1
  236. package/dist/internal/OpenApi.js +140 -41
  237. package/dist/internal/OpenApi.js.map +1 -1
  238. package/dist/internal/Response.d.ts +14 -9
  239. package/dist/internal/Response.d.ts.map +1 -1
  240. package/dist/internal/Response.js +16 -5
  241. package/dist/internal/Response.js.map +1 -1
  242. package/dist/internal/Schema.d.ts +11 -10
  243. package/dist/internal/Schema.d.ts.map +1 -1
  244. package/dist/internal/Schema.js +14 -9
  245. package/dist/internal/Schema.js.map +1 -1
  246. package/dist/internal/Store.d.ts +28 -6
  247. package/dist/internal/Store.d.ts.map +1 -1
  248. package/dist/internal/Store.js +121 -25
  249. package/dist/internal/Store.js.map +1 -1
  250. package/dist/internal/Tidx.d.ts +2 -0
  251. package/dist/internal/Tidx.d.ts.map +1 -1
  252. package/dist/internal/Tidx.js +23 -6
  253. package/dist/internal/Tidx.js.map +1 -1
  254. package/dist/internal/Timeout.d.ts +36 -0
  255. package/dist/internal/Timeout.d.ts.map +1 -0
  256. package/dist/internal/Timeout.js +37 -0
  257. package/dist/internal/Timeout.js.map +1 -0
  258. package/dist/internal/Timing.d.ts +9 -0
  259. package/dist/internal/Timing.d.ts.map +1 -1
  260. package/dist/internal/Timing.js +7 -0
  261. package/dist/internal/Timing.js.map +1 -1
  262. package/dist/internal/WebhookDestination.d.ts.map +1 -1
  263. package/dist/internal/WebhookDestination.js +3 -0
  264. package/dist/internal/WebhookDestination.js.map +1 -1
  265. package/dist/internal/Webhooks.d.ts +29 -12
  266. package/dist/internal/Webhooks.d.ts.map +1 -1
  267. package/dist/internal/Webhooks.js +37 -20
  268. package/dist/internal/Webhooks.js.map +1 -1
  269. package/dist/internal/funding/Action.d.ts +9 -0
  270. package/dist/internal/funding/Action.d.ts.map +1 -1
  271. package/dist/internal/funding/Action.js +16 -8
  272. package/dist/internal/funding/Action.js.map +1 -1
  273. package/dist/internal/funding/Catalog.d.ts +9 -2
  274. package/dist/internal/funding/Catalog.d.ts.map +1 -1
  275. package/dist/internal/funding/Catalog.js +19 -8
  276. package/dist/internal/funding/Catalog.js.map +1 -1
  277. package/dist/internal/funding/Deposit.d.ts +2 -2
  278. package/dist/internal/funding/Deposit.d.ts.map +1 -1
  279. package/dist/internal/funding/Deposit.js +9 -8
  280. package/dist/internal/funding/Deposit.js.map +1 -1
  281. package/dist/internal/funding/DepositAddress.d.ts +4 -4
  282. package/dist/internal/funding/DepositAddress.d.ts.map +1 -1
  283. package/dist/internal/funding/DepositAddress.js +9 -8
  284. package/dist/internal/funding/DepositAddress.js.map +1 -1
  285. package/dist/internal/funding/Provider.d.ts +68 -13
  286. package/dist/internal/funding/Provider.d.ts.map +1 -1
  287. package/dist/internal/funding/Provider.js +42 -20
  288. package/dist/internal/funding/Provider.js.map +1 -1
  289. package/dist/internal/funding/Transfer.d.ts +13 -12
  290. package/dist/internal/funding/Transfer.d.ts.map +1 -1
  291. package/dist/internal/funding/Transfer.js +23 -21
  292. package/dist/internal/funding/Transfer.js.map +1 -1
  293. package/dist/internal/funding/providers/stargate.d.ts +38 -0
  294. package/dist/internal/funding/providers/stargate.d.ts.map +1 -0
  295. package/dist/internal/funding/providers/stargate.js +277 -0
  296. package/dist/internal/funding/providers/stargate.js.map +1 -0
  297. package/dist/internal/index.d.ts +1 -0
  298. package/dist/internal/index.d.ts.map +1 -1
  299. package/dist/internal/index.js +1 -0
  300. package/dist/internal/index.js.map +1 -1
  301. package/dist/providers/index.d.ts +7 -0
  302. package/dist/providers/index.d.ts.map +1 -1
  303. package/dist/providers/index.js +3 -0
  304. package/dist/providers/index.js.map +1 -1
  305. package/package.json +3 -3
  306. package/src/App.test.ts +148 -0
  307. package/src/App.ts +45 -4
  308. package/src/Assets.test.ts +18 -0
  309. package/src/Assets.ts +22 -0
  310. package/src/Client.test-d.ts +311 -16
  311. package/src/Scope.test.ts +20 -0
  312. package/src/Scope.ts +16 -0
  313. package/src/admin/apps/api-keys.test.ts +75 -0
  314. package/src/admin/apps/api-keys.ts +64 -0
  315. package/src/admin/apps/earn-vaults.test.ts +143 -0
  316. package/src/admin/apps/earn-vaults.ts +84 -7
  317. package/src/admin/apps/organizations.ts +6 -2
  318. package/src/admin/ui/src/lib/api-keys.ts +19 -0
  319. package/src/admin/ui/src/routes/api-keys.tsx +125 -2
  320. package/src/admin/ui.generated.ts +71 -71
  321. package/src/apps/Zones.test.ts +4 -4
  322. package/src/apps/Zones.ts +4 -4
  323. package/src/apps/composition.test.ts +1 -1
  324. package/src/apps/data/App.test.ts +72 -0
  325. package/src/apps/data/App.ts +58 -10
  326. package/src/apps/data/ZoneSelection.test.ts +196 -0
  327. package/src/apps/data/ZoneSelection.ts +108 -0
  328. package/src/apps/data/routes/activities.test.ts +1843 -2
  329. package/src/apps/data/routes/activities.ts +2211 -1388
  330. package/src/apps/data/routes/balances.ts +134 -98
  331. package/src/apps/data/routes/blocks.test.ts +533 -0
  332. package/src/apps/data/routes/blocks.ts +36 -17
  333. package/src/apps/data/routes/earn.test.ts +187 -25
  334. package/src/apps/data/routes/earn.ts +228 -32
  335. package/src/apps/data/routes/earn.zone-access.test.ts +46 -0
  336. package/src/apps/data/routes/exchanges.test.ts +31 -1
  337. package/src/apps/data/routes/exchanges.ts +19 -15
  338. package/src/apps/data/routes/fee-amm.ts +18 -11
  339. package/src/apps/data/routes/receipts.ts +48 -17
  340. package/src/apps/data/routes/rpc.test.ts +75 -0
  341. package/src/apps/data/routes/rpc.ts +23 -9
  342. package/src/apps/data/routes/tokenlist.ts +21 -18
  343. package/src/apps/data/routes/tokens.test.ts +607 -0
  344. package/src/apps/data/routes/tokens.ts +312 -231
  345. package/src/apps/data/routes/transactions.ts +69 -30
  346. package/src/apps/data/routes/transfers.test.ts +424 -3
  347. package/src/apps/data/routes/transfers.ts +57 -36
  348. package/src/apps/data/routes/valuation.ts +94 -78
  349. package/src/apps/data/routes/webhooks.ts +6 -2
  350. package/src/apps/data/routes/zones.test.ts +21 -15
  351. package/src/apps/data/routes/zones.ts +1 -1
  352. package/src/apps/funding/routes/chains.test.ts +211 -7
  353. package/src/apps/funding/routes/chains.ts +19 -12
  354. package/src/apps/funding/routes/deposit-addresses.test.ts +416 -0
  355. package/src/apps/funding/routes/deposit-addresses.ts +101 -84
  356. package/src/apps/funding/routes/providers.ts +9 -5
  357. package/src/apps/funding/routes/quotes.test.ts +42 -0
  358. package/src/apps/funding/routes/quotes.ts +8 -5
  359. package/src/apps/funding/routes/transfers.test.ts +430 -40
  360. package/src/apps/funding/routes/transfers.ts +76 -59
  361. package/src/apps/management/Billing.test.ts +26 -0
  362. package/src/apps/management/Billing.ts +24 -7
  363. package/src/apps/management/routes/api-keys.test.ts +398 -0
  364. package/src/apps/management/routes/api-keys.ts +481 -145
  365. package/src/apps/management/routes/billing.test.ts +209 -0
  366. package/src/apps/management/routes/billing.ts +254 -177
  367. package/src/apps/management/routes/faucet.test.ts +39 -0
  368. package/src/apps/management/routes/faucet.ts +75 -41
  369. package/src/apps/management/routes/invitations.test.ts +216 -0
  370. package/src/apps/management/routes/invitations.ts +186 -109
  371. package/src/apps/management/routes/invite-links.test.ts +263 -1
  372. package/src/apps/management/routes/invite-links.ts +295 -214
  373. package/src/apps/management/routes/me.test.ts +49 -0
  374. package/src/apps/management/routes/me.ts +42 -32
  375. package/src/apps/management/routes/members.test.ts +124 -1
  376. package/src/apps/management/routes/members.ts +81 -51
  377. package/src/apps/management/routes/orgs.test.ts +176 -0
  378. package/src/apps/management/routes/orgs.ts +101 -59
  379. package/src/apps/management/routes/projects.test.ts +183 -0
  380. package/src/apps/management/routes/projects.ts +124 -60
  381. package/src/apps/management/routes/scopes.test.ts +44 -0
  382. package/src/apps/management/routes/scopes.ts +37 -28
  383. package/src/apps/management/routes/usage.test.ts +92 -0
  384. package/src/apps/management/routes/usage.ts +186 -151
  385. package/src/apps/management/routes/verified-token-requests.test.ts +114 -0
  386. package/src/apps/management/routes/verified-token-requests.ts +166 -133
  387. package/src/apps/management/routes/webhooks.test.ts +234 -0
  388. package/src/apps/management/routes/webhooks.ts +191 -78
  389. package/src/apps/mpp/internal/Adapter.ts +13 -1
  390. package/src/db/Db.test.ts +41 -0
  391. package/src/db/Db.ts +75 -1
  392. package/src/db/Schema.ts +33 -5
  393. package/src/db/tables/earnVaults.test.ts +22 -0
  394. package/src/db/tables/earnVaults.ts +11 -1
  395. package/src/db/tables/fundingCatalog.test.ts +16 -2
  396. package/src/db/tables/fundingCatalog.ts +9 -3
  397. package/src/db/tables/webhookDeliveries.ts +13 -0
  398. package/src/db/tables/webhookQueueCompletions.ts +55 -0
  399. package/src/db/tables/webhookQueueEvents.ts +95 -61
  400. package/src/db/tables/webhookSubscriptions.ts +45 -6
  401. package/src/handlers/internal/utils.test.ts +53 -0
  402. package/src/handlers/internal/utils.ts +15 -0
  403. package/src/internal/Auth.ts +35 -9
  404. package/src/internal/Cache.ts +14 -7
  405. package/src/internal/EarnVaults.capabilities.test.ts +33 -0
  406. package/src/internal/EarnVaults.test.ts +79 -0
  407. package/src/internal/EarnVaults.ts +277 -0
  408. package/src/internal/Fetch.test.ts +46 -0
  409. package/src/internal/Fetch.ts +56 -0
  410. package/src/internal/Log.test.ts +21 -0
  411. package/src/internal/Log.ts +20 -5
  412. package/src/internal/OpenApi.ts +177 -51
  413. package/src/internal/Response.test.ts +95 -0
  414. package/src/internal/Response.ts +41 -3
  415. package/src/internal/Schema.test.ts +18 -0
  416. package/src/internal/Schema.ts +19 -9
  417. package/src/internal/Store.test.ts +364 -0
  418. package/src/internal/Store.ts +153 -27
  419. package/src/internal/Tidx.test.ts +21 -1
  420. package/src/internal/Tidx.ts +23 -6
  421. package/src/internal/Timeout.test.ts +35 -0
  422. package/src/internal/Timeout.ts +73 -0
  423. package/src/internal/Timing.ts +16 -0
  424. package/src/internal/WebhookDestination.ts +3 -0
  425. package/src/internal/Webhooks.test.ts +122 -8
  426. package/src/internal/Webhooks.ts +59 -29
  427. package/src/internal/funding/Action.test.ts +41 -1
  428. package/src/internal/funding/Action.ts +69 -41
  429. package/src/internal/funding/Catalog.test.ts +34 -0
  430. package/src/internal/funding/Catalog.ts +28 -11
  431. package/src/internal/funding/Deposit.ts +71 -64
  432. package/src/internal/funding/DepositAddress.ts +50 -43
  433. package/src/internal/funding/Provider.test.ts +73 -0
  434. package/src/internal/funding/Provider.ts +246 -170
  435. package/src/internal/funding/Transfer.ts +133 -110
  436. package/src/internal/funding/providers/index.test.ts +22 -0
  437. package/src/internal/funding/providers/relay.test.ts +2 -2
  438. package/src/internal/funding/providers/stargate.test.ts +163 -0
  439. package/src/internal/funding/providers/stargate.ts +409 -0
  440. package/src/internal/index.test.ts +1 -0
  441. package/src/internal/index.ts +1 -0
  442. package/src/providers/index.test.ts +1 -0
  443. package/src/providers/index.ts +9 -0
@@ -12,82 +12,86 @@ import * as Billing from '../Billing.js'
12
12
  import * as OpenApi from '../../../internal/OpenApi.js'
13
13
  import * as Response from '../../../internal/Response.js'
14
14
  import * as Schema from '../../../internal/Schema.js'
15
+ import * as Store from '../../../internal/Store.js'
15
16
  import * as Scope from '../../../Scope.js'
16
17
  import * as ManagementError from '../Error.js'
17
18
 
18
19
  /** Zod schemas owned by the API-keys resource. */
19
20
  export namespace schema {
20
21
  /** One API key: metadata only — the token appears once, at mint. */
21
- export const Key = Schema.describe(
22
- z.object({
23
- allowedIps: ApiKey.schema.AllowedIps.check(
24
- z.describe(
25
- 'Client IP addresses and CIDR ranges allowed to use this key. An empty list means unrestricted.',
26
- ),
27
- z.meta({ examples: [['203.0.113.0/24', '2001:db8::1']] }),
28
- ),
29
- createdAt: z
30
- .string()
31
- .check(
32
- z.describe('When the key was minted (ISO 8601).'),
33
- z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
34
- ),
35
- createdBy: z
36
- .optional(z.string())
37
- .check(
38
- z.describe('Identity that minted the key (`usr_…`, or `super_admin`).'),
39
- z.meta({ examples: ['usr_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
40
- ),
41
- environment: z
42
- .enum(['production', 'sandbox'])
43
- .check(z.describe('Key environment.'), z.meta({ examples: ['sandbox'] })),
44
- expiresAt: z
45
- .optional(z.string())
46
- .check(
47
- z.describe('When the key expires (ISO 8601). Absent for a non-expiring key.'),
48
- z.meta({ examples: ['2027-01-01T00:00:00.000Z'] }),
49
- ),
50
- id: z
51
- .string()
52
- .check(
53
- z.describe('Opaque key id (`key_…`).'),
54
- z.meta({ examples: ['key_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
55
- ),
56
- lastUsedAt: z
57
- .optional(z.string())
58
- .check(
59
- z.describe('When the key last authenticated a request (ISO 8601).'),
60
- z.meta({ examples: ['2026-07-21T12:34:56.000Z'] }),
61
- ),
62
- name: z
63
- .optional(z.string())
64
- .check(z.describe('Human-readable key name.'), z.meta({ examples: ['CI'] })),
65
- orgId: z
66
- .string()
67
- .check(
68
- z.describe('Owning organization id (`org_…`).'),
69
- z.meta({ examples: ['org_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
70
- ),
71
- projectId: z.optional(z.string()).check(
72
- z.describe('Attributed project id (`prj_…`).'), // prettier-ignore
73
- z.meta({ examples: ['prj_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
74
- ),
75
- scopes: z
76
- .array(z.string().check(z.minLength(1)))
77
- .check(
22
+ export const Key = OpenApi.component(
23
+ Schema.describe(
24
+ z.object({
25
+ allowedIps: ApiKey.schema.AllowedIps.check(
78
26
  z.describe(
79
- "Granted scopes. '*' and non-self-serve scopes appear only on keys minted by the super admin.",
27
+ 'Client IP addresses and CIDR ranges allowed to use this key. An empty list means unrestricted.',
80
28
  ),
81
- z.meta({ examples: [['data:read']] }),
29
+ z.meta({ examples: [['203.0.113.0/24', '2001:db8::1']] }),
82
30
  ),
83
- tokenLast4: z
84
- .string()
85
- .check(
86
- z.describe('Last 4 characters of the plaintext token.'),
87
- z.meta({ examples: ['a1b2'] }),
31
+ createdAt: z.iso
32
+ .datetime()
33
+ .check(
34
+ z.describe('When the key was minted (ISO 8601).'),
35
+ z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
36
+ ),
37
+ createdBy: z
38
+ .optional(z.string())
39
+ .check(
40
+ z.describe('Identity that minted the key (`usr_…`, or `super_admin`).'),
41
+ z.meta({ examples: ['usr_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
42
+ ),
43
+ environment: z
44
+ .enum(['production', 'sandbox'])
45
+ .check(z.describe('Key environment.'), z.meta({ examples: ['sandbox'] })),
46
+ expiresAt: z
47
+ .optional(z.iso.datetime())
48
+ .check(
49
+ z.describe('When the key expires (ISO 8601). Absent for a non-expiring key.'),
50
+ z.meta({ examples: ['2027-01-01T00:00:00.000Z'] }),
51
+ ),
52
+ id: z
53
+ .string()
54
+ .check(
55
+ z.describe('Opaque key id (`key_…`).'),
56
+ z.meta({ examples: ['key_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
57
+ ),
58
+ lastUsedAt: z
59
+ .optional(z.iso.datetime())
60
+ .check(
61
+ z.describe('When the key last authenticated a request (ISO 8601).'),
62
+ z.meta({ examples: ['2026-07-21T12:34:56.000Z'] }),
63
+ ),
64
+ name: z
65
+ .optional(z.string())
66
+ .check(z.describe('Human-readable key name.'), z.meta({ examples: ['CI'] })),
67
+ orgId: z
68
+ .string()
69
+ .check(
70
+ z.describe('Owning organization id (`org_…`).'),
71
+ z.meta({ examples: ['org_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
72
+ ),
73
+ projectId: z.optional(z.string()).check(
74
+ z.describe('Attributed project id (`prj_…`).'), // prettier-ignore
75
+ z.meta({ examples: ['prj_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
88
76
  ),
89
- }),
90
- 'An API key: metadata only — the token appears once, at mint.',
77
+ scopes: z
78
+ .array(z.string().check(z.minLength(1)))
79
+ .check(
80
+ z.describe(
81
+ "Granted scopes. '*' and non-self-serve scopes appear only on keys minted by the super admin.",
82
+ ),
83
+ z.meta({ examples: [['data:read']] }),
84
+ ),
85
+ tokenLast4: z
86
+ .string()
87
+ .check(
88
+ z.describe('Last 4 characters of the plaintext token.'),
89
+ z.meta({ examples: ['a1b2'] }),
90
+ ),
91
+ }),
92
+ 'An API key: metadata only — the token appears once, at mint.',
93
+ ),
94
+ 'ApiKey',
91
95
  )
92
96
 
93
97
  /** Path parameters addressing a project's key collection. */
@@ -144,53 +148,88 @@ export namespace schema {
144
148
  })
145
149
  .check(z.describe('Path parameters for one API key.'))
146
150
 
147
- /** Request body minting a key. The wildcard scope is not issuable here. */
148
- export const KeyBody = z
151
+ /** Path parameters addressing one organization-level API key. */
152
+ export const OrgKeyParams = z
149
153
  .object({
150
- allowedIps: z
151
- .optional(ApiKey.schema.AllowedIps)
154
+ keyId: z
155
+ .string()
152
156
  .check(
153
- z.describe(
154
- 'Client IP addresses and CIDR ranges allowed to use the key. Omit or use an empty list for unrestricted access.',
155
- ),
156
- z.meta({ examples: [['203.0.113.0/24']] }),
157
+ z.describe('The key id (`key_…`).'),
158
+ z.meta({ examples: ['key_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
159
+ ),
160
+ orgId: z
161
+ .string()
162
+ .check(
163
+ z.describe('The organization id (`org_…`).'),
164
+ z.meta({ examples: ['org_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
157
165
  ),
158
- environment: z
159
- ._default(z.enum(['production', 'sandbox']), 'production')
160
- .check(z.describe('Key environment.'), z.meta({ examples: ['sandbox'] })),
161
- name: z
162
- .optional(z.string().check(z.minLength(1), z.maxLength(100)))
163
- .check(z.describe('Human-readable key name.'), z.meta({ examples: ['CI'] })),
164
- scopes: z
165
- ._default(
166
- z.array(
167
- z.string().check(
168
- z.minLength(1),
169
- z.refine((scope) => scope !== Scope.wildcard),
166
+ })
167
+ .check(z.describe('Path parameters for one organization-level API key.'))
168
+
169
+ /** Request body minting a key. The wildcard scope is not issuable here. */
170
+ export const CreateApiKeyRequest = OpenApi.component(
171
+ z
172
+ .object({
173
+ allowedIps: z
174
+ .optional(ApiKey.schema.AllowedIps)
175
+ .check(
176
+ z.describe(
177
+ 'Client IP addresses and CIDR ranges allowed to use the key. Omit or use an empty list for unrestricted access.',
170
178
  ),
179
+ z.meta({ examples: [['203.0.113.0/24']] }),
171
180
  ),
172
- [],
173
- )
174
- .check(z.describe('Scopes to grant.'), z.meta({ examples: [['data:read']] })),
175
- })
176
- .check(z.describe('Fields for minting an API key.'))
181
+ environment: z
182
+ ._default(z.enum(['production', 'sandbox']), 'production')
183
+ .check(z.describe('Key environment.'), z.meta({ examples: ['sandbox'] })),
184
+ name: z
185
+ .optional(z.string().check(z.minLength(1), z.maxLength(100)))
186
+ .check(z.describe('Human-readable key name.'), z.meta({ examples: ['CI'] })),
187
+ scopes: z
188
+ ._default(
189
+ z.array(
190
+ z.string().check(
191
+ z.minLength(1),
192
+ z.refine((scope) => scope !== Scope.wildcard),
193
+ ),
194
+ ),
195
+ [],
196
+ )
197
+ .check(z.describe('Scopes to grant.'), z.meta({ examples: [['data:read']] })),
198
+ })
199
+ .check(z.describe('Fields for minting an API key.')),
200
+ 'CreateApiKeyRequest',
201
+ )
177
202
 
178
203
  /** Schemas for the createApiKey operation. */
179
204
  export namespace createApiKey {
180
205
  /** The minted key plus its one-time token. */
181
- export const Response = Schema.describe(
182
- z.extend(Key, {
183
- token: z
184
- .string()
185
- .check(
186
- z.describe('The plaintext token — shown once, unrecoverable afterward.'),
187
- z.meta({ examples: ['tempo_sandbox:sk:…'] }),
188
- ),
189
- }),
190
- 'The minted key, including its one-time token.',
206
+ export const Response = OpenApi.component(
207
+ Schema.describe(
208
+ z.extend(Key, {
209
+ token: z
210
+ .string()
211
+ .check(
212
+ z.describe('The plaintext token — shown once, unrecoverable afterward.'),
213
+ z.meta({ examples: ['tempo_sandbox:sk:…'] }),
214
+ ),
215
+ }),
216
+ 'The minted key, including its one-time token.',
217
+ ),
218
+ 'CreateApiKeyResponse',
191
219
  )
192
220
  }
193
221
 
222
+ /** Non-paginated list of API key metadata. */
223
+ export const ApiKeyList = OpenApi.component(
224
+ Schema.describe(
225
+ z.object({
226
+ data: z.array(Key).check(z.describe('The API keys, newest first.')),
227
+ }),
228
+ 'A non-paginated list of API key metadata.',
229
+ ),
230
+ 'ApiKeyList',
231
+ )
232
+
194
233
  /** Schemas for the listApiKeys operation. */
195
234
  export namespace listApiKeys {
196
235
  /** Query parameters filtering a project's keys. */
@@ -199,12 +238,7 @@ export namespace schema {
199
238
  .check(z.describe("Query parameters for a project's API keys."))
200
239
 
201
240
  /** Non-paginated list of a project's keys. */
202
- export const Response = Schema.describe(
203
- z.object({
204
- data: z.array(Key).check(z.describe("The project's keys, newest first.")),
205
- }),
206
- "A non-paginated list of a project's API keys (metadata only).",
207
- )
241
+ export const Response = ApiKeyList
208
242
  }
209
243
 
210
244
  /** Schemas for the listOrgApiKeys operation. */
@@ -215,44 +249,62 @@ export namespace schema {
215
249
  .check(z.describe("Query parameters for an organization's API keys."))
216
250
 
217
251
  /** Non-paginated list of every key in the organization. */
218
- export const Response = Schema.describe(
219
- z.object({
220
- data: z
221
- .array(Key)
222
- .check(z.describe("The organization's keys across all projects, newest first.")),
223
- }),
224
- "A non-paginated list of an organization's API keys (metadata only).",
225
- )
252
+ export const Response = ApiKeyList
226
253
  }
227
254
 
228
255
  /** Schemas for the revokeApiKey operation. */
229
256
  export namespace revokeApiKey {
230
257
  /** Confirmation that the key was revoked. */
231
- export const Response = z
232
- .object({
233
- id: z
234
- .string()
235
- .check(
236
- z.describe('ID of the key that was revoked.'),
237
- z.meta({ examples: ['key_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
238
- ),
239
- })
240
- .check(z.describe('Confirmation that the key was revoked.'))
258
+ export const Response = OpenApi.component(
259
+ z
260
+ .object({
261
+ id: z
262
+ .string()
263
+ .check(
264
+ z.describe('ID of the key that was revoked.'),
265
+ z.meta({ examples: ['key_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
266
+ ),
267
+ })
268
+ .check(z.describe('Confirmation that the key was revoked.')),
269
+ 'RevokeApiKeyResponse',
270
+ )
271
+ }
272
+
273
+ /** Schemas for the rotateApiKey operation. */
274
+ export namespace rotateApiKey {
275
+ /** The replacement key plus its one-time token. */
276
+ export const Response = OpenApi.component(
277
+ Schema.describe(
278
+ z.extend(Key, {
279
+ token: z
280
+ .string()
281
+ .check(
282
+ z.describe('The plaintext token — shown once, unrecoverable afterward.'),
283
+ z.meta({ examples: ['tempo_sandbox:sk:…'] }),
284
+ ),
285
+ }),
286
+ 'The replacement key, including its one-time token.',
287
+ ),
288
+ 'RotateApiKeyResponse',
289
+ )
241
290
  }
242
291
 
243
292
  /** Schemas for the updateApiKey operation. */
244
293
  export namespace updateApiKey {
245
294
  /** Request body replacing or clearing a key's IP allowlist. */
246
- export const Body = z
247
- .object({
248
- allowedIps: ApiKey.schema.AllowedIps.check(
249
- z.describe(
250
- 'Replacement client IP/CIDR allowlist. Use an empty list for unrestricted access.',
295
+ export const Body = OpenApi.component(
296
+ z
297
+ .object({
298
+ allowedIps: ApiKey.schema.AllowedIps.check(
299
+ z.describe(
300
+ 'Replacement client IP/CIDR allowlist. Use an empty list for unrestricted access.',
301
+ ),
302
+ z.meta({ examples: [['203.0.113.0/24']] }),
251
303
  ),
252
- z.meta({ examples: [['203.0.113.0/24']] }),
253
- ),
254
- })
255
- .check(z.describe("Fields for updating an API key's network access."))
304
+ })
305
+ .check(z.describe("Fields for updating an API key's network access.")),
306
+ 'UpdateApiKeyRequest',
307
+ )
256
308
  }
257
309
  }
258
310
 
@@ -271,7 +323,7 @@ export function apiKeys(options: apiKeys.Options = {}) {
271
323
  code: 'param_invalid',
272
324
  message: 'Check the path parameters and try again.',
273
325
  }),
274
- OpenApi.validate('json', schema.KeyBody, {
326
+ OpenApi.validate('json', schema.CreateApiKeyRequest, {
275
327
  code: 'body_invalid',
276
328
  message: 'Check the request body and try again.',
277
329
  }),
@@ -281,11 +333,18 @@ export function apiKeys(options: apiKeys.Options = {}) {
281
333
  operationId: 'createApiKey',
282
334
  responses: OpenApi.responses({
283
335
  errors: {
336
+ 400: {
337
+ codes: ['body_invalid', 'param_invalid'],
338
+ description: 'Malformed API key, invalid path, or invalid body.',
339
+ },
284
340
  403: {
285
341
  codes: ['scope_not_issuable'],
286
342
  description: 'The requested scopes are not issuable.',
287
343
  },
288
- 404: 'No accessible project was found for this id.',
344
+ 404: {
345
+ codes: ['api_keys_not_enabled', 'organization_not_found', 'project_not_found'],
346
+ description: 'No accessible project or API key surface was found.',
347
+ },
289
348
  },
290
349
  success: {
291
350
  description: 'The minted key, including its one-time token.',
@@ -298,6 +357,7 @@ export function apiKeys(options: apiKeys.Options = {}) {
298
357
  async (c) => {
299
358
  if (Auth.narrowAccess) return Auth.superAdminAccessError(c)
300
359
  if (Auth.narrowScope) return Auth.ensureProjectError(c)
360
+ if (Auth.narrowOrgRole) return Auth.ensureOrgRoleError(c)
301
361
  if (OpenApi.narrowValidation)
302
362
  return OpenApi.validationError(c, {
303
363
  code: 'param_invalid',
@@ -379,8 +439,14 @@ export function apiKeys(options: apiKeys.Options = {}) {
379
439
  operationId: 'listApiKeys',
380
440
  responses: OpenApi.responses({
381
441
  errors: {
382
- 400: { codes: ['query_invalid'], description: 'Invalid query parameters.' },
383
- 404: 'No accessible project was found for this id.',
442
+ 400: {
443
+ codes: ['param_invalid', 'query_invalid'],
444
+ description: 'Malformed API key, invalid path, or invalid query.',
445
+ },
446
+ 404: {
447
+ codes: ['api_keys_not_enabled', 'organization_not_found', 'project_not_found'],
448
+ description: 'No accessible project or API key surface was found.',
449
+ },
384
450
  },
385
451
  success: {
386
452
  description: "The project's keys, newest first (metadata only).",
@@ -441,8 +507,14 @@ export function apiKeys(options: apiKeys.Options = {}) {
441
507
  operationId: 'listOrgApiKeys',
442
508
  responses: OpenApi.responses({
443
509
  errors: {
444
- 400: { codes: ['query_invalid'], description: 'Invalid query parameters.' },
445
- 404: 'No accessible organization was found for this id.',
510
+ 400: {
511
+ codes: ['param_invalid', 'query_invalid'],
512
+ description: 'Malformed API key, invalid path, or invalid query.',
513
+ },
514
+ 404: {
515
+ codes: ['api_keys_not_enabled', 'organization_not_found'],
516
+ description: 'No accessible organization or API key surface was found.',
517
+ },
446
518
  },
447
519
  success: {
448
520
  description: "The organization's keys across all projects, newest first (metadata only).", // prettier-ignore
@@ -484,6 +556,124 @@ export function apiKeys(options: apiKeys.Options = {}) {
484
556
  }
485
557
  },
486
558
  )
559
+ .post(
560
+ '/v1/orgs/:orgId{org_[A-Za-z0-9_-]+}/api-keys/:keyId{key_[A-Za-z0-9_-]+}/rotate',
561
+ Auth.policy({ session: true }),
562
+ Auth.ensureOrg({ role: 'admin' }),
563
+ OpenApi.validate('param', schema.OrgKeyParams, {
564
+ code: 'param_invalid',
565
+ message: 'Check the path parameters and try again.',
566
+ }),
567
+ OpenApi.describeRoute({
568
+ description:
569
+ 'Create a replacement organization-level API key with the same access as an existing key. The existing key remains active until revoked.',
570
+ hide: hidden,
571
+ operationId: 'rotateOrgApiKey',
572
+ responses: OpenApi.responses({
573
+ errors: {
574
+ 400: { codes: ['param_invalid'], description: 'Malformed API key or invalid path.' },
575
+ 403: {
576
+ codes: ['scope_not_issuable'],
577
+ description: 'The source key contains scopes the caller cannot rotate.',
578
+ },
579
+ 404: {
580
+ codes: ['api_key_not_found', 'api_keys_not_enabled', 'organization_not_found'],
581
+ description: 'No accessible API key or API key surface was found.',
582
+ },
583
+ },
584
+ success: {
585
+ description: 'The replacement key, including its one-time token.',
586
+ schema: schema.rotateApiKey.Response,
587
+ },
588
+ }),
589
+ summary: 'Rotate organization API key',
590
+ tags: ['API Keys'],
591
+ }),
592
+ async (c) => {
593
+ if (Auth.narrowAccess) return Auth.superAdminAccessError(c)
594
+ if (Auth.narrowOrgRole) return Auth.ensureOrgRoleError(c)
595
+ if (OpenApi.narrowValidation)
596
+ return OpenApi.validationError(c, {
597
+ code: 'param_invalid',
598
+ message: 'Check the path parameters and try again.',
599
+ })
600
+
601
+ const kv = c.get('kv')
602
+ if (!kv) return notEnabled(c)
603
+ const createdBy = mintedBy(c)
604
+ if (!createdBy) return ManagementError.sessionRequired(c)
605
+ const { keyId } = c.req.valid('param')
606
+ try {
607
+ const source = await ApiKeys.get(kv.store, keyId, {
608
+ scopeCatalog: c.get('scopeCatalog'),
609
+ })
610
+ if (!source || source.orgId !== Auth.org(c).id || source.projectId !== undefined)
611
+ return keyNotFound(c)
612
+ if (!canRotate(c, source.scopes))
613
+ return Response.error(c, {
614
+ code: 'scope_not_issuable',
615
+ message: 'The source key contains scopes the caller cannot rotate.',
616
+ status: 403,
617
+ })
618
+ return rotate(c, kv.store, source, createdBy)
619
+ } catch (cause) {
620
+ return Response.upstream(c, cause)
621
+ }
622
+ },
623
+ )
624
+ .delete(
625
+ '/v1/orgs/:orgId{org_[A-Za-z0-9_-]+}/api-keys/:keyId{key_[A-Za-z0-9_-]+}',
626
+ Auth.policy({ apiKey: { scopes: ['management:write'] }, session: true }),
627
+ Auth.ensureOrg({ role: 'admin' }),
628
+ OpenApi.validate('param', schema.OrgKeyParams, {
629
+ code: 'param_invalid',
630
+ message: 'Check the path parameters and try again.',
631
+ }),
632
+ OpenApi.describeRoute({
633
+ description:
634
+ 'Revoke an organization-level API key. Requests presenting its token stop resolving.',
635
+ hide: hidden,
636
+ operationId: 'revokeOrgApiKey',
637
+ responses: OpenApi.responses({
638
+ errors: {
639
+ 400: { codes: ['param_invalid'], description: 'Malformed API key or invalid path.' },
640
+ 404: {
641
+ codes: ['api_key_not_found', 'api_keys_not_enabled', 'organization_not_found'],
642
+ description: 'No accessible API key or API key surface was found.',
643
+ },
644
+ },
645
+ success: {
646
+ description: 'Confirmation that the key was revoked.',
647
+ schema: schema.revokeApiKey.Response,
648
+ },
649
+ }),
650
+ summary: 'Revoke organization API key',
651
+ tags: ['API Keys'],
652
+ }),
653
+ async (c) => {
654
+ if (Auth.narrowAccess) return Auth.accessError(c)
655
+ if (Auth.narrowOrgRole) return Auth.ensureOrgRoleError(c)
656
+ if (OpenApi.narrowValidation)
657
+ return OpenApi.validationError(c, {
658
+ code: 'param_invalid',
659
+ message: 'Check the path parameters and try again.',
660
+ })
661
+
662
+ const kv = c.get('kv')
663
+ if (!kv) return notEnabled(c)
664
+ const { keyId } = c.req.valid('param')
665
+ try {
666
+ const record = await ApiKeys.get(kv.store, keyId, {
667
+ scopeCatalog: c.get('scopeCatalog'),
668
+ })
669
+ if (!record || record.orgId !== Auth.org(c).id || record.projectId !== undefined)
670
+ return keyNotFound(c)
671
+ return revoke(c, kv.store, keyId)
672
+ } catch (cause) {
673
+ return Response.upstream(c, cause)
674
+ }
675
+ },
676
+ )
487
677
  .patch(
488
678
  '/v1/orgs/:orgId{org_[A-Za-z0-9_-]+}/projects/:projectId{prj_[A-Za-z0-9_-]+}/api-keys/:keyId{key_[A-Za-z0-9_-]+}',
489
679
  Auth.policy({ apiKey: { scopes: ['management:write'] }, session: true }),
@@ -504,7 +694,19 @@ export function apiKeys(options: apiKeys.Options = {}) {
504
694
  operationId: 'updateApiKey',
505
695
  responses: OpenApi.responses({
506
696
  errors: {
507
- 404: 'No accessible API key was found for this id.',
697
+ 400: {
698
+ codes: ['body_invalid', 'param_invalid'],
699
+ description: 'Malformed API key, invalid path, or invalid body.',
700
+ },
701
+ 404: {
702
+ codes: [
703
+ 'api_key_not_found',
704
+ 'api_keys_not_enabled',
705
+ 'organization_not_found',
706
+ 'project_not_found',
707
+ ],
708
+ description: 'No accessible API key or API key surface was found.',
709
+ },
508
710
  },
509
711
  success: {
510
712
  description: 'The updated API key metadata.',
@@ -517,6 +719,7 @@ export function apiKeys(options: apiKeys.Options = {}) {
517
719
  async (c) => {
518
720
  if (Auth.narrowAccess) return Auth.accessError(c)
519
721
  if (Auth.narrowScope) return Auth.ensureProjectError(c)
722
+ if (Auth.narrowOrgRole) return Auth.ensureOrgRoleError(c)
520
723
  if (OpenApi.narrowValidation)
521
724
  return OpenApi.validationError(c, {
522
725
  code: 'param_invalid',
@@ -547,6 +750,78 @@ export function apiKeys(options: apiKeys.Options = {}) {
547
750
  }
548
751
  },
549
752
  )
753
+ .post(
754
+ '/v1/orgs/:orgId{org_[A-Za-z0-9_-]+}/projects/:projectId{prj_[A-Za-z0-9_-]+}/api-keys/:keyId{key_[A-Za-z0-9_-]+}/rotate',
755
+ Auth.policy({ session: true }),
756
+ Auth.ensureOrg({ role: 'admin' }),
757
+ Auth.ensureProject(),
758
+ OpenApi.validate('param', schema.KeyParams, {
759
+ code: 'param_invalid',
760
+ message: 'Check the path parameters and try again.',
761
+ }),
762
+ OpenApi.describeRoute({
763
+ description:
764
+ 'Create a replacement API key with the same access as an existing key. The existing key remains active until revoked.',
765
+ hide: hidden,
766
+ operationId: 'rotateApiKey',
767
+ responses: OpenApi.responses({
768
+ errors: {
769
+ 400: { codes: ['param_invalid'], description: 'Malformed API key or invalid path.' },
770
+ 403: {
771
+ codes: ['scope_not_issuable'],
772
+ description: 'The source key contains scopes the caller cannot rotate.',
773
+ },
774
+ 404: {
775
+ codes: [
776
+ 'api_key_not_found',
777
+ 'api_keys_not_enabled',
778
+ 'organization_not_found',
779
+ 'project_not_found',
780
+ ],
781
+ description: 'No accessible API key or API key surface was found.',
782
+ },
783
+ },
784
+ success: {
785
+ description: 'The replacement key, including its one-time token.',
786
+ schema: schema.rotateApiKey.Response,
787
+ },
788
+ }),
789
+ summary: 'Rotate API key',
790
+ tags: ['API Keys'],
791
+ }),
792
+ async (c) => {
793
+ if (Auth.narrowAccess) return Auth.superAdminAccessError(c)
794
+ if (Auth.narrowScope) return Auth.ensureProjectError(c)
795
+ if (Auth.narrowOrgRole) return Auth.ensureOrgRoleError(c)
796
+ if (OpenApi.narrowValidation)
797
+ return OpenApi.validationError(c, {
798
+ code: 'param_invalid',
799
+ message: 'Check the path parameters and try again.',
800
+ })
801
+
802
+ const kv = c.get('kv')
803
+ if (!kv) return notEnabled(c)
804
+ const createdBy = mintedBy(c)
805
+ if (!createdBy) return ManagementError.sessionRequired(c)
806
+ const { keyId } = c.req.valid('param')
807
+ try {
808
+ const source = await ApiKeys.get(kv.store, keyId, {
809
+ scopeCatalog: c.get('scopeCatalog'),
810
+ })
811
+ if (!source || source.orgId !== Auth.org(c).id || source.projectId !== Auth.project(c).id)
812
+ return keyNotFound(c)
813
+ if (!canRotate(c, source.scopes))
814
+ return Response.error(c, {
815
+ code: 'scope_not_issuable',
816
+ message: 'The source key contains scopes the caller cannot rotate.',
817
+ status: 403,
818
+ })
819
+ return rotate(c, kv.store, source, createdBy)
820
+ } catch (cause) {
821
+ return Response.upstream(c, cause)
822
+ }
823
+ },
824
+ )
550
825
  .delete(
551
826
  '/v1/orgs/:orgId{org_[A-Za-z0-9_-]+}/projects/:projectId{prj_[A-Za-z0-9_-]+}/api-keys/:keyId{key_[A-Za-z0-9_-]+}',
552
827
  Auth.policy({ apiKey: { scopes: ['management:write'] }, session: true }),
@@ -561,7 +836,18 @@ export function apiKeys(options: apiKeys.Options = {}) {
561
836
  hide: hidden,
562
837
  operationId: 'revokeApiKey',
563
838
  responses: OpenApi.responses({
564
- errors: { 404: 'No accessible API key was found for this id.' },
839
+ errors: {
840
+ 400: { codes: ['param_invalid'], description: 'Malformed API key or invalid path.' },
841
+ 404: {
842
+ codes: [
843
+ 'api_key_not_found',
844
+ 'api_keys_not_enabled',
845
+ 'organization_not_found',
846
+ 'project_not_found',
847
+ ],
848
+ description: 'No accessible API key or API key surface was found.',
849
+ },
850
+ },
565
851
  success: {
566
852
  description: 'Confirmation that the key was revoked.',
567
853
  schema: schema.revokeApiKey.Response,
@@ -573,6 +859,7 @@ export function apiKeys(options: apiKeys.Options = {}) {
573
859
  async (c) => {
574
860
  if (Auth.narrowAccess) return Auth.accessError(c)
575
861
  if (Auth.narrowScope) return Auth.ensureProjectError(c)
862
+ if (Auth.narrowOrgRole) return Auth.ensureOrgRoleError(c)
576
863
  if (OpenApi.narrowValidation)
577
864
  return OpenApi.validationError(c, {
578
865
  code: 'param_invalid',
@@ -590,9 +877,7 @@ export function apiKeys(options: apiKeys.Options = {}) {
590
877
  })
591
878
  if (!record || record.orgId !== Auth.org(c).id || record.projectId !== Auth.project(c).id)
592
879
  return keyNotFound(c)
593
- const revoked = await ApiKeys.revoke(kv.store, keyId)
594
- if (!revoked) return keyNotFound(c)
595
- return c.json(Response.validated(schema.revokeApiKey.Response, { id: keyId }), 200)
880
+ return revoke(c, kv.store, keyId)
596
881
  } catch (cause) {
597
882
  return Response.upstream(c, cause)
598
883
  }
@@ -663,6 +948,57 @@ function canIssue(c: Context<App.Environment>, scopes: readonly Scope.Id[]) {
663
948
  return false
664
949
  }
665
950
 
951
+ /** Checks caller-specific restrictions that still apply when copying existing grants. */
952
+ function canRotate(c: Context<App.Environment>, scopes: readonly Scope.Id[]) {
953
+ const principal = Auth.getPrincipal(c)
954
+ if (principal?.type === 'super_admin') return true
955
+ if (principal?.type !== 'session') return false
956
+ return (
957
+ (!scopes.includes('management:write') && !scopes.includes(Scope.wildcard)) ||
958
+ Auth.membership(c)?.role === 'owner'
959
+ )
960
+ }
961
+
962
+ /** Mints a replacement that preserves the source key's access and attribution. */
963
+ async function rotate(
964
+ c: Context<App.Environment>,
965
+ store: Store.State,
966
+ source: ApiKeys.Record,
967
+ createdBy: string,
968
+ ) {
969
+ const billingActive =
970
+ source.environment === 'sandbox'
971
+ ? await Billing.active(Db.get(c.get('db')), source.orgId, 'sandbox')
972
+ : undefined
973
+ const { record, token } = await ApiKeys.mint(
974
+ store,
975
+ {
976
+ allowedIps: source.allowedIps,
977
+ createdBy,
978
+ environment: source.environment,
979
+ orgId: source.orgId,
980
+ ...(source.projectId === undefined ? {} : { projectId: source.projectId }),
981
+ scopes: source.scopes,
982
+ ...(billingActive === undefined ? {} : { billingActive }),
983
+ ...(source.expiresAt === undefined ? {} : { expiresAt: source.expiresAt }),
984
+ ...(source.name === undefined ? {} : { name: source.name }),
985
+ ...(source.rateLimits === undefined ? {} : { rateLimits: source.rateLimits }),
986
+ },
987
+ { scopeCatalog: c.get('scopeCatalog') },
988
+ )
989
+ return c.json(
990
+ Response.validated(schema.rotateApiKey.Response, { ...serializeKey(record), token }),
991
+ 200,
992
+ )
993
+ }
994
+
995
+ /** Revokes an API key after its route has verified ownership. */
996
+ async function revoke(c: Context<App.Environment>, store: Store.State, keyId: string) {
997
+ const revoked = await ApiKeys.revoke(store, keyId)
998
+ if (!revoked) return keyNotFound(c)
999
+ return c.json(Response.validated(schema.revokeApiKey.Response, { id: keyId }), 200)
1000
+ }
1001
+
666
1002
  function keyNotFound(c: Context<App.Environment>) {
667
1003
  return Response.error(c, {
668
1004
  code: 'api_key_not_found',