tapimo 0.14.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1160) hide show
  1. package/README.md +7 -4
  2. package/dist/ApiKey.js +1 -1
  3. package/dist/ApiKey.js.map +1 -1
  4. package/dist/ApiKeys.d.ts +95 -14
  5. package/dist/ApiKeys.d.ts.map +1 -1
  6. package/dist/ApiKeys.js +360 -49
  7. package/dist/ApiKeys.js.map +1 -1
  8. package/dist/App.d.ts +12466 -10374
  9. package/dist/App.d.ts.map +1 -1
  10. package/dist/App.js +300 -22
  11. package/dist/App.js.map +1 -1
  12. package/dist/Assets.d.ts.map +1 -1
  13. package/dist/Assets.js +2 -1
  14. package/dist/Assets.js.map +1 -1
  15. package/dist/Handler.d.ts +0 -1
  16. package/dist/Handler.d.ts.map +1 -1
  17. package/dist/Handler.js +0 -1
  18. package/dist/Handler.js.map +1 -1
  19. package/dist/Scope.d.ts +13 -5
  20. package/dist/Scope.d.ts.map +1 -1
  21. package/dist/Scope.js +16 -5
  22. package/dist/Scope.js.map +1 -1
  23. package/dist/Webhooks.js +1 -1
  24. package/dist/Webhooks.js.map +1 -1
  25. package/dist/admin/App.d.ts +3057 -546
  26. package/dist/admin/App.d.ts.map +1 -1
  27. package/dist/admin/App.js +26 -5
  28. package/dist/admin/App.js.map +1 -1
  29. package/dist/admin/apps/api-keys.d.ts +179 -27
  30. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  31. package/dist/admin/apps/api-keys.js +95 -43
  32. package/dist/admin/apps/api-keys.js.map +1 -1
  33. package/dist/admin/apps/earn-vaults.d.ts +1398 -0
  34. package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
  35. package/dist/admin/apps/earn-vaults.js +463 -7
  36. package/dist/admin/apps/earn-vaults.js.map +1 -1
  37. package/dist/admin/apps/organizations.d.ts +267 -15
  38. package/dist/admin/apps/organizations.d.ts.map +1 -1
  39. package/dist/admin/apps/organizations.js +241 -25
  40. package/dist/admin/apps/organizations.js.map +1 -1
  41. package/dist/admin/apps/routes-support.d.ts +95 -0
  42. package/dist/admin/apps/routes-support.d.ts.map +1 -0
  43. package/dist/admin/apps/routes-support.js +151 -0
  44. package/dist/admin/apps/routes-support.js.map +1 -0
  45. package/dist/admin/apps/routes.d.ts +2764 -0
  46. package/dist/admin/apps/routes.d.ts.map +1 -0
  47. package/dist/admin/apps/routes.js +728 -0
  48. package/dist/admin/apps/routes.js.map +1 -0
  49. package/dist/admin/apps/subsidies.d.ts +501 -0
  50. package/dist/admin/apps/subsidies.d.ts.map +1 -0
  51. package/dist/admin/apps/subsidies.js +384 -0
  52. package/dist/admin/apps/subsidies.js.map +1 -0
  53. package/dist/admin/apps/verified-tokens.d.ts +166 -160
  54. package/dist/admin/apps/verified-tokens.d.ts.map +1 -1
  55. package/dist/admin/apps/verified-tokens.js +27 -7
  56. package/dist/admin/apps/verified-tokens.js.map +1 -1
  57. package/dist/admin/ui.generated.d.ts +1 -1
  58. package/dist/admin/ui.generated.d.ts.map +1 -1
  59. package/dist/admin/ui.generated.js +201 -149
  60. package/dist/admin/ui.generated.js.map +1 -1
  61. package/dist/analytics/Analytics.d.ts +5 -2
  62. package/dist/analytics/Analytics.d.ts.map +1 -1
  63. package/dist/analytics/Analytics.js +31 -1
  64. package/dist/analytics/Analytics.js.map +1 -1
  65. package/dist/analytics/tables/requestEvents.d.ts +2 -1
  66. package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
  67. package/dist/analytics/tables/requestEvents.js +10 -1
  68. package/dist/analytics/tables/requestEvents.js.map +1 -1
  69. package/dist/analytics/tables/routesLifecycleIntervals.d.ts +72 -0
  70. package/dist/analytics/tables/routesLifecycleIntervals.d.ts.map +1 -0
  71. package/dist/analytics/tables/routesLifecycleIntervals.js +56 -0
  72. package/dist/analytics/tables/routesLifecycleIntervals.js.map +1 -0
  73. package/dist/apps/Zones.d.ts +21 -12526
  74. package/dist/apps/Zones.d.ts.map +1 -1
  75. package/dist/apps/Zones.js +37 -5
  76. package/dist/apps/Zones.js.map +1 -1
  77. package/dist/apps/data/App.d.ts +3971 -2595
  78. package/dist/apps/data/App.d.ts.map +1 -1
  79. package/dist/apps/data/App.js +76 -21
  80. package/dist/apps/data/App.js.map +1 -1
  81. package/dist/apps/data/routes/activities.d.ts +629 -299
  82. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  83. package/dist/apps/data/routes/activities.js +495 -190
  84. package/dist/apps/data/routes/activities.js.map +1 -1
  85. package/dist/apps/data/routes/addresses.d.ts +72 -0
  86. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  87. package/dist/apps/data/routes/blocks.d.ts +116 -116
  88. package/dist/apps/data/routes/coingecko.d.ts.map +1 -1
  89. package/dist/apps/data/routes/coingecko.js +47 -21
  90. package/dist/apps/data/routes/coingecko.js.map +1 -1
  91. package/dist/apps/data/routes/earn.d.ts +1450 -337
  92. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  93. package/dist/apps/data/routes/earn.js +1226 -144
  94. package/dist/apps/data/routes/earn.js.map +1 -1
  95. package/dist/apps/data/routes/fee-amm.d.ts +113 -108
  96. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  97. package/dist/apps/data/routes/fee-amm.js +41 -21
  98. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  99. package/dist/apps/data/routes/indexer.d.ts +142 -17
  100. package/dist/apps/data/routes/indexer.d.ts.map +1 -1
  101. package/dist/apps/data/routes/indexer.js +83 -27
  102. package/dist/apps/data/routes/indexer.js.map +1 -1
  103. package/dist/apps/data/routes/receipts.d.ts +235 -235
  104. package/dist/apps/data/routes/rpc.d.ts +507 -33
  105. package/dist/apps/data/routes/rpc.d.ts.map +1 -1
  106. package/dist/apps/data/routes/rpc.js +309 -165
  107. package/dist/apps/data/routes/rpc.js.map +1 -1
  108. package/dist/apps/data/routes/tokenlist.d.ts +47 -15
  109. package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
  110. package/dist/apps/data/routes/tokenlist.js +68 -11
  111. package/dist/apps/data/routes/tokenlist.js.map +1 -1
  112. package/dist/apps/data/routes/tokens.d.ts +2 -0
  113. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  114. package/dist/apps/data/routes/tokens.js +26 -14
  115. package/dist/apps/data/routes/tokens.js.map +1 -1
  116. package/dist/apps/data/routes/transfers.d.ts +93 -77
  117. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  118. package/dist/apps/data/routes/transfers.js +9 -7
  119. package/dist/apps/data/routes/transfers.js.map +1 -1
  120. package/dist/apps/data/routes/valuation.d.ts +32 -32
  121. package/dist/apps/data/routes/verified-tokens.d.ts +88 -88
  122. package/dist/apps/data/routes/verified-tokens.d.ts.map +1 -1
  123. package/dist/apps/data/routes/verified-tokens.js +64 -20
  124. package/dist/apps/data/routes/verified-tokens.js.map +1 -1
  125. package/dist/apps/data/routes/webhooks.d.ts +614 -177
  126. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  127. package/dist/apps/data/routes/webhooks.js +308 -205
  128. package/dist/apps/data/routes/webhooks.js.map +1 -1
  129. package/dist/apps/data/routes/zones.d.ts +31 -31
  130. package/dist/apps/data/routes/zones.d.ts.map +1 -1
  131. package/dist/apps/data/routes/zones.js +20 -12
  132. package/dist/apps/data/routes/zones.js.map +1 -1
  133. package/dist/apps/docs/reference.js +2 -2
  134. package/dist/apps/docs/reference.js.map +1 -1
  135. package/dist/apps/index.d.ts +1 -1
  136. package/dist/apps/index.d.ts.map +1 -1
  137. package/dist/apps/index.js +1 -1
  138. package/dist/apps/index.js.map +1 -1
  139. package/dist/apps/management/App.d.ts +3780 -3402
  140. package/dist/apps/management/App.d.ts.map +1 -1
  141. package/dist/apps/management/App.js +5 -14
  142. package/dist/apps/management/App.js.map +1 -1
  143. package/dist/apps/management/Billing.d.ts +48 -7
  144. package/dist/apps/management/Billing.d.ts.map +1 -1
  145. package/dist/apps/management/Billing.js +204 -25
  146. package/dist/apps/management/Billing.js.map +1 -1
  147. package/dist/apps/management/routes/api-keys.d.ts +317 -215
  148. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  149. package/dist/apps/management/routes/api-keys.js +43 -15
  150. package/dist/apps/management/routes/api-keys.js.map +1 -1
  151. package/dist/apps/management/routes/billing.d.ts +290 -4
  152. package/dist/apps/management/routes/billing.d.ts.map +1 -1
  153. package/dist/apps/management/routes/billing.js +274 -49
  154. package/dist/apps/management/routes/billing.js.map +1 -1
  155. package/dist/apps/management/routes/faucet.d.ts +6 -6
  156. package/dist/apps/management/routes/faucet.js +1 -1
  157. package/dist/apps/management/routes/faucet.js.map +1 -1
  158. package/dist/apps/management/routes/invitations.d.ts +213 -138
  159. package/dist/apps/management/routes/invitations.d.ts.map +1 -1
  160. package/dist/apps/management/routes/invitations.js +117 -13
  161. package/dist/apps/management/routes/invitations.js.map +1 -1
  162. package/dist/apps/management/routes/invite-links.d.ts +166 -166
  163. package/dist/apps/management/routes/me.d.ts.map +1 -1
  164. package/dist/apps/management/routes/me.js +6 -2
  165. package/dist/apps/management/routes/me.js.map +1 -1
  166. package/dist/apps/management/routes/members.d.ts +30 -30
  167. package/dist/apps/management/routes/orgs.d.ts +103 -87
  168. package/dist/apps/management/routes/orgs.d.ts.map +1 -1
  169. package/dist/apps/management/routes/orgs.js +52 -12
  170. package/dist/apps/management/routes/orgs.js.map +1 -1
  171. package/dist/apps/management/routes/projects.d.ts +125 -125
  172. package/dist/apps/management/routes/projects.d.ts.map +1 -1
  173. package/dist/apps/management/routes/projects.js +6 -1
  174. package/dist/apps/management/routes/projects.js.map +1 -1
  175. package/dist/apps/management/routes/scopes.d.ts.map +1 -1
  176. package/dist/apps/management/routes/scopes.js +4 -1
  177. package/dist/apps/management/routes/scopes.js.map +1 -1
  178. package/dist/apps/management/routes/usage.d.ts +24 -24
  179. package/dist/apps/management/routes/usage.js +21 -4
  180. package/dist/apps/management/routes/usage.js.map +1 -1
  181. package/dist/apps/management/routes/verified-token-requests.d.ts +95 -95
  182. package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
  183. package/dist/apps/management/routes/verified-token-requests.js +7 -9
  184. package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
  185. package/dist/apps/management/routes/webhooks.d.ts +682 -616
  186. package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
  187. package/dist/apps/management/routes/webhooks.js +58 -12
  188. package/dist/apps/management/routes/webhooks.js.map +1 -1
  189. package/dist/apps/mcp.d.ts +1 -1
  190. package/dist/apps/mcp.d.ts.map +1 -1
  191. package/dist/apps/mcp.js +23 -10
  192. package/dist/apps/mcp.js.map +1 -1
  193. package/dist/apps/mpp/App.d.ts +44 -44
  194. package/dist/apps/mpp/App.d.ts.map +1 -1
  195. package/dist/apps/mpp/App.js +35 -7
  196. package/dist/apps/mpp/App.js.map +1 -1
  197. package/dist/apps/mpp/internal/Adapter.d.ts +2 -0
  198. package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
  199. package/dist/apps/mpp/internal/Adapter.js +30 -1
  200. package/dist/apps/mpp/internal/Adapter.js.map +1 -1
  201. package/dist/apps/mpp/internal/Policy.d.ts +22 -4
  202. package/dist/apps/mpp/internal/Policy.d.ts.map +1 -1
  203. package/dist/apps/mpp/internal/Policy.js +24 -6
  204. package/dist/apps/mpp/internal/Policy.js.map +1 -1
  205. package/dist/apps/mpp/internal/Sponsorship.d.ts +3 -0
  206. package/dist/apps/mpp/internal/Sponsorship.d.ts.map +1 -1
  207. package/dist/apps/mpp/internal/Sponsorship.js +6 -3
  208. package/dist/apps/mpp/internal/Sponsorship.js.map +1 -1
  209. package/dist/apps/relay/App.d.ts +2 -0
  210. package/dist/apps/relay/App.d.ts.map +1 -1
  211. package/dist/apps/relay/App.js +134 -75
  212. package/dist/apps/relay/App.js.map +1 -1
  213. package/dist/apps/relay/Sponsorships.d.ts +5 -3
  214. package/dist/apps/relay/Sponsorships.d.ts.map +1 -1
  215. package/dist/apps/relay/Sponsorships.js +209 -28
  216. package/dist/apps/relay/Sponsorships.js.map +1 -1
  217. package/dist/apps/{funding → routes}/Access.d.ts +4 -4
  218. package/dist/apps/routes/Access.d.ts.map +1 -0
  219. package/dist/apps/{funding → routes}/Access.js +4 -4
  220. package/dist/apps/routes/Access.js.map +1 -0
  221. package/dist/apps/{funding → routes}/App.d.ts +418 -124
  222. package/dist/apps/{funding → routes}/App.d.ts.map +1 -1
  223. package/dist/apps/{funding → routes}/App.js +16 -16
  224. package/dist/apps/routes/App.js.map +1 -0
  225. package/dist/apps/routes/Inventory.d.ts.map +1 -0
  226. package/dist/apps/{funding → routes}/Inventory.js +2 -2
  227. package/dist/apps/routes/Inventory.js.map +1 -0
  228. package/dist/apps/routes/index.d.ts +2 -0
  229. package/dist/apps/routes/index.d.ts.map +1 -0
  230. package/dist/apps/routes/index.js +2 -0
  231. package/dist/apps/routes/index.js.map +1 -0
  232. package/dist/apps/{funding → routes}/routes/chains.d.ts +32 -32
  233. package/dist/apps/routes/routes/chains.d.ts.map +1 -0
  234. package/dist/apps/{funding → routes}/routes/chains.js +25 -25
  235. package/dist/apps/routes/routes/chains.js.map +1 -0
  236. package/dist/apps/{funding → routes}/routes/deposit-addresses.d.ts +107 -43
  237. package/dist/apps/routes/routes/deposit-addresses.d.ts.map +1 -0
  238. package/dist/apps/{funding → routes}/routes/deposit-addresses.js +497 -222
  239. package/dist/apps/routes/routes/deposit-addresses.js.map +1 -0
  240. package/dist/apps/{funding → routes}/routes/providers.d.ts +8 -8
  241. package/dist/apps/routes/routes/providers.d.ts.map +1 -0
  242. package/dist/apps/routes/routes/providers.js +57 -0
  243. package/dist/apps/routes/routes/providers.js.map +1 -0
  244. package/dist/apps/{funding → routes}/routes/quotes.d.ts +106 -103
  245. package/dist/apps/routes/routes/quotes.d.ts.map +1 -0
  246. package/dist/apps/{funding → routes}/routes/quotes.js +55 -38
  247. package/dist/apps/routes/routes/quotes.js.map +1 -0
  248. package/dist/apps/{funding → routes}/routes/transfers.d.ts +733 -428
  249. package/dist/apps/routes/routes/transfers.d.ts.map +1 -0
  250. package/dist/apps/routes/routes/transfers.js +1140 -0
  251. package/dist/apps/routes/routes/transfers.js.map +1 -0
  252. package/dist/cli/Cli.d.ts +30 -0
  253. package/dist/cli/Cli.d.ts.map +1 -1
  254. package/dist/cli/commands/admin.d.ts +36 -0
  255. package/dist/cli/commands/admin.d.ts.map +1 -1
  256. package/dist/cli/commands/admin.js +273 -0
  257. package/dist/cli/commands/admin.js.map +1 -1
  258. package/dist/cloudflare.d.ts +16 -14
  259. package/dist/cloudflare.d.ts.map +1 -1
  260. package/dist/cloudflare.js +26 -21
  261. package/dist/cloudflare.js.map +1 -1
  262. package/dist/db/Db.d.ts +63 -21
  263. package/dist/db/Db.d.ts.map +1 -1
  264. package/dist/db/Db.js +1035 -15
  265. package/dist/db/Db.js.map +1 -1
  266. package/dist/db/Schema.d.ts +780 -133
  267. package/dist/db/Schema.d.ts.map +1 -1
  268. package/dist/db/Schema.js +575 -162
  269. package/dist/db/Schema.js.map +1 -1
  270. package/dist/db/tables/apiKeyAdmissionBootstraps.d.ts +4 -0
  271. package/dist/db/tables/apiKeyAdmissionBootstraps.d.ts.map +1 -0
  272. package/dist/db/tables/apiKeyAdmissionBootstraps.js +2 -0
  273. package/dist/db/tables/apiKeyAdmissionBootstraps.js.map +1 -0
  274. package/dist/db/tables/apiKeyAdmissions.d.ts +73 -0
  275. package/dist/db/tables/apiKeyAdmissions.d.ts.map +1 -0
  276. package/dist/db/tables/apiKeyAdmissions.js +142 -0
  277. package/dist/db/tables/apiKeyAdmissions.js.map +1 -0
  278. package/dist/db/tables/apiKeyOwnerAdmissions.d.ts +4 -0
  279. package/dist/db/tables/apiKeyOwnerAdmissions.d.ts.map +1 -0
  280. package/dist/db/tables/apiKeyOwnerAdmissions.js +2 -0
  281. package/dist/db/tables/apiKeyOwnerAdmissions.js.map +1 -0
  282. package/dist/db/tables/apiKeyOwnerTombstones.d.ts +20 -0
  283. package/dist/db/tables/apiKeyOwnerTombstones.d.ts.map +1 -0
  284. package/dist/db/tables/apiKeyOwnerTombstones.js +57 -0
  285. package/dist/db/tables/apiKeyOwnerTombstones.js.map +1 -0
  286. package/dist/db/tables/apiKeyRevocations.d.ts +21 -0
  287. package/dist/db/tables/apiKeyRevocations.d.ts.map +1 -0
  288. package/dist/db/tables/apiKeyRevocations.js +98 -0
  289. package/dist/db/tables/apiKeyRevocations.js.map +1 -0
  290. package/dist/db/tables/authAccounts.d.ts +47 -0
  291. package/dist/db/tables/authAccounts.d.ts.map +1 -0
  292. package/dist/db/tables/authAccounts.js +72 -0
  293. package/dist/db/tables/authAccounts.js.map +1 -0
  294. package/dist/db/tables/authSessions.d.ts +12 -0
  295. package/dist/db/tables/authSessions.d.ts.map +1 -0
  296. package/dist/db/tables/authSessions.js +2 -0
  297. package/dist/db/tables/authSessions.js.map +1 -0
  298. package/dist/db/tables/authVerifications.d.ts +12 -0
  299. package/dist/db/tables/authVerifications.d.ts.map +1 -0
  300. package/dist/db/tables/authVerifications.js +2 -0
  301. package/dist/db/tables/authVerifications.js.map +1 -0
  302. package/dist/db/tables/invitations.d.ts +17 -1
  303. package/dist/db/tables/invitations.d.ts.map +1 -1
  304. package/dist/db/tables/invitations.js +123 -43
  305. package/dist/db/tables/invitations.js.map +1 -1
  306. package/dist/db/tables/memberships.d.ts +8 -0
  307. package/dist/db/tables/memberships.d.ts.map +1 -1
  308. package/dist/db/tables/memberships.js +51 -2
  309. package/dist/db/tables/memberships.js.map +1 -1
  310. package/dist/db/tables/organizations.d.ts +32 -10
  311. package/dist/db/tables/organizations.d.ts.map +1 -1
  312. package/dist/db/tables/organizations.js +110 -49
  313. package/dist/db/tables/organizations.js.map +1 -1
  314. package/dist/db/tables/projects.d.ts +2 -0
  315. package/dist/db/tables/projects.d.ts.map +1 -1
  316. package/dist/db/tables/projects.js +12 -3
  317. package/dist/db/tables/projects.js.map +1 -1
  318. package/dist/db/tables/requestUsage.d.ts.map +1 -1
  319. package/dist/db/tables/requestUsage.js.map +1 -1
  320. package/dist/db/tables/rewardAccounts.d.ts +86 -0
  321. package/dist/db/tables/rewardAccounts.d.ts.map +1 -0
  322. package/dist/db/tables/rewardAccounts.js +88 -0
  323. package/dist/db/tables/rewardAccounts.js.map +1 -0
  324. package/dist/db/tables/rewardCampaignDistributors.d.ts +36 -0
  325. package/dist/db/tables/rewardCampaignDistributors.d.ts.map +1 -0
  326. package/dist/db/tables/rewardCampaignDistributors.js +30 -0
  327. package/dist/db/tables/rewardCampaignDistributors.js.map +1 -0
  328. package/dist/db/tables/rewardCampaigns.d.ts +171 -0
  329. package/dist/db/tables/rewardCampaigns.d.ts.map +1 -0
  330. package/dist/db/tables/rewardCampaigns.js +392 -0
  331. package/dist/db/tables/rewardCampaigns.js.map +1 -0
  332. package/dist/db/tables/rewardCredits.d.ts +53 -0
  333. package/dist/db/tables/rewardCredits.d.ts.map +1 -0
  334. package/dist/db/tables/rewardCredits.js +63 -0
  335. package/dist/db/tables/rewardCredits.js.map +1 -0
  336. package/dist/db/tables/rewardEligibilityAssociations.d.ts +61 -0
  337. package/dist/db/tables/rewardEligibilityAssociations.d.ts.map +1 -0
  338. package/dist/db/tables/rewardEligibilityAssociations.js +103 -0
  339. package/dist/db/tables/rewardEligibilityAssociations.js.map +1 -0
  340. package/dist/db/tables/rewardRuns.d.ts +188 -0
  341. package/dist/db/tables/rewardRuns.d.ts.map +1 -0
  342. package/dist/db/tables/rewardRuns.js +278 -0
  343. package/dist/db/tables/rewardRuns.js.map +1 -0
  344. package/dist/db/tables/rewardTransactionAttempts.d.ts +100 -0
  345. package/dist/db/tables/rewardTransactionAttempts.d.ts.map +1 -0
  346. package/dist/db/tables/rewardTransactionAttempts.js +163 -0
  347. package/dist/db/tables/rewardTransactionAttempts.js.map +1 -0
  348. package/dist/db/tables/routesCatalog.d.ts +58 -0
  349. package/dist/db/tables/routesCatalog.d.ts.map +1 -0
  350. package/dist/db/tables/{fundingCatalog.js → routesCatalog.js} +19 -19
  351. package/dist/db/tables/routesCatalog.js.map +1 -0
  352. package/dist/db/tables/routesDepositAddresses.d.ts +476 -0
  353. package/dist/db/tables/routesDepositAddresses.d.ts.map +1 -0
  354. package/dist/db/tables/routesDepositAddresses.js +587 -0
  355. package/dist/db/tables/routesDepositAddresses.js.map +1 -0
  356. package/dist/db/tables/{fundingDepositRequestObservations.d.ts → routesDepositRequestObservations.d.ts} +6 -6
  357. package/dist/db/tables/routesDepositRequestObservations.d.ts.map +1 -0
  358. package/dist/db/tables/{fundingDepositRequestObservations.js → routesDepositRequestObservations.js} +6 -6
  359. package/dist/db/tables/routesDepositRequestObservations.js.map +1 -0
  360. package/dist/db/tables/{fundingDeposits.d.ts → routesDeposits.d.ts} +210 -22
  361. package/dist/db/tables/routesDeposits.d.ts.map +1 -0
  362. package/dist/db/tables/routesDeposits.js +576 -0
  363. package/dist/db/tables/routesDeposits.js.map +1 -0
  364. package/dist/db/tables/routesIdempotency.d.ts +166 -0
  365. package/dist/db/tables/routesIdempotency.d.ts.map +1 -0
  366. package/dist/db/tables/routesIdempotency.js +330 -0
  367. package/dist/db/tables/routesIdempotency.js.map +1 -0
  368. package/dist/db/tables/routesSubsidies.d.ts +27 -0
  369. package/dist/db/tables/routesSubsidies.d.ts.map +1 -0
  370. package/dist/db/tables/routesSubsidies.js +45 -0
  371. package/dist/db/tables/routesSubsidies.js.map +1 -0
  372. package/dist/db/tables/{fundingTransferEvents.d.ts → routesTransferEvents.d.ts} +3 -3
  373. package/dist/db/tables/routesTransferEvents.d.ts.map +1 -0
  374. package/dist/db/tables/{fundingTransferEvents.js → routesTransferEvents.js} +3 -3
  375. package/dist/db/tables/routesTransferEvents.js.map +1 -0
  376. package/dist/db/tables/routesTransferSubsidies.d.ts +19 -0
  377. package/dist/db/tables/routesTransferSubsidies.d.ts.map +1 -0
  378. package/dist/db/tables/routesTransferSubsidies.js +17 -0
  379. package/dist/db/tables/routesTransferSubsidies.js.map +1 -0
  380. package/dist/db/tables/routesTransferSubsidyNonces.d.ts +51 -0
  381. package/dist/db/tables/routesTransferSubsidyNonces.d.ts.map +1 -0
  382. package/dist/db/tables/routesTransferSubsidyNonces.js +82 -0
  383. package/dist/db/tables/routesTransferSubsidyNonces.js.map +1 -0
  384. package/dist/db/tables/routesTransferTransactions.d.ts +77 -0
  385. package/dist/db/tables/routesTransferTransactions.d.ts.map +1 -0
  386. package/dist/db/tables/{fundingTransferTransactions.js → routesTransferTransactions.js} +31 -13
  387. package/dist/db/tables/routesTransferTransactions.js.map +1 -0
  388. package/dist/db/tables/routesTransfers.d.ts +319 -0
  389. package/dist/db/tables/routesTransfers.d.ts.map +1 -0
  390. package/dist/db/tables/routesTransfers.js +372 -0
  391. package/dist/db/tables/routesTransfers.js.map +1 -0
  392. package/dist/db/tables/sponsoredTransactions.d.ts +75 -20
  393. package/dist/db/tables/sponsoredTransactions.d.ts.map +1 -1
  394. package/dist/db/tables/sponsoredTransactions.js +124 -54
  395. package/dist/db/tables/sponsoredTransactions.js.map +1 -1
  396. package/dist/db/tables/sponsorshipAttributions.d.ts +69 -0
  397. package/dist/db/tables/sponsorshipAttributions.d.ts.map +1 -0
  398. package/dist/db/tables/sponsorshipAttributions.js +77 -0
  399. package/dist/db/tables/sponsorshipAttributions.js.map +1 -0
  400. package/dist/db/tables/sponsorshipReconciliationCursors.d.ts +22 -0
  401. package/dist/db/tables/sponsorshipReconciliationCursors.d.ts.map +1 -0
  402. package/dist/db/tables/sponsorshipReconciliationCursors.js +45 -0
  403. package/dist/db/tables/sponsorshipReconciliationCursors.js.map +1 -0
  404. package/dist/db/tables/stripeCustomers.d.ts +11 -0
  405. package/dist/db/tables/stripeCustomers.d.ts.map +1 -1
  406. package/dist/db/tables/stripeCustomers.js +13 -0
  407. package/dist/db/tables/stripeCustomers.js.map +1 -1
  408. package/dist/db/tables/users.d.ts +17 -1
  409. package/dist/db/tables/users.d.ts.map +1 -1
  410. package/dist/db/tables/users.js +47 -2
  411. package/dist/db/tables/users.js.map +1 -1
  412. package/dist/db/tables/verifiedTokenRequests.d.ts +21 -4
  413. package/dist/db/tables/verifiedTokenRequests.d.ts.map +1 -1
  414. package/dist/db/tables/verifiedTokenRequests.js +65 -44
  415. package/dist/db/tables/verifiedTokenRequests.js.map +1 -1
  416. package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
  417. package/dist/db/tables/webhookQueueEvents.js +5 -1
  418. package/dist/db/tables/webhookQueueEvents.js.map +1 -1
  419. package/dist/db/tables/webhookSubscriptions.d.ts +19 -11
  420. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  421. package/dist/db/tables/webhookSubscriptions.js +45 -13
  422. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  423. package/dist/handlers/internal/executionError.d.ts +2 -2
  424. package/dist/handlers/internal/executionError.d.ts.map +1 -1
  425. package/dist/handlers/internal/executionError.js +1 -2
  426. package/dist/handlers/internal/executionError.js.map +1 -1
  427. package/dist/handlers/internal/multisig.d.ts +4 -232
  428. package/dist/handlers/internal/multisig.d.ts.map +1 -1
  429. package/dist/handlers/internal/multisig.js +11 -537
  430. package/dist/handlers/internal/multisig.js.map +1 -1
  431. package/dist/handlers/internal/sponsorship.d.ts +19 -8
  432. package/dist/handlers/internal/sponsorship.d.ts.map +1 -1
  433. package/dist/handlers/internal/sponsorship.js +13 -9
  434. package/dist/handlers/internal/sponsorship.js.map +1 -1
  435. package/dist/handlers/relay.d.ts +9 -12
  436. package/dist/handlers/relay.d.ts.map +1 -1
  437. package/dist/handlers/relay.js +81 -85
  438. package/dist/handlers/relay.js.map +1 -1
  439. package/dist/index.d.ts +0 -17
  440. package/dist/index.d.ts.map +1 -1
  441. package/dist/index.js +0 -17
  442. package/dist/index.js.map +1 -1
  443. package/dist/internal/AssetResponse.d.ts +12 -0
  444. package/dist/internal/AssetResponse.d.ts.map +1 -0
  445. package/dist/internal/AssetResponse.js +21 -0
  446. package/dist/internal/AssetResponse.js.map +1 -0
  447. package/dist/internal/Auth.d.ts +64 -12
  448. package/dist/internal/Auth.d.ts.map +1 -1
  449. package/dist/internal/Auth.js +631 -180
  450. package/dist/internal/Auth.js.map +1 -1
  451. package/dist/internal/BetterAuth.d.ts +1488 -0
  452. package/dist/internal/BetterAuth.d.ts.map +1 -0
  453. package/dist/internal/BetterAuth.js +253 -0
  454. package/dist/internal/BetterAuth.js.map +1 -0
  455. package/dist/internal/Cache.d.ts +2 -0
  456. package/dist/internal/Cache.d.ts.map +1 -1
  457. package/dist/internal/Cache.js +2 -0
  458. package/dist/internal/Cache.js.map +1 -1
  459. package/dist/internal/EarnRates.d.ts +26 -3
  460. package/dist/internal/EarnRates.d.ts.map +1 -1
  461. package/dist/internal/EarnRates.js +84 -19
  462. package/dist/internal/EarnRates.js.map +1 -1
  463. package/dist/internal/EarnSharePrices.d.ts +120 -0
  464. package/dist/internal/EarnSharePrices.d.ts.map +1 -0
  465. package/dist/internal/EarnSharePrices.js +179 -0
  466. package/dist/internal/EarnSharePrices.js.map +1 -0
  467. package/dist/internal/EarnVaults.d.ts +4 -0
  468. package/dist/internal/EarnVaults.d.ts.map +1 -1
  469. package/dist/internal/EarnVaults.js +27 -10
  470. package/dist/internal/EarnVaults.js.map +1 -1
  471. package/dist/internal/Email.d.ts +37 -0
  472. package/dist/internal/Email.d.ts.map +1 -0
  473. package/dist/internal/Email.js +16 -0
  474. package/dist/internal/Email.js.map +1 -0
  475. package/dist/internal/Log.d.ts +32 -28
  476. package/dist/internal/Log.d.ts.map +1 -1
  477. package/dist/internal/Log.js +18 -11
  478. package/dist/internal/Log.js.map +1 -1
  479. package/dist/internal/MetricSink.d.ts +3 -0
  480. package/dist/internal/MetricSink.d.ts.map +1 -1
  481. package/dist/internal/MetricSink.js +67 -8
  482. package/dist/internal/MetricSink.js.map +1 -1
  483. package/dist/internal/Mpp.d.ts.map +1 -1
  484. package/dist/internal/Mpp.js +20 -25
  485. package/dist/internal/Mpp.js.map +1 -1
  486. package/dist/internal/OpenApi.d.ts +26 -3
  487. package/dist/internal/OpenApi.d.ts.map +1 -1
  488. package/dist/internal/OpenApi.js +25 -10
  489. package/dist/internal/OpenApi.js.map +1 -1
  490. package/dist/internal/Provider.d.ts +1 -1
  491. package/dist/internal/Provider.d.ts.map +1 -1
  492. package/dist/internal/RateLimit.d.ts.map +1 -1
  493. package/dist/internal/RateLimit.js +13 -1
  494. package/dist/internal/RateLimit.js.map +1 -1
  495. package/dist/internal/Store.d.ts +16 -0
  496. package/dist/internal/Store.d.ts.map +1 -1
  497. package/dist/internal/Store.js +59 -8
  498. package/dist/internal/Store.js.map +1 -1
  499. package/dist/internal/Tidx.d.ts +9 -2
  500. package/dist/internal/Tidx.d.ts.map +1 -1
  501. package/dist/internal/Tidx.js +78 -11
  502. package/dist/internal/Tidx.js.map +1 -1
  503. package/dist/internal/Timing.d.ts +26 -0
  504. package/dist/internal/Timing.d.ts.map +1 -1
  505. package/dist/internal/Timing.js +63 -5
  506. package/dist/internal/Timing.js.map +1 -1
  507. package/dist/internal/VercelOidc.d.ts +94 -0
  508. package/dist/internal/VercelOidc.d.ts.map +1 -0
  509. package/dist/internal/VercelOidc.js +128 -0
  510. package/dist/internal/VercelOidc.js.map +1 -0
  511. package/dist/internal/VerifiedTokens.d.ts +2 -8
  512. package/dist/internal/VerifiedTokens.d.ts.map +1 -1
  513. package/dist/internal/VerifiedTokens.js +24 -24
  514. package/dist/internal/VerifiedTokens.js.map +1 -1
  515. package/dist/internal/Viem.d.ts +30 -2067
  516. package/dist/internal/Viem.d.ts.map +1 -1
  517. package/dist/internal/Viem.js +167 -17
  518. package/dist/internal/Viem.js.map +1 -1
  519. package/dist/internal/Webhooks.d.ts +12 -4
  520. package/dist/internal/Webhooks.d.ts.map +1 -1
  521. package/dist/internal/Webhooks.js +9 -3
  522. package/dist/internal/Webhooks.js.map +1 -1
  523. package/dist/internal/ZoneRpc.d.ts +7 -0
  524. package/dist/internal/ZoneRpc.d.ts.map +1 -0
  525. package/dist/internal/ZoneRpc.js +49 -0
  526. package/dist/internal/ZoneRpc.js.map +1 -0
  527. package/dist/internal/index.d.ts +3 -1
  528. package/dist/internal/index.d.ts.map +1 -1
  529. package/dist/internal/index.js +3 -1
  530. package/dist/internal/index.js.map +1 -1
  531. package/dist/internal/rewards/Audit.d.ts +88 -0
  532. package/dist/internal/rewards/Audit.d.ts.map +1 -0
  533. package/dist/internal/rewards/Audit.js +134 -0
  534. package/dist/internal/rewards/Audit.js.map +1 -0
  535. package/dist/internal/rewards/Campaigns.d.ts +572 -0
  536. package/dist/internal/rewards/Campaigns.d.ts.map +1 -0
  537. package/dist/internal/rewards/Campaigns.js +531 -0
  538. package/dist/internal/rewards/Campaigns.js.map +1 -0
  539. package/dist/internal/rewards/Credits.d.ts +76 -0
  540. package/dist/internal/rewards/Credits.d.ts.map +1 -0
  541. package/dist/internal/rewards/Credits.js +95 -0
  542. package/dist/internal/rewards/Credits.js.map +1 -0
  543. package/dist/internal/rewards/Events.d.ts +100 -0
  544. package/dist/internal/rewards/Events.d.ts.map +1 -0
  545. package/dist/internal/rewards/Events.js +340 -0
  546. package/dist/internal/rewards/Events.js.map +1 -0
  547. package/dist/internal/rewards/Projection.d.ts +237 -0
  548. package/dist/internal/rewards/Projection.d.ts.map +1 -0
  549. package/dist/internal/rewards/Projection.js +616 -0
  550. package/dist/internal/rewards/Projection.js.map +1 -0
  551. package/dist/internal/rewards/Rates.d.ts +44 -0
  552. package/dist/internal/rewards/Rates.d.ts.map +1 -0
  553. package/dist/internal/rewards/Rates.js +60 -0
  554. package/dist/internal/rewards/Rates.js.map +1 -0
  555. package/dist/internal/rewards/Read.d.ts +158 -0
  556. package/dist/internal/rewards/Read.d.ts.map +1 -0
  557. package/dist/internal/rewards/Read.js +292 -0
  558. package/dist/internal/rewards/Read.js.map +1 -0
  559. package/dist/internal/rewards/Runner.d.ts +164 -0
  560. package/dist/internal/rewards/Runner.d.ts.map +1 -0
  561. package/dist/internal/rewards/Runner.js +1778 -0
  562. package/dist/internal/rewards/Runner.js.map +1 -0
  563. package/dist/internal/rewards/Signer.d.ts +224 -0
  564. package/dist/internal/rewards/Signer.d.ts.map +1 -0
  565. package/dist/internal/rewards/Signer.js +135 -0
  566. package/dist/internal/rewards/Signer.js.map +1 -0
  567. package/dist/internal/rewards/index.d.ts +15 -0
  568. package/dist/internal/rewards/index.d.ts.map +1 -0
  569. package/dist/internal/rewards/index.js +15 -0
  570. package/dist/internal/rewards/index.js.map +1 -0
  571. package/dist/internal/{funding → routes}/Action.d.ts +12 -1
  572. package/dist/internal/routes/Action.d.ts.map +1 -0
  573. package/dist/internal/{funding → routes}/Action.js +17 -9
  574. package/dist/internal/routes/Action.js.map +1 -0
  575. package/dist/internal/{funding → routes}/Catalog.d.ts +20 -20
  576. package/dist/internal/routes/Catalog.d.ts.map +1 -0
  577. package/dist/internal/{funding → routes}/Catalog.js +29 -29
  578. package/dist/internal/routes/Catalog.js.map +1 -0
  579. package/dist/internal/{funding → routes}/Chain.d.ts +10 -10
  580. package/dist/internal/routes/Chain.d.ts.map +1 -0
  581. package/dist/internal/{funding → routes}/Chain.js +3 -3
  582. package/dist/internal/routes/Chain.js.map +1 -0
  583. package/dist/internal/{funding → routes}/Deposit.d.ts +45 -23
  584. package/dist/internal/routes/Deposit.d.ts.map +1 -0
  585. package/dist/internal/{funding → routes}/Deposit.js +60 -27
  586. package/dist/internal/routes/Deposit.js.map +1 -0
  587. package/dist/internal/{funding → routes}/DepositAddress.d.ts +56 -27
  588. package/dist/internal/routes/DepositAddress.d.ts.map +1 -0
  589. package/dist/internal/{funding → routes}/DepositAddress.js +95 -33
  590. package/dist/internal/routes/DepositAddress.js.map +1 -0
  591. package/dist/internal/{funding → routes}/DepositWebhook.d.ts +4 -4
  592. package/dist/internal/routes/DepositWebhook.d.ts.map +1 -0
  593. package/dist/internal/{funding → routes}/DepositWebhook.js +4 -4
  594. package/dist/internal/routes/DepositWebhook.js.map +1 -0
  595. package/dist/internal/routes/Economics.d.ts +25 -0
  596. package/dist/internal/routes/Economics.d.ts.map +1 -0
  597. package/dist/internal/routes/Economics.js +28 -0
  598. package/dist/internal/routes/Economics.js.map +1 -0
  599. package/dist/internal/{funding → routes}/Evidence.d.ts +3 -3
  600. package/dist/internal/routes/Evidence.d.ts.map +1 -0
  601. package/dist/internal/{funding → routes}/Evidence.js +7 -7
  602. package/dist/internal/routes/Evidence.js.map +1 -0
  603. package/dist/internal/routes/Observability.d.ts +154 -0
  604. package/dist/internal/routes/Observability.d.ts.map +1 -0
  605. package/dist/internal/routes/Observability.js +389 -0
  606. package/dist/internal/routes/Observability.js.map +1 -0
  607. package/dist/internal/{funding → routes}/Provider.d.ts +311 -105
  608. package/dist/internal/routes/Provider.d.ts.map +1 -0
  609. package/dist/internal/{funding → routes}/Provider.js +229 -98
  610. package/dist/internal/routes/Provider.js.map +1 -0
  611. package/dist/internal/{funding → routes}/Reconciliation.d.ts +11 -6
  612. package/dist/internal/routes/Reconciliation.d.ts.map +1 -0
  613. package/dist/internal/{funding → routes}/Reconciliation.js +408 -158
  614. package/dist/internal/routes/Reconciliation.js.map +1 -0
  615. package/dist/internal/routes/Route.d.ts +21 -0
  616. package/dist/internal/routes/Route.d.ts.map +1 -0
  617. package/dist/internal/{funding → routes}/Route.js +1 -1
  618. package/dist/internal/routes/Route.js.map +1 -0
  619. package/dist/internal/{funding → routes}/SourceObservation.d.ts +6 -6
  620. package/dist/internal/routes/SourceObservation.d.ts.map +1 -0
  621. package/dist/internal/{funding → routes}/SourceObservation.js +8 -8
  622. package/dist/internal/routes/SourceObservation.js.map +1 -0
  623. package/dist/internal/{funding → routes}/Subsidy.d.ts +48 -3
  624. package/dist/internal/routes/Subsidy.d.ts.map +1 -0
  625. package/dist/internal/{funding → routes}/Subsidy.js +43 -3
  626. package/dist/internal/routes/Subsidy.js.map +1 -0
  627. package/dist/internal/{funding → routes}/Token.d.ts +4 -4
  628. package/dist/internal/routes/Token.d.ts.map +1 -0
  629. package/dist/internal/{funding → routes}/Token.js +3 -3
  630. package/dist/internal/routes/Token.js.map +1 -0
  631. package/dist/internal/{funding → routes}/Transfer.d.ts +241 -46
  632. package/dist/internal/routes/Transfer.d.ts.map +1 -0
  633. package/dist/internal/routes/Transfer.js +728 -0
  634. package/dist/internal/routes/Transfer.js.map +1 -0
  635. package/dist/internal/{funding → routes}/TransferReconciliation.d.ts +13 -10
  636. package/dist/internal/routes/TransferReconciliation.d.ts.map +1 -0
  637. package/dist/internal/routes/TransferReconciliation.js +422 -0
  638. package/dist/internal/routes/TransferReconciliation.js.map +1 -0
  639. package/dist/internal/routes/TransferSubsidy.d.ts +201 -0
  640. package/dist/internal/routes/TransferSubsidy.d.ts.map +1 -0
  641. package/dist/internal/routes/TransferSubsidy.js +256 -0
  642. package/dist/internal/routes/TransferSubsidy.js.map +1 -0
  643. package/dist/internal/{funding → routes}/TransferWebhook.d.ts +5 -5
  644. package/dist/internal/routes/TransferWebhook.d.ts.map +1 -0
  645. package/dist/internal/{funding → routes}/TransferWebhook.js +3 -3
  646. package/dist/internal/routes/TransferWebhook.js.map +1 -0
  647. package/dist/internal/{funding → routes}/index.d.ts +2 -0
  648. package/dist/internal/routes/index.d.ts.map +1 -0
  649. package/dist/internal/{funding → routes}/index.js +2 -0
  650. package/dist/internal/routes/index.js.map +1 -0
  651. package/dist/internal/{funding → routes}/providers/across.d.ts +4 -4
  652. package/dist/internal/routes/providers/across.d.ts.map +1 -0
  653. package/dist/internal/{funding → routes}/providers/across.js +13 -13
  654. package/dist/internal/routes/providers/across.js.map +1 -0
  655. package/dist/internal/{funding → routes}/providers/relay.d.ts +21 -12
  656. package/dist/internal/routes/providers/relay.d.ts.map +1 -0
  657. package/dist/internal/{funding → routes}/providers/relay.js +194 -110
  658. package/dist/internal/routes/providers/relay.js.map +1 -0
  659. package/dist/internal/{funding → routes}/providers/rhino.d.ts +4 -4
  660. package/dist/internal/routes/providers/rhino.d.ts.map +1 -0
  661. package/dist/internal/{funding → routes}/providers/rhino.js +10 -10
  662. package/dist/internal/routes/providers/rhino.js.map +1 -0
  663. package/dist/internal/{funding → routes}/providers/squid.d.ts +4 -4
  664. package/dist/internal/routes/providers/squid.d.ts.map +1 -0
  665. package/dist/internal/{funding → routes}/providers/squid.js +14 -14
  666. package/dist/internal/routes/providers/squid.js.map +1 -0
  667. package/dist/internal/{funding → routes}/providers/stargate.d.ts +46 -18
  668. package/dist/internal/routes/providers/stargate.d.ts.map +1 -0
  669. package/dist/internal/routes/providers/stargate.js +898 -0
  670. package/dist/internal/routes/providers/stargate.js.map +1 -0
  671. package/dist/internal/{funding → routes}/providers/symbiosis.d.ts +4 -4
  672. package/dist/internal/routes/providers/symbiosis.d.ts.map +1 -0
  673. package/dist/internal/{funding → routes}/providers/symbiosis.js +30 -20
  674. package/dist/internal/routes/providers/symbiosis.js.map +1 -0
  675. package/dist/internal/webhookDestinations/slack.js +12 -12
  676. package/dist/internal/webhookDestinations/slack.js.map +1 -1
  677. package/dist/providers/index.d.ts +12 -12
  678. package/dist/providers/index.d.ts.map +1 -1
  679. package/dist/providers/index.js +12 -12
  680. package/dist/providers/index.js.map +1 -1
  681. package/dist/server.d.ts +19 -0
  682. package/dist/server.d.ts.map +1 -0
  683. package/dist/server.js +19 -0
  684. package/dist/server.js.map +1 -0
  685. package/package.json +15 -4
  686. package/src/ApiKey.ts +1 -1
  687. package/src/ApiKeys.test.ts +1033 -3
  688. package/src/ApiKeys.ts +489 -48
  689. package/src/App.test-d.ts +1 -1
  690. package/src/App.test.ts +216 -25
  691. package/src/App.ts +334 -31
  692. package/src/Assets.test.ts +2 -2
  693. package/src/Assets.ts +3 -1
  694. package/src/Auth.test-d.ts +1 -1
  695. package/src/Client.test-d.ts +539 -110
  696. package/src/Handler.ts +0 -1
  697. package/src/OpenApi.contract.test.ts +195 -0
  698. package/src/Scope.ts +17 -5
  699. package/src/Webhooks.ts +1 -1
  700. package/src/admin/App.test.ts +30 -2
  701. package/src/admin/App.ts +42 -6
  702. package/src/admin/apps/api-keys.test.ts +267 -5
  703. package/src/admin/apps/api-keys.ts +100 -50
  704. package/src/admin/apps/earn-vaults.test.ts +158 -0
  705. package/src/admin/apps/earn-vaults.ts +679 -6
  706. package/src/admin/apps/organizations.test.ts +306 -17
  707. package/src/admin/apps/organizations.ts +299 -24
  708. package/src/admin/apps/routes-support.test.ts +200 -0
  709. package/src/admin/apps/routes-support.ts +201 -0
  710. package/src/admin/apps/routes.test.ts +450 -0
  711. package/src/admin/apps/routes.ts +896 -0
  712. package/src/admin/apps/scopes.test.ts +15 -5
  713. package/src/admin/apps/subsidies.test.ts +306 -0
  714. package/src/admin/apps/subsidies.ts +457 -0
  715. package/src/admin/apps/verified-tokens.test.ts +40 -3
  716. package/src/admin/apps/verified-tokens.ts +33 -7
  717. package/src/admin/ui/plugin.ts +1 -2
  718. package/src/admin/ui/src/components/RewardCampaignForm.tsx +1009 -0
  719. package/src/admin/ui/src/lib/config.ts +11 -2
  720. package/src/admin/ui/src/lib/earn-vaults.ts +2 -2
  721. package/src/admin/ui/src/lib/organizations.test.ts +83 -50
  722. package/src/admin/ui/src/lib/organizations.ts +106 -25
  723. package/src/admin/ui/src/lib/query-client.ts +1 -1
  724. package/src/admin/ui/src/lib/reward-campaigns.ts +136 -0
  725. package/src/admin/ui/src/lib/routes.test.ts +88 -0
  726. package/src/admin/ui/src/lib/routes.ts +304 -0
  727. package/src/admin/ui/src/lib/subsidies.ts +75 -0
  728. package/src/admin/ui/src/lib/verified-tokens.ts +24 -9
  729. package/src/admin/ui/src/routeTree.gen.ts +63 -0
  730. package/src/admin/ui/src/routes/__root.tsx +13 -2
  731. package/src/admin/ui/src/routes/api-keys.tsx +196 -84
  732. package/src/admin/ui/src/routes/earn.vaults_.$vaultId.edit.tsx +105 -70
  733. package/src/admin/ui/src/routes/organizations.tsx +34 -4
  734. package/src/admin/ui/src/routes/organizations_.$orgId.tsx +239 -23
  735. package/src/admin/ui/src/routes/routes.tsx +1615 -0
  736. package/src/admin/ui/src/routes/routes_.support.tsx +248 -0
  737. package/src/admin/ui/src/routes/subsidies.tsx +799 -0
  738. package/src/admin/ui/src/routes/verified-tokens.tsx +64 -20
  739. package/src/admin/ui.generated.ts +202 -188
  740. package/src/analytics/Analytics.test.ts +108 -18
  741. package/src/analytics/Analytics.ts +38 -6
  742. package/src/analytics/tables/requestEvents.test.ts +100 -0
  743. package/src/analytics/tables/requestEvents.ts +10 -1
  744. package/src/analytics/tables/routesLifecycleIntervals.ts +140 -0
  745. package/src/apps/Zones.test.ts +15 -0
  746. package/src/apps/Zones.ts +52 -5
  747. package/src/apps/composition.test.ts +68 -60
  748. package/src/apps/data/App.test.ts +180 -2
  749. package/src/apps/data/App.ts +88 -28
  750. package/src/apps/data/routes/activities.test.ts +419 -7
  751. package/src/apps/data/routes/activities.ts +683 -216
  752. package/src/apps/data/routes/balances.test.ts +2 -2
  753. package/src/apps/data/routes/blocks.test.ts +46 -1
  754. package/src/apps/data/routes/coingecko.test.ts +419 -1
  755. package/src/apps/data/routes/coingecko.ts +309 -253
  756. package/src/apps/data/routes/earn.discovery.test.ts +274 -0
  757. package/src/apps/data/routes/earn.test.ts +1294 -17
  758. package/src/apps/data/routes/earn.ts +1838 -321
  759. package/src/apps/data/routes/exchanges.test.ts +12 -15
  760. package/src/apps/data/routes/fee-amm.test.ts +243 -0
  761. package/src/apps/data/routes/fee-amm.ts +201 -162
  762. package/src/apps/data/routes/indexer.test.ts +389 -0
  763. package/src/apps/data/routes/indexer.ts +165 -69
  764. package/src/apps/data/routes/receipts.test.ts +1 -1
  765. package/src/apps/data/routes/rpc.test.ts +384 -8
  766. package/src/apps/data/routes/rpc.ts +452 -227
  767. package/src/apps/data/routes/rpc.zone.test.ts +340 -0
  768. package/src/apps/data/routes/tokenlist.test.ts +285 -0
  769. package/src/apps/data/routes/tokenlist.ts +173 -88
  770. package/src/apps/data/routes/tokens.test.ts +93 -3
  771. package/src/apps/data/routes/tokens.ts +39 -23
  772. package/src/apps/data/routes/transactions.test.ts +1 -1
  773. package/src/apps/data/routes/transfers.test.ts +56 -24
  774. package/src/apps/data/routes/transfers.ts +19 -8
  775. package/src/apps/data/routes/valuation.test.ts +1 -1
  776. package/src/apps/data/routes/verified-tokens.test.ts +345 -0
  777. package/src/apps/data/routes/verified-tokens.ts +99 -29
  778. package/src/apps/data/routes/webhooks.scan.test.ts +29 -0
  779. package/src/apps/data/routes/webhooks.test.ts +651 -83
  780. package/src/apps/data/routes/webhooks.ts +1113 -868
  781. package/src/apps/data/routes/zones.test.ts +148 -71
  782. package/src/apps/data/routes/zones.ts +71 -55
  783. package/src/apps/docs/reference.ts +2 -2
  784. package/src/apps/index.ts +1 -1
  785. package/src/apps/management/App.ts +9 -51
  786. package/src/apps/management/Billing.test.ts +375 -14
  787. package/src/apps/management/Billing.ts +265 -29
  788. package/src/apps/management/routes/api-keys.test.ts +269 -7
  789. package/src/apps/management/routes/api-keys.ts +61 -20
  790. package/src/apps/management/routes/billing.test.ts +477 -15
  791. package/src/apps/management/routes/billing.ts +377 -50
  792. package/src/apps/management/routes/faucet.test.ts +1 -1
  793. package/src/apps/management/routes/faucet.ts +1 -1
  794. package/src/apps/management/routes/invitations.test.ts +270 -3
  795. package/src/apps/management/routes/invitations.ts +185 -15
  796. package/src/apps/management/routes/invoicePreview.test.ts +549 -0
  797. package/src/apps/management/routes/me.test.ts +246 -5
  798. package/src/apps/management/routes/me.ts +7 -2
  799. package/src/apps/management/routes/members.test.ts +108 -0
  800. package/src/apps/management/routes/orgs.test.ts +191 -3
  801. package/src/apps/management/routes/orgs.ts +58 -11
  802. package/src/apps/management/routes/projects.test.ts +33 -3
  803. package/src/apps/management/routes/projects.ts +6 -1
  804. package/src/apps/management/routes/scopes.test.ts +30 -2
  805. package/src/apps/management/routes/scopes.ts +4 -1
  806. package/src/apps/management/routes/usage.test.ts +32 -0
  807. package/src/apps/management/routes/usage.ts +22 -4
  808. package/src/apps/management/routes/verified-token-requests.test.ts +16 -2
  809. package/src/apps/management/routes/verified-token-requests.ts +7 -10
  810. package/src/apps/management/routes/webhooks.test.ts +49 -26
  811. package/src/apps/management/routes/webhooks.ts +78 -22
  812. package/src/apps/mcp.test.ts +113 -30
  813. package/src/apps/mcp.ts +22 -10
  814. package/src/apps/mpp/App.ts +37 -7
  815. package/src/apps/mpp/Mpp.test.ts +49 -8
  816. package/src/apps/mpp/Mpp.zone.test.ts +219 -0
  817. package/src/apps/mpp/internal/Adapter.ts +34 -0
  818. package/src/apps/mpp/internal/Policy.test.ts +86 -31
  819. package/src/apps/mpp/internal/Policy.ts +49 -7
  820. package/src/apps/mpp/internal/Sponsorship.test.ts +207 -0
  821. package/src/apps/mpp/internal/Sponsorship.ts +9 -3
  822. package/src/apps/relay/App.test.ts +839 -64
  823. package/src/apps/relay/App.ts +148 -81
  824. package/src/apps/relay/App.zone-billing.test.ts +257 -0
  825. package/src/apps/relay/Sponsorships.test.ts +67 -4
  826. package/src/apps/relay/Sponsorships.ts +233 -32
  827. package/src/apps/relay/Sponsorships.zone.test.ts +102 -0
  828. package/src/apps/{funding → routes}/Access.ts +6 -6
  829. package/src/apps/routes/App.test.ts +165 -0
  830. package/src/apps/routes/App.ts +96 -0
  831. package/src/apps/{funding → routes}/Inventory.ts +2 -2
  832. package/src/apps/routes/index.ts +1 -0
  833. package/src/apps/{funding → routes}/routes/chains.test.ts +66 -66
  834. package/src/apps/{funding → routes}/routes/chains.ts +23 -23
  835. package/src/apps/{funding → routes}/routes/deposit-addresses.test.ts +1358 -458
  836. package/src/apps/{funding → routes}/routes/deposit-addresses.ts +566 -246
  837. package/src/apps/{funding → routes}/routes/providers.test.ts +27 -33
  838. package/src/apps/{funding → routes}/routes/providers.ts +23 -23
  839. package/src/apps/{funding → routes}/routes/quotes.test.ts +298 -41
  840. package/src/apps/{funding → routes}/routes/quotes.ts +57 -40
  841. package/src/apps/{funding → routes}/routes/transfers.test.ts +1100 -353
  842. package/src/apps/routes/routes/transfers.ts +1332 -0
  843. package/src/cli/Cli.test.ts +1 -1
  844. package/src/cli/commands/admin.test.ts +748 -1
  845. package/src/cli/commands/admin.ts +278 -0
  846. package/src/cloudflare.ts +52 -47
  847. package/src/db/Db.test.ts +245 -2
  848. package/src/db/Db.ts +1485 -34
  849. package/src/db/Schema.ts +729 -228
  850. package/src/db/tables/apiKeyAdmissionBootstraps.ts +4 -0
  851. package/src/db/tables/apiKeyAdmissions.ts +218 -0
  852. package/src/db/tables/apiKeyOwnerAdmissions.ts +4 -0
  853. package/src/db/tables/apiKeyOwnerTombstones.ts +81 -0
  854. package/src/db/tables/apiKeyRevocations.test.ts +74 -0
  855. package/src/db/tables/apiKeyRevocations.ts +121 -0
  856. package/src/db/tables/authAccounts.ts +105 -0
  857. package/src/db/tables/authSessions.ts +13 -0
  858. package/src/db/tables/authVerifications.ts +13 -0
  859. package/src/db/tables/invitations.ts +142 -45
  860. package/src/db/tables/memberships.ts +79 -3
  861. package/src/db/tables/organizations.test.ts +690 -13
  862. package/src/db/tables/organizations.ts +139 -55
  863. package/src/db/tables/projects.test.ts +16 -0
  864. package/src/db/tables/projects.ts +13 -3
  865. package/src/db/tables/requestUsage.ts +4 -1
  866. package/src/db/tables/rewardAccounts.ts +178 -0
  867. package/src/db/tables/rewardCampaignDistributors.ts +68 -0
  868. package/src/db/tables/rewardCampaigns.test.ts +1388 -0
  869. package/src/db/tables/rewardCampaigns.ts +647 -0
  870. package/src/db/tables/rewardCredits.ts +110 -0
  871. package/src/db/tables/rewardEligibilityAssociations.test.ts +271 -0
  872. package/src/db/tables/rewardEligibilityAssociations.ts +184 -0
  873. package/src/db/tables/rewardRuns.ts +514 -0
  874. package/src/db/tables/rewardTransactionAttempts.ts +272 -0
  875. package/src/db/tables/routesCatalog.test.ts +185 -0
  876. package/src/db/tables/routesCatalog.ts +163 -0
  877. package/src/db/tables/routesDepositAddresses.test.ts +1048 -0
  878. package/src/db/tables/routesDepositAddresses.ts +1008 -0
  879. package/src/db/tables/{fundingDepositRequestObservations.test.ts → routesDepositRequestObservations.test.ts} +13 -14
  880. package/src/db/tables/{fundingDepositRequestObservations.ts → routesDepositRequestObservations.ts} +10 -10
  881. package/src/db/tables/{fundingDeposits.test.ts → routesDeposits.test.ts} +388 -46
  882. package/src/db/tables/routesDeposits.ts +1062 -0
  883. package/src/db/tables/routesIdempotency.test.ts +796 -0
  884. package/src/db/tables/routesIdempotency.ts +496 -0
  885. package/src/db/tables/routesSubsidies.test.ts +120 -0
  886. package/src/db/tables/routesSubsidies.ts +71 -0
  887. package/src/db/tables/{fundingTransferEvents.ts → routesTransferEvents.ts} +4 -4
  888. package/src/db/tables/routesTransferSubsidies.ts +38 -0
  889. package/src/db/tables/routesTransferSubsidyNonces.ts +124 -0
  890. package/src/db/tables/routesTransferTransactions.test.ts +195 -0
  891. package/src/db/tables/{fundingTransferTransactions.ts → routesTransferTransactions.ts} +63 -18
  892. package/src/db/tables/routesTransfers.test.ts +338 -0
  893. package/src/db/tables/routesTransfers.ts +662 -0
  894. package/src/db/tables/sponsoredTransactions.test.ts +269 -45
  895. package/src/db/tables/sponsoredTransactions.ts +225 -65
  896. package/src/db/tables/sponsorshipAttributions.test.ts +160 -0
  897. package/src/db/tables/sponsorshipAttributions.ts +168 -0
  898. package/src/db/tables/sponsorshipReconciliationCursors.test.ts +115 -0
  899. package/src/db/tables/sponsorshipReconciliationCursors.ts +67 -0
  900. package/src/db/tables/stripeCustomers.test.ts +85 -0
  901. package/src/db/tables/stripeCustomers.ts +24 -0
  902. package/src/db/tables/users.test.ts +129 -0
  903. package/src/db/tables/users.ts +49 -3
  904. package/src/db/tables/verifiedTokenRequests.test.ts +39 -20
  905. package/src/db/tables/verifiedTokenRequests.ts +80 -44
  906. package/src/db/tables/webhookQueueEvents.ts +8 -1
  907. package/src/db/tables/webhookSubscriptions.ts +95 -20
  908. package/src/handlers/internal/executionError.ts +3 -4
  909. package/src/handlers/internal/multisig.ts +13 -816
  910. package/src/handlers/internal/sponsorship.ts +26 -10
  911. package/src/handlers/relay.test-d.ts +9 -1
  912. package/src/handlers/relay.test.ts +823 -3
  913. package/src/handlers/relay.ts +127 -107
  914. package/src/index.test-d.ts +7 -0
  915. package/src/index.ts +0 -17
  916. package/src/internal/AssetResponse.ts +26 -0
  917. package/src/internal/Auth.test.ts +1656 -9
  918. package/src/internal/Auth.ts +880 -244
  919. package/src/internal/BetterAuth.test.ts +242 -0
  920. package/src/internal/BetterAuth.ts +349 -0
  921. package/src/internal/Cache.ts +2 -0
  922. package/src/internal/EarnRates.test.ts +17 -0
  923. package/src/internal/EarnRates.ts +124 -31
  924. package/src/internal/EarnSharePrices.test.ts +182 -0
  925. package/src/internal/EarnSharePrices.ts +313 -0
  926. package/src/internal/EarnVaults.test.ts +21 -0
  927. package/src/internal/EarnVaults.ts +33 -11
  928. package/src/internal/Email.ts +54 -0
  929. package/src/internal/Idempotency.test.ts +2 -2
  930. package/src/internal/Log.test-d.ts +8 -7
  931. package/src/internal/Log.test.ts +114 -16
  932. package/src/internal/Log.ts +53 -40
  933. package/src/internal/MetricSink.test.ts +313 -26
  934. package/src/internal/MetricSink.ts +73 -8
  935. package/src/internal/Mpp.test.ts +31 -0
  936. package/src/internal/Mpp.ts +21 -24
  937. package/src/internal/OpenApi.ts +45 -12
  938. package/src/internal/Provider.test.ts +1 -1
  939. package/src/internal/Provider.ts +1 -1
  940. package/src/internal/RateLimit.test.ts +21 -3
  941. package/src/internal/RateLimit.ts +12 -1
  942. package/src/internal/Store.test-d.ts +1 -1
  943. package/src/internal/Store.test.ts +151 -8
  944. package/src/internal/Store.ts +76 -9
  945. package/src/internal/Tidx.test.ts +59 -8
  946. package/src/internal/Tidx.ts +86 -14
  947. package/src/internal/Timing.test.ts +77 -0
  948. package/src/internal/Timing.ts +83 -6
  949. package/src/internal/VercelOidc.test.ts +188 -0
  950. package/src/internal/VercelOidc.ts +193 -0
  951. package/src/internal/VerifiedTokens.test.ts +60 -6
  952. package/src/internal/VerifiedTokens.ts +21 -24
  953. package/src/internal/Viem.batch.test.ts +80 -0
  954. package/src/internal/Viem.test.ts +201 -2
  955. package/src/internal/Viem.ts +221 -25
  956. package/src/internal/Webhooks.test.ts +85 -6
  957. package/src/internal/Webhooks.ts +22 -4
  958. package/src/internal/ZoneRpc.ts +50 -0
  959. package/src/internal/exchange/Provider.test.ts +2 -2
  960. package/src/internal/index.test.ts +3 -1
  961. package/src/internal/index.ts +3 -1
  962. package/src/internal/rewards/Audit.ts +231 -0
  963. package/src/internal/rewards/Campaigns.test.ts +1234 -0
  964. package/src/internal/rewards/Campaigns.ts +1205 -0
  965. package/src/internal/rewards/Credits.ts +165 -0
  966. package/src/internal/rewards/Events.local.test.ts +113 -0
  967. package/src/internal/rewards/Events.test.ts +152 -0
  968. package/src/internal/rewards/Events.ts +468 -0
  969. package/src/internal/rewards/Projection.test.ts +681 -0
  970. package/src/internal/rewards/Projection.ts +987 -0
  971. package/src/internal/rewards/Rates.test.ts +171 -0
  972. package/src/internal/rewards/Rates.ts +110 -0
  973. package/src/internal/rewards/Read.test.ts +501 -0
  974. package/src/internal/rewards/Read.ts +476 -0
  975. package/src/internal/rewards/Runner.checkpoint.test.ts +80 -0
  976. package/src/internal/rewards/Runner.states.test.ts +188 -0
  977. package/src/internal/rewards/Runner.test.ts +90 -0
  978. package/src/internal/rewards/Runner.ts +2229 -0
  979. package/src/internal/rewards/Signer.test.ts +79 -0
  980. package/src/internal/rewards/Signer.ts +180 -0
  981. package/src/internal/rewards/index.ts +14 -0
  982. package/src/internal/{funding → routes}/Action.test.ts +63 -14
  983. package/src/internal/{funding → routes}/Action.ts +35 -8
  984. package/src/internal/{funding → routes}/Catalog.test.ts +3 -3
  985. package/src/internal/{funding → routes}/Catalog.ts +39 -39
  986. package/src/internal/{funding → routes}/Chain.test.ts +1 -1
  987. package/src/internal/{funding → routes}/Chain.ts +11 -11
  988. package/src/internal/{funding → routes}/Deposit.test.ts +1 -1
  989. package/src/internal/{funding → routes}/Deposit.ts +93 -45
  990. package/src/internal/{funding → routes}/DepositAddress.test.ts +11 -3
  991. package/src/internal/{funding → routes}/DepositAddress.ts +132 -53
  992. package/src/internal/{funding → routes}/DepositWebhook.test.ts +61 -18
  993. package/src/internal/{funding → routes}/DepositWebhook.ts +9 -9
  994. package/src/internal/routes/Economics.test.ts +42 -0
  995. package/src/internal/routes/Economics.ts +47 -0
  996. package/src/internal/{funding → routes}/Evidence.test.ts +6 -6
  997. package/src/internal/{funding → routes}/Evidence.ts +9 -9
  998. package/src/internal/routes/Observability.test.ts +636 -0
  999. package/src/internal/routes/Observability.ts +668 -0
  1000. package/src/internal/{funding → routes}/Provider.test.ts +489 -153
  1001. package/src/internal/{funding → routes}/Provider.ts +489 -186
  1002. package/src/internal/{funding → routes}/Reconciliation.local.test.ts +84 -12
  1003. package/src/internal/{funding → routes}/Reconciliation.test.ts +1213 -279
  1004. package/src/internal/{funding → routes}/Reconciliation.ts +501 -203
  1005. package/src/internal/routes/Reconciliation.unattributed.test.ts +250 -0
  1006. package/src/internal/{funding → routes}/Route.ts +7 -7
  1007. package/src/internal/{funding → routes}/SourceObservation.test.ts +13 -14
  1008. package/src/internal/{funding → routes}/SourceObservation.ts +13 -13
  1009. package/src/internal/{funding → routes}/Subsidy.local.test.ts +7 -7
  1010. package/src/internal/routes/Subsidy.test.ts +169 -0
  1011. package/src/internal/{funding → routes}/Subsidy.ts +86 -6
  1012. package/src/internal/{funding → routes}/Token.test.ts +1 -1
  1013. package/src/internal/{funding → routes}/Token.ts +5 -5
  1014. package/src/internal/routes/Transfer.test.ts +1199 -0
  1015. package/src/internal/routes/Transfer.ts +1206 -0
  1016. package/src/internal/routes/TransferReconciliation.test.ts +731 -0
  1017. package/src/internal/routes/TransferReconciliation.ts +527 -0
  1018. package/src/internal/routes/TransferSubsidy.test.ts +172 -0
  1019. package/src/internal/routes/TransferSubsidy.ts +447 -0
  1020. package/src/internal/{funding → routes}/TransferWebhook.test.ts +13 -13
  1021. package/src/internal/{funding → routes}/TransferWebhook.ts +7 -7
  1022. package/src/internal/{funding → routes}/index.test.ts +5 -3
  1023. package/src/internal/{funding → routes}/index.ts +2 -0
  1024. package/src/internal/{funding → routes}/providers/across.ts +16 -16
  1025. package/src/internal/{funding → routes}/providers/index.test.ts +157 -44
  1026. package/src/internal/{funding → routes}/providers/relay.test.ts +224 -32
  1027. package/src/internal/{funding → routes}/providers/relay.ts +228 -121
  1028. package/src/internal/{funding → routes}/providers/rhino.ts +16 -16
  1029. package/src/internal/{funding → routes}/providers/squid.ts +17 -17
  1030. package/src/internal/routes/providers/stargate.test.ts +728 -0
  1031. package/src/internal/routes/providers/stargate.ts +1276 -0
  1032. package/src/internal/{funding → routes}/providers/symbiosis.ts +64 -24
  1033. package/src/internal/webhookDestinations/slack.ts +10 -10
  1034. package/src/providers/index.ts +13 -13
  1035. package/src/server.ts +18 -0
  1036. package/dist/apps/funding/Access.d.ts.map +0 -1
  1037. package/dist/apps/funding/Access.js.map +0 -1
  1038. package/dist/apps/funding/App.js.map +0 -1
  1039. package/dist/apps/funding/Inventory.d.ts.map +0 -1
  1040. package/dist/apps/funding/Inventory.js.map +0 -1
  1041. package/dist/apps/funding/ProviderAttempts.d.ts +0 -5
  1042. package/dist/apps/funding/ProviderAttempts.d.ts.map +0 -1
  1043. package/dist/apps/funding/ProviderAttempts.js +0 -24
  1044. package/dist/apps/funding/ProviderAttempts.js.map +0 -1
  1045. package/dist/apps/funding/index.d.ts +0 -2
  1046. package/dist/apps/funding/index.d.ts.map +0 -1
  1047. package/dist/apps/funding/index.js +0 -2
  1048. package/dist/apps/funding/index.js.map +0 -1
  1049. package/dist/apps/funding/routes/chains.d.ts.map +0 -1
  1050. package/dist/apps/funding/routes/chains.js.map +0 -1
  1051. package/dist/apps/funding/routes/deposit-addresses.d.ts.map +0 -1
  1052. package/dist/apps/funding/routes/deposit-addresses.js.map +0 -1
  1053. package/dist/apps/funding/routes/providers.d.ts.map +0 -1
  1054. package/dist/apps/funding/routes/providers.js +0 -57
  1055. package/dist/apps/funding/routes/providers.js.map +0 -1
  1056. package/dist/apps/funding/routes/quotes.d.ts.map +0 -1
  1057. package/dist/apps/funding/routes/quotes.js.map +0 -1
  1058. package/dist/apps/funding/routes/transfers.d.ts.map +0 -1
  1059. package/dist/apps/funding/routes/transfers.js +0 -828
  1060. package/dist/apps/funding/routes/transfers.js.map +0 -1
  1061. package/dist/db/tables/fundingCatalog.d.ts +0 -58
  1062. package/dist/db/tables/fundingCatalog.d.ts.map +0 -1
  1063. package/dist/db/tables/fundingCatalog.js.map +0 -1
  1064. package/dist/db/tables/fundingDepositAddresses.d.ts +0 -192
  1065. package/dist/db/tables/fundingDepositAddresses.d.ts.map +0 -1
  1066. package/dist/db/tables/fundingDepositAddresses.js +0 -235
  1067. package/dist/db/tables/fundingDepositAddresses.js.map +0 -1
  1068. package/dist/db/tables/fundingDepositRequestObservations.d.ts.map +0 -1
  1069. package/dist/db/tables/fundingDepositRequestObservations.js.map +0 -1
  1070. package/dist/db/tables/fundingDeposits.d.ts.map +0 -1
  1071. package/dist/db/tables/fundingDeposits.js +0 -295
  1072. package/dist/db/tables/fundingDeposits.js.map +0 -1
  1073. package/dist/db/tables/fundingIdempotency.d.ts +0 -91
  1074. package/dist/db/tables/fundingIdempotency.d.ts.map +0 -1
  1075. package/dist/db/tables/fundingIdempotency.js +0 -103
  1076. package/dist/db/tables/fundingIdempotency.js.map +0 -1
  1077. package/dist/db/tables/fundingTransferEvents.d.ts.map +0 -1
  1078. package/dist/db/tables/fundingTransferEvents.js.map +0 -1
  1079. package/dist/db/tables/fundingTransferTransactions.d.ts +0 -53
  1080. package/dist/db/tables/fundingTransferTransactions.d.ts.map +0 -1
  1081. package/dist/db/tables/fundingTransferTransactions.js.map +0 -1
  1082. package/dist/db/tables/fundingTransfers.d.ts +0 -99
  1083. package/dist/db/tables/fundingTransfers.d.ts.map +0 -1
  1084. package/dist/db/tables/fundingTransfers.js +0 -110
  1085. package/dist/db/tables/fundingTransfers.js.map +0 -1
  1086. package/dist/internal/funding/Action.d.ts.map +0 -1
  1087. package/dist/internal/funding/Action.js.map +0 -1
  1088. package/dist/internal/funding/Catalog.d.ts.map +0 -1
  1089. package/dist/internal/funding/Catalog.js.map +0 -1
  1090. package/dist/internal/funding/Chain.d.ts.map +0 -1
  1091. package/dist/internal/funding/Chain.js.map +0 -1
  1092. package/dist/internal/funding/Deposit.d.ts.map +0 -1
  1093. package/dist/internal/funding/Deposit.js.map +0 -1
  1094. package/dist/internal/funding/DepositAddress.d.ts.map +0 -1
  1095. package/dist/internal/funding/DepositAddress.js.map +0 -1
  1096. package/dist/internal/funding/DepositWebhook.d.ts.map +0 -1
  1097. package/dist/internal/funding/DepositWebhook.js.map +0 -1
  1098. package/dist/internal/funding/Evidence.d.ts.map +0 -1
  1099. package/dist/internal/funding/Evidence.js.map +0 -1
  1100. package/dist/internal/funding/Provider.d.ts.map +0 -1
  1101. package/dist/internal/funding/Provider.js.map +0 -1
  1102. package/dist/internal/funding/Reconciliation.d.ts.map +0 -1
  1103. package/dist/internal/funding/Reconciliation.js.map +0 -1
  1104. package/dist/internal/funding/Route.d.ts +0 -21
  1105. package/dist/internal/funding/Route.d.ts.map +0 -1
  1106. package/dist/internal/funding/Route.js.map +0 -1
  1107. package/dist/internal/funding/SourceObservation.d.ts.map +0 -1
  1108. package/dist/internal/funding/SourceObservation.js.map +0 -1
  1109. package/dist/internal/funding/Subsidy.d.ts.map +0 -1
  1110. package/dist/internal/funding/Subsidy.js.map +0 -1
  1111. package/dist/internal/funding/Token.d.ts.map +0 -1
  1112. package/dist/internal/funding/Token.js.map +0 -1
  1113. package/dist/internal/funding/Transfer.d.ts.map +0 -1
  1114. package/dist/internal/funding/Transfer.js +0 -462
  1115. package/dist/internal/funding/Transfer.js.map +0 -1
  1116. package/dist/internal/funding/TransferReconciliation.d.ts.map +0 -1
  1117. package/dist/internal/funding/TransferReconciliation.js +0 -192
  1118. package/dist/internal/funding/TransferReconciliation.js.map +0 -1
  1119. package/dist/internal/funding/TransferWebhook.d.ts.map +0 -1
  1120. package/dist/internal/funding/TransferWebhook.js.map +0 -1
  1121. package/dist/internal/funding/index.d.ts.map +0 -1
  1122. package/dist/internal/funding/index.js.map +0 -1
  1123. package/dist/internal/funding/providers/across.d.ts.map +0 -1
  1124. package/dist/internal/funding/providers/across.js.map +0 -1
  1125. package/dist/internal/funding/providers/relay.d.ts.map +0 -1
  1126. package/dist/internal/funding/providers/relay.js.map +0 -1
  1127. package/dist/internal/funding/providers/rhino.d.ts.map +0 -1
  1128. package/dist/internal/funding/providers/rhino.js.map +0 -1
  1129. package/dist/internal/funding/providers/squid.d.ts.map +0 -1
  1130. package/dist/internal/funding/providers/squid.js.map +0 -1
  1131. package/dist/internal/funding/providers/stargate.d.ts.map +0 -1
  1132. package/dist/internal/funding/providers/stargate.js +0 -579
  1133. package/dist/internal/funding/providers/stargate.js.map +0 -1
  1134. package/dist/internal/funding/providers/symbiosis.d.ts.map +0 -1
  1135. package/dist/internal/funding/providers/symbiosis.js.map +0 -1
  1136. package/src/apps/funding/App.test.ts +0 -78
  1137. package/src/apps/funding/App.ts +0 -88
  1138. package/src/apps/funding/ProviderAttempts.ts +0 -26
  1139. package/src/apps/funding/index.ts +0 -1
  1140. package/src/apps/funding/routes/transfers.ts +0 -987
  1141. package/src/db/tables/fundingCatalog.test.ts +0 -122
  1142. package/src/db/tables/fundingCatalog.ts +0 -163
  1143. package/src/db/tables/fundingDepositAddresses.test.ts +0 -608
  1144. package/src/db/tables/fundingDepositAddresses.ts +0 -443
  1145. package/src/db/tables/fundingDeposits.ts +0 -572
  1146. package/src/db/tables/fundingIdempotency.test.ts +0 -182
  1147. package/src/db/tables/fundingIdempotency.ts +0 -180
  1148. package/src/db/tables/fundingTransferTransactions.test.ts +0 -112
  1149. package/src/db/tables/fundingTransfers.test.ts +0 -115
  1150. package/src/db/tables/fundingTransfers.ts +0 -189
  1151. package/src/handlers/internal/multisig.test.ts +0 -818
  1152. package/src/internal/funding/Subsidy.test.ts +0 -75
  1153. package/src/internal/funding/Transfer.test.ts +0 -524
  1154. package/src/internal/funding/Transfer.ts +0 -762
  1155. package/src/internal/funding/TransferReconciliation.test.ts +0 -147
  1156. package/src/internal/funding/TransferReconciliation.ts +0 -264
  1157. package/src/internal/funding/providers/stargate.test.ts +0 -328
  1158. package/src/internal/funding/providers/stargate.ts +0 -856
  1159. /package/dist/apps/{funding → routes}/Inventory.d.ts +0 -0
  1160. /package/src/internal/{funding → routes}/Route.test.ts +0 -0
@@ -1,13 +1,18 @@
1
1
  import * as Accounts from 'accounts/server'
2
+ import { splitSetCookieHeader } from 'better-auth/cookies'
2
3
  import { Hono } from 'hono'
3
4
  import type { Context as hono_Context, MiddlewareHandler } from 'hono'
5
+ import { deleteCookie, getCookie, setCookie } from 'hono/cookie'
4
6
  import type { HonoBase } from 'hono/hono-base'
5
7
  import { createMiddleware } from 'hono/factory'
6
8
  import { matchedRoutes } from 'hono/route'
7
9
  import type { MergePath, RouterRoute, Schema as core_Schema } from 'hono/types'
8
10
  import { findTargetHandler } from 'hono/utils/handler'
11
+ import * as jose from 'jose'
12
+ import { sql } from 'kysely'
9
13
  import { Challenge, Credential, type Method } from 'mppx'
10
14
  import { Mppx, tempo } from 'mppx/hono'
15
+ import { Address, Hex } from 'ox'
11
16
  import { Addresses } from 'viem/tempo'
12
17
  import { tempoMainnet } from 'viem/tempo/chains'
13
18
  import * as z from 'zod/mini'
@@ -15,25 +20,69 @@ import * as z from 'zod/mini'
15
20
  import type * as App from '../App.js'
16
21
  import * as ApiKey from '../ApiKey.js'
17
22
  import * as ApiKeys from '../ApiKeys.js'
23
+ import * as ApiKeyAdmissions from '../db/tables/apiKeyAdmissions.js'
24
+ import * as ApiKeyOwnerTombstones from '../db/tables/apiKeyOwnerTombstones.js'
25
+ import * as AuthAccounts from '../db/tables/authAccounts.js'
26
+ import * as BetterAuth from './BetterAuth.js'
18
27
  import * as Db from '../db/Db.js'
19
- import type * as Store from './Store.js'
28
+ import type * as Email from './Email.js'
20
29
  import * as Memberships from '../db/tables/memberships.js'
21
30
  import * as IpAllowlist from './IpAllowlist.js'
22
31
  import * as Metadata from '../apps/metadata.js'
23
32
  import * as OpenApi from './OpenApi.js'
24
33
  import * as Organizations from '../db/tables/organizations.js'
34
+ import * as Path from './Path.js'
25
35
  import * as Projects from '../db/tables/projects.js'
26
36
  import * as RateLimit from './RateLimit.js'
27
37
  import * as Response from './Response.js'
28
38
  import * as Schema from './Schema.js'
29
39
  import * as Scope from '../Scope.js'
40
+ import type * as Store from './Store.js'
41
+ import * as Timing from './Timing.js'
30
42
  import * as Users from '../db/tables/users.js'
31
43
  import type * as Viem from './Viem.js'
32
44
 
33
45
  const policySymbol = Symbol('tempo-api.auth.policy')
34
46
  const mppManagementSymbol = Symbol('tempo-api.auth.mpp-management')
47
+ const trustedClientIps = new WeakMap<Request, string>()
35
48
  const defaultApiKeyRateLimit = { limit: 10_000, period: 'minute' } satisfies RateLimit.Limit
49
+ const defaultIdentitySessionTtl = 24 * 60 * 60
36
50
  const defaultMppRateLimit = { limit: 100, period: 'minute' } satisfies RateLimit.Limit
51
+ const defaultPublicRateLimit = { limit: 60, period: 'minute' } satisfies RateLimit.Limit
52
+ const identityCookieName = 'tempo_identity'
53
+ const walletIdentityIssuer = 'https://wallet.tempo.xyz/api/oidc'
54
+
55
+ type IdentitySession = {
56
+ /** Wallet address asserted by the identity token. */
57
+ address: string
58
+ /** Verified email asserted by the identity token. */
59
+ email?: string | undefined
60
+ /** Unix timestamp when the session expires. */
61
+ expiresAt: number
62
+ /** Unix timestamp when the session was issued. */
63
+ issuedAt: number
64
+ }
65
+
66
+ type WalletSession = {
67
+ /** Wallet address used to resolve the canonical user. */
68
+ address: string
69
+ /** Verified email used to reconcile the canonical user. */
70
+ email?: string | undefined
71
+ }
72
+
73
+ function isIdentityTokenError(error: unknown) {
74
+ return (
75
+ error instanceof jose.errors.JOSEAlgNotAllowed ||
76
+ error instanceof jose.errors.JOSENotSupported ||
77
+ error instanceof jose.errors.JWSInvalid ||
78
+ error instanceof jose.errors.JWKSNoMatchingKey ||
79
+ error instanceof jose.errors.JWSSignatureVerificationFailed ||
80
+ error instanceof jose.errors.JWTClaimValidationFailed ||
81
+ error instanceof jose.errors.JWTExpired ||
82
+ error instanceof jose.errors.JWTInvalid ||
83
+ (error instanceof Error && error.message === 'email not verified')
84
+ )
85
+ }
37
86
 
38
87
  /** Auth context consumed by Tempo API handlers. */
39
88
  export type Context = {
@@ -95,7 +144,10 @@ export type Payment = {
95
144
  type: 'mpp'
96
145
  }
97
146
 
98
- /** MPP route-policy types. Distinct from the SIWE {@link Session} capability. */
147
+ /** Host-provided request backstop that returns a rejection response when over quota. */
148
+ export type EdgeRateLimit = (request: Request) => Promise<Response | undefined>
149
+
150
+ /** MPP route-policy types. Distinct from the authentication {@link Session} capability. */
99
151
  export declare namespace Mpp {
100
152
  /** MPP Session request options used by route access policies. */
101
153
  type Session = Method.RequestDefaults<ReturnType<typeof tempo.session>> & {
@@ -135,6 +187,8 @@ export type PolicyOverride = {
135
187
  /** API-key lane: pass quota/scopes overrides, or a boolean to enable/disable. */
136
188
  apiKey?:
137
189
  | {
190
+ /** Optional counter bucket that isolates this route's quota. */
191
+ bucket?: string | undefined
138
192
  /** API-key quota override for this route (a protective per-route cap). */
139
193
  rateLimit?: RateLimit.Limit | undefined
140
194
  /** Required API-key scopes override for this route. */
@@ -145,6 +199,8 @@ export type PolicyOverride = {
145
199
  /** MPP paid lane: object to override the Session request, or boolean to enable/disable. */
146
200
  mpp?:
147
201
  | {
202
+ /** Optional counter bucket that isolates this route's quota. */
203
+ bucket?: string | undefined
148
204
  /** Paid-request quota override for this route (a protective per-route cap). */
149
205
  rateLimit?: RateLimit.Limit | undefined
150
206
  /** Tempo Session request override for this route. */
@@ -155,12 +211,14 @@ export type PolicyOverride = {
155
211
  /** Public lane: object to override the quota, or boolean to enable/disable. */
156
212
  public?:
157
213
  | {
214
+ /** Optional counter bucket that isolates this route's quota. */
215
+ bucket?: string | undefined
158
216
  /** Anonymous public quota override for this route. */
159
217
  rateLimit?: RateLimit.Limit | undefined
160
218
  }
161
219
  | boolean
162
220
  | undefined
163
- /** Session lane: `true` allows signed-in wallet sessions, `false` disables. */
221
+ /** Session lane: `true` allows signed-in sessions, `false` disables. */
164
222
  session?: boolean | undefined
165
223
  }
166
224
 
@@ -197,7 +255,7 @@ export type Principal =
197
255
  id: string
198
256
  /** Identity that established the session, as a provider/subject pair (OIDC `iss`/`sub` semantics). */
199
257
  identity: {
200
- /** Identity provider: `wallet` for SIWE sign-in, an OIDC issuer otherwise. */
258
+ /** Identity provider: `email`, `wallet`, or an OIDC issuer. */
201
259
  provider: string
202
260
  /** Provider-scoped subject — the wallet address for `wallet`. */
203
261
  subject: string
@@ -237,6 +295,17 @@ export function getPrincipal<environment extends Environment>(c: hono_Context<en
237
295
  return c.get('principal') ?? null
238
296
  }
239
297
 
298
+ /** Resolves the caller IP from configured trusted metadata. */
299
+ export function getTrustedClientIp<environment extends Environment>(c: hono_Context<environment>) {
300
+ const auth = c.get('auth')
301
+ return auth ? trustedClientIp(c, auth) : resolveTrustedClientIp(c.req.raw, undefined)
302
+ }
303
+
304
+ /** Marks a synthesized in-process request with its trusted caller IP address. */
305
+ export function trustClientIp(request: Request, address: string) {
306
+ trustedClientIps.set(request, address)
307
+ }
308
+
240
309
  /**
241
310
  * Guards `:orgId` routes and resolves the organization. Sessions require membership, API keys require ownership, and the super admin bypasses ownership.
242
311
  */
@@ -504,6 +573,20 @@ export function middleware<
504
573
  endpoint extends string = string,
505
574
  environment extends Environment = Environment,
506
575
  >(options: middleware.Options<endpoint>): MiddlewareHandler<environment> {
576
+ const resolve = createApiKeyResolver({
577
+ apiKey: options.apiKey,
578
+ scopeCatalog: options.scopeCatalog,
579
+ })
580
+ return createAuthMiddleware(options, resolve)
581
+ }
582
+
583
+ function createAuthMiddleware<
584
+ endpoint extends string = string,
585
+ environment extends Environment = Environment,
586
+ >(
587
+ options: middleware.Options<endpoint>,
588
+ resolve: ReturnType<typeof createApiKeyResolver>,
589
+ ): MiddlewareHandler<environment> {
507
590
  const {
508
591
  rateLimit: mppRateLimit = defaultMppRateLimit,
509
592
  session: session_ = {},
@@ -522,23 +605,13 @@ export function middleware<
522
605
  // keyed by token sha256) so hot keys skip the backend read on the auth path
523
606
  // of every request. Pass `apiKey.cache: false` when immediate key updates
524
607
  // matter more than the per-request read.
525
- const resolve = (() => {
526
- const uncached = (c: hono_Context, token: string) => {
527
- const kv = contextKv(c)
528
- return kv
529
- ? ApiKeys.resolve(kv.store, token, { scopeCatalog: options.scopeCatalog })
530
- : Promise.resolve(null)
531
- }
532
- if (options.apiKey === false || options.apiKey?.cache === false) return uncached
533
- return cachedResolve(uncached, options.apiKey?.cache ?? {})
534
- })()
535
608
  const auth: Context = {
536
609
  ...(options.apiKey === false
537
610
  ? {}
538
611
  : {
539
612
  apiKey: {
540
613
  ...(options.apiKey?.rateLimits ? { rateLimits: options.apiKey.rateLimits } : {}),
541
- resolve,
614
+ resolve: resolve.resolve,
542
615
  },
543
616
  }),
544
617
  // The throttle ceiling for sandbox keys without active billing, so
@@ -580,38 +653,125 @@ export function middleware<
580
653
  }
581
654
 
582
655
  return createMiddleware<environment>((c, next) => {
583
- const route = openApiRoute(c)
584
- if (!route) return next()
585
-
586
- const { key, description, management, scope } = route
587
- const overrides = options.overrides as
588
- | Record<string, PolicyOverride | false | undefined>
589
- | undefined
590
- const routePolicies = policies(c)
591
- const configuredOverride = (() => {
592
- const configured = overrides?.[key]
593
- if (configured !== undefined) return configured
594
- const inheritedMethod = routePolicies.find(
595
- (policy) => policy.inheritOverridesFrom,
596
- )?.inheritOverridesFrom
597
- if (inheritedMethod === undefined) return undefined
598
- const inheritedKey = `${inheritedMethod.toUpperCase()} ${key.slice(key.indexOf(' ') + 1)}`
599
- return overrides?.[inheritedKey]
600
- })()
601
- const routeOverride =
602
- management && configuredOverride ? { mpp: configuredOverride.mpp } : configuredOverride
603
- const endpointPolicy = bindMppScope(
604
- resolvePolicy(base, defaults, [...routePolicies, routeOverride], description),
605
- scope,
606
- )
607
- if (!endpointPolicy) return next()
608
- if (management && (!auth.mpp || !endpointPolicy.mpp)) return next()
656
+ const resolved = resolveRequestPolicy(c, { base, defaults, options })
657
+ if (!resolved) return next()
609
658
 
610
659
  c.set('auth', auth)
611
- return require<environment>(endpointPolicy)(c, next)
660
+ if (!resolved.policy) return next()
661
+ if (resolved.management && (!auth.mpp || !resolved.policy.mpp)) return next()
662
+
663
+ return require<environment>(resolved.policy)(c, next)
612
664
  })
613
665
  }
614
666
 
667
+ function resolveRequestPolicy(c: hono_Context, options: resolveRequestPolicy.Options) {
668
+ const route = openApiRoute(c)
669
+ if (!route) return undefined
670
+
671
+ const { key, description, management, scope } = route
672
+ const overrides = options.options.overrides as
673
+ | Record<string, PolicyOverride | false | undefined>
674
+ | undefined
675
+ const routePolicies = policies(c)
676
+ const configuredOverride = (() => {
677
+ const configured = overrides?.[key]
678
+ if (configured !== undefined) return configured
679
+ const inheritedMethod = routePolicies.find(
680
+ (routePolicy): routePolicy is policy.Options =>
681
+ routePolicy !== false && routePolicy.inheritOverridesFrom !== undefined,
682
+ )?.inheritOverridesFrom
683
+ if (inheritedMethod === undefined) return undefined
684
+ const inheritedKey = `${inheritedMethod.toUpperCase()} ${key.slice(key.indexOf(' ') + 1)}`
685
+ return overrides?.[inheritedKey]
686
+ })()
687
+ // Generated management routes already materialize the GET's MPP contract.
688
+ // Reapplying its override would also copy GET-only quota controls.
689
+ const routeOverride = management ? undefined : configuredOverride
690
+ return {
691
+ management,
692
+ policy: bindMppScope(
693
+ resolvePolicy(options.base, options.defaults, [...routePolicies, routeOverride], description),
694
+ scope,
695
+ ),
696
+ }
697
+ }
698
+
699
+ declare namespace resolveRequestPolicy {
700
+ /** Inputs used to resolve the current route's authentication policy. */
701
+ type Options = {
702
+ /** Default-closed base policy. */
703
+ base: require.Policy
704
+ /** Configured lane defaults. */
705
+ defaults: LaneDefaults
706
+ /** Authentication middleware options and route overrides. */
707
+ options: middleware.Options
708
+ }
709
+ }
710
+
711
+ type ApiKeyResolverOptions = {
712
+ /** API-key authentication and cache configuration. */
713
+ apiKey: middleware.Options['apiKey']
714
+ /** Authoritative owner store used to reject orphaned API keys. */
715
+ db?: Db.Source | undefined
716
+ /** Scope catalog accepted while resolving records. */
717
+ scopeCatalog: Scope.Catalog | undefined
718
+ }
719
+
720
+ type RequestApiKeyResolution = {
721
+ /** Resolved API key, or null when the token is invalid. */
722
+ apiKey: ApiKey.ApiKey | null
723
+ /** Hash of the presented token associated with the resolution. */
724
+ tokenHash: string
725
+ }
726
+
727
+ function createApiKeyResolver(options: ApiKeyResolverOptions) {
728
+ const requests = new WeakMap<hono_Context, RequestApiKeyResolution>()
729
+ const uncached = (c: hono_Context, token: string) => {
730
+ const kv = contextKv(c)
731
+ return kv
732
+ ? ApiKeys.resolve(kv.store, token, { scopeCatalog: options.scopeCatalog })
733
+ : Promise.resolve(null)
734
+ }
735
+ const cache =
736
+ options.apiKey === false || options.apiKey?.cache === false
737
+ ? { invalidate: () => {}, peek: () => undefined, resolve: uncached }
738
+ : cachedResolve(uncached, options.apiKey?.cache ?? {})
739
+
740
+ return {
741
+ peek: (c: hono_Context, token: string) => {
742
+ const tokenHash = ApiKey.hash(token)
743
+ const existing = requests.get(c)
744
+ if (existing?.tokenHash === tokenHash) return existing.apiKey
745
+ return cache.peek(token)
746
+ },
747
+ resolve: async (c: hono_Context, token: string) => {
748
+ const tokenHash = ApiKey.hash(token)
749
+ const existing = requests.get(c)
750
+ if (existing?.tokenHash === tokenHash) return existing.apiKey
751
+ const cached = await cache.resolve(c, token)
752
+ const kv = contextKv(c)
753
+ const apiKey =
754
+ cached &&
755
+ ((kv && (await ApiKeys.isOwnerDeleted(kv.store, cached))) ||
756
+ !(await apiKeyOwnerExists(cached, options.db)))
757
+ ? null
758
+ : cached
759
+ if (cached && !apiKey) cache.invalidate(token)
760
+ requests.set(c, { apiKey, tokenHash })
761
+ return apiKey
762
+ },
763
+ }
764
+ }
765
+
766
+ /** Rejects attributed keys fenced by a committed owner deletion. */
767
+ async function apiKeyOwnerExists(apiKey: ApiKey.ApiKey, source: Db.Source | undefined) {
768
+ if (!source) return true
769
+ const db = Db.get(source)
770
+ if (!(await ApiKeyAdmissions.matches(db, apiKey))) return false
771
+ if (await ApiKeyOwnerTombstones.isDeleted(db, apiKey)) return false
772
+ return true
773
+ }
774
+
615
775
  export declare namespace middleware {
616
776
  /** Per-route policy overrides keyed by HTTP endpoint. */
617
777
  type Overrides<endpoint extends string = string> = Partial<
@@ -689,7 +849,7 @@ export declare namespace middleware {
689
849
  }
690
850
  }
691
851
 
692
- /** Zod schemas documenting the session sign-in surface (`/v1/auth/siwe`). */
852
+ /** Zod schemas documenting the session sign-in surface. */
693
853
  namespace schema {
694
854
  const siweMessage =
695
855
  'api.tempo.xyz wants you to sign in with your Ethereum account:\n0x0000000000000000000000000000000000000000\n\nURI: https://api.tempo.xyz\nVersion: 1\nChain ID: 0\nNonce: 3D0sZfnHqTBmc9tKR\nIssued At: 2026-01-01T00:00:00.000Z\nExpiration Time: 2026-01-01T00:10:00.000Z'
@@ -710,64 +870,92 @@ namespace schema {
710
870
  /** Schemas for `POST /v1/auth/siwe/challenge`. */
711
871
  export namespace challenge {
712
872
  /** Request body. Accepted fields beyond this document pass through to the SDK handler. */
713
- export const Body = z.object({})
873
+ export const Body = OpenApi.component(z.object({}), 'SiweChallengeRequest')
714
874
 
715
875
  /** Response body. */
716
- export const Response = z.object({
717
- message: z
718
- .string()
719
- .check(
720
- z.describe('Single-use EIP-4361 (SIWE) message to sign and submit for verification.'),
721
- z.meta({ examples: [siweMessage] }),
722
- ),
723
- })
876
+ export const Response = OpenApi.component(
877
+ z.object({
878
+ message: z
879
+ .string()
880
+ .check(
881
+ z.describe('Single-use EIP-4361 (SIWE) message to sign and submit for verification.'),
882
+ z.meta({ examples: [siweMessage] }),
883
+ ),
884
+ }),
885
+ 'SiweChallengeResponse',
886
+ )
724
887
  }
725
888
 
726
889
  /** Schemas for `POST /v1/auth/siwe` (verify). */
727
890
  export namespace verify {
728
891
  /** Request body. */
729
- export const Body = z.object({
730
- address: z
731
- .string()
732
- .check(
733
- z.describe('Wallet address that signed the message; becomes the session subject.'),
734
- z.meta({ examples: ['0x0000000000000000000000000000000000000001'] }),
892
+ export const Body = OpenApi.component(
893
+ z.object({
894
+ address: z
895
+ .string()
896
+ .check(
897
+ z.describe('Wallet address that signed the message; becomes the session subject.'),
898
+ z.meta({ examples: ['0x0000000000000000000000000000000000000001'] }),
899
+ ),
900
+ idToken: z.optional(z.string()).check(
901
+ z.describe('Wallet-minted OIDC identity token (JWT) asserting a verified email, folded onto the session.'), // prettier-ignore
902
+ z.meta({ examples: ['eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIweDAwMDAifQ.c2lnbmF0dXJl'] }),
735
903
  ),
736
- idToken: z.optional(z.string()).check(
737
- z.describe('Wallet-minted OIDC identity token (JWT) asserting a verified email, folded onto the session.'), // prettier-ignore
738
- z.meta({ examples: ['eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIweDAwMDAifQ.c2lnbmF0dXJl'] }),
739
- ),
740
- keyAuthorization: z.optional(z.string()).check(
741
- z.describe('RLP-serialized signed key authorization (TIP-1053) whose witness binds this message; verification recovers over its digest.'), // prettier-ignore
742
- z.meta({ examples: [`0x${'aa'.repeat(60)}`] }),
743
- ),
744
- message: z
745
- .string()
746
- .check(
747
- z.describe('The exact challenge message issued by `POST /v1/auth/siwe/challenge`.'),
748
- z.meta({ examples: [siweMessage] }),
904
+ keyAuthorization: z.optional(z.string()).check(
905
+ z.describe('RLP-serialized signed key authorization (TIP-1053) whose witness binds this message; verification recovers over its digest.'), // prettier-ignore
906
+ z.meta({ examples: [`0x${'aa'.repeat(60)}`] }),
749
907
  ),
750
- returnToken: z.optional(z.boolean()).check(
751
- z.describe('Return the session token in the body instead of setting the session cookie.'), // prettier-ignore
752
- z.meta({ examples: [true] }),
753
- ),
754
- signature: z
755
- .string()
756
- .check(
757
- z.describe('Signature over the challenge message (or the key-authorization digest).'),
758
- z.meta({ examples: [`0x${'aa'.repeat(65)}`] }),
908
+ message: z
909
+ .string()
910
+ .check(
911
+ z.describe('The exact challenge message issued by `POST /v1/auth/siwe/challenge`.'),
912
+ z.meta({ examples: [siweMessage] }),
913
+ ),
914
+ returnToken: z.optional(z.boolean()).check(
915
+ z.describe('Return the session token in the body instead of setting the session cookie.'), // prettier-ignore
916
+ z.meta({ examples: [true] }),
759
917
  ),
760
- })
918
+ signature: z
919
+ .string()
920
+ .check(
921
+ z.describe('Signature over the challenge message (or the key-authorization digest).'),
922
+ z.meta({ examples: [`0x${'aa'.repeat(65)}`] }),
923
+ ),
924
+ }),
925
+ 'SiweVerifyRequest',
926
+ )
761
927
 
762
928
  /** Response body. */
763
- export const Response = z.object({
764
- token: z
765
- .optional(z.string())
766
- .check(
767
- z.describe('Bearer session token; present only when `returnToken` is true.'),
768
- z.meta({ examples: ['aa'.repeat(32)] }),
769
- ),
770
- })
929
+ export const Response = OpenApi.component(
930
+ z.object({
931
+ token: z
932
+ .optional(z.string())
933
+ .check(
934
+ z.describe('Bearer session token; present only when `returnToken` is true.'),
935
+ z.meta({ examples: ['aa'.repeat(32)] }),
936
+ ),
937
+ }),
938
+ 'SiweVerifyResponse',
939
+ )
940
+ }
941
+
942
+ /** Schemas for `POST /v1/auth/identity`. */
943
+ export namespace identity {
944
+ /** Request body. */
945
+ export const Body = OpenApi.component(
946
+ z.object({
947
+ idToken: z
948
+ .string()
949
+ .check(
950
+ z.describe('Wallet-issued OpenID Connect identity token.'),
951
+ z.meta({ examples: ['eyJhbGciOiJFZERTQSJ9.eyJzdWIiOiIweDAwMDAifQ.c2lnbmF0dXJl'] }),
952
+ ),
953
+ }),
954
+ 'IdentitySignInRequest',
955
+ )
956
+
957
+ /** Response body. */
958
+ export const Response = OpenApi.component(z.object({}), 'IdentitySignInResponse')
771
959
  }
772
960
  }
773
961
 
@@ -787,19 +975,39 @@ function handlerError(description: string) {
787
975
  */
788
976
  export function install(options: install.Options) {
789
977
  const { db, kv, scopeCatalog } = options
790
- const { session: options_session, ...options_middleware } =
791
- options.auth === false ? {} : (options.auth ?? {})
978
+ const {
979
+ edgeRateLimit: options_edgeRateLimit,
980
+ session: options_session,
981
+ ...options_middleware
982
+ } = options.auth === false ? {} : (options.auth ?? {})
983
+ const publicClientIp =
984
+ typeof options_middleware.public === 'object' ? options_middleware.public.clientIp : undefined
792
985
  if (options_session && !kv)
793
986
  throw new Error('`auth.session` requires the `kv` state store: sessions and sign-in challenges persist there.') // prettier-ignore
987
+ const options_betterAuth = options_session
988
+ ? {
989
+ basePath: Path.join(options.basePath, 'v1/auth'),
990
+ clientIp: (request: Request) => resolveTrustedClientIp(request, publicClientIp),
991
+ db,
992
+ get email() {
993
+ return options.email()
994
+ },
995
+ rateLimit: RateLimit.memory(options_middleware.rateLimit),
996
+ secret: options_session.secret,
997
+ ...(options_session.google ? { google: options_session.google } : {}),
998
+ ...(options_session.trustedOrigins
999
+ ? { trustedOrigins: options_session.trustedOrigins }
1000
+ : {}),
1001
+ }
1002
+ : undefined
794
1003
 
795
1004
  // Session sign-in surface (challenge, verify, logout — SIWE wallet sign-in
796
1005
  // today) plus the capability the session lane resolves through. Public but
797
1006
  // policy-gated: the hidden describeRoute engages the middleware for the
798
1007
  // mounted sub-app, and the public lane rate-limits challenge-store writes.
799
1008
  const app = (() => {
800
- if (!options_session || !kv) return undefined
801
- const { issuer, origin, requireEmail, ttl } =
802
- (typeof options_session === 'object' ? options_session.wallet : undefined) ?? {}
1009
+ if (!options_betterAuth || !options_session || !kv) return undefined
1010
+ const { issuer, origin, requireEmail, ttl } = options_session.wallet ?? {}
803
1011
 
804
1012
  const handler = Accounts.Handler.auth({
805
1013
  getClient: options.getClient,
@@ -839,30 +1047,105 @@ export function install(options: install.Options) {
839
1047
  },
840
1048
  ...(ttl ? { ttl } : {}),
841
1049
  })
1050
+ const identity = options_session.identity
1051
+ const identitySessionTtl = identity?.ttl ?? defaultIdentitySessionTtl
1052
+ const identitySessionKey = (token: string) => `identity:session:${token}`
1053
+
1054
+ async function resolveWallet(payload: WalletSession) {
1055
+ const database = Db.get(db)
1056
+ const verifiedEmail = payload.email?.trim().toLowerCase()
1057
+ return database.kysely.transaction().execute(async (kysely) => {
1058
+ const tx = { ...database, kysely }
1059
+ // Organization creation locks the same address row before resolving
1060
+ // the wallet owner, serializing resource writes with reconciliation.
1061
+ const addressUser = await Users.getByAddressForUpdate(tx, payload.address)
1062
+ if (!addressUser) return null
1063
+ if (verifiedEmail)
1064
+ await sql`SELECT pg_advisory_xact_lock(hashtextextended(${verifiedEmail}, 0))`.execute(
1065
+ kysely,
1066
+ )
1067
+ const linkedUserId = await AuthAccounts.getWalletUserId(tx, payload.address)
1068
+ const linkedUser = linkedUserId ? await Users.get(tx, linkedUserId) : undefined
1069
+ const emailUser = verifiedEmail ? await Users.getByEmail(tx, verifiedEmail) : undefined
1070
+ const walletUser = linkedUser ?? addressUser
1071
+ const walletHasResources =
1072
+ emailUser && walletUser.id !== emailUser.id
1073
+ ? await Memberships.existsForUser(tx, walletUser.id)
1074
+ : false
1075
+ // A verified email reconciles a provisional email-less wallet link.
1076
+ // Keep a provisional owner when changing it would orphan its access.
1077
+ const user = walletHasResources ? walletUser : (emailUser ?? walletUser)
1078
+ if (linkedUser?.id !== user.id)
1079
+ await AuthAccounts.setWalletUser(tx, { address: payload.address, userId: user.id })
1080
+ if (verifiedEmail && (user.email !== verifiedEmail || !user.emailVerified))
1081
+ await Users.setEmail(tx, user.id, verifiedEmail)
1082
+ return { email: verifiedEmail ?? user.email ?? undefined, user }
1083
+ })
1084
+ }
842
1085
 
843
1086
  const session: Session = {
844
1087
  resolve: async (c) => {
845
- const payload = await handler.getSession(c.req.raw)
846
- if (!payload) return null
847
- const database = Db.get(db)
848
- const user = await Users.getByAddress(database, payload.address)
849
- if (!user) return null
850
- // Fold a newly verified email onto the user row: identity tokens are
851
- // optional per sign-in, so the column fills lazily.
852
- if (payload.email && user.email !== payload.email)
853
- await Users.setEmail(database, user.id, payload.email)
854
- const email = payload.email ?? user.email ?? undefined
855
- return {
856
- ...(email ? { email } : {}),
857
- id: user.id,
858
- identity: { provider: 'wallet', subject: payload.address },
859
- type: 'session',
860
- }
1088
+ const [betterAuth, identitySession, wallet] = await Promise.all([
1089
+ (async () => {
1090
+ const auth = BetterAuth.fromContext(c, options_betterAuth)
1091
+ const request = BetterAuth.request(c, options_betterAuth)
1092
+ const result = await auth.api.getSession({ headers: request.headers })
1093
+ if (!result) return null
1094
+ const provider =
1095
+ 'provider' in result.session && typeof result.session.provider === 'string'
1096
+ ? result.session.provider
1097
+ : undefined
1098
+ if (
1099
+ !provider ||
1100
+ !result.user.email ||
1101
+ (provider === 'email' && !options_betterAuth.email)
1102
+ )
1103
+ return null
1104
+ return {
1105
+ email: result.user.email,
1106
+ id: result.user.id,
1107
+ identity: { provider, subject: result.user.email },
1108
+ type: 'session',
1109
+ } satisfies SessionPrincipal
1110
+ })(),
1111
+ (async () => {
1112
+ if (!identity) return null
1113
+ const token = getCookie(c, identityCookieName)
1114
+ if (!token) return null
1115
+ const value = await kv.store.get(identitySessionKey(token))
1116
+ if (value === null) return null
1117
+ const payload = JSON.parse(value) as IdentitySession
1118
+ if (payload.expiresAt <= Math.floor(Date.now() / 1_000)) return null
1119
+ const user = await resolveWallet(payload)
1120
+ if (!user) return null
1121
+ return {
1122
+ ...(user.email ? { email: user.email } : {}),
1123
+ id: user.user.id,
1124
+ identity: { provider: 'wallet', subject: payload.address },
1125
+ type: 'session',
1126
+ } satisfies SessionPrincipal
1127
+ })(),
1128
+ (async () => {
1129
+ const payload = await handler.getSession(c.req.raw)
1130
+ if (!payload) return null
1131
+ const user = await resolveWallet(payload)
1132
+ if (!user) return null
1133
+ return {
1134
+ ...(user.email ? { email: user.email } : {}),
1135
+ id: user.user.id,
1136
+ identity: { provider: 'wallet', subject: payload.address },
1137
+ type: 'session',
1138
+ } satisfies SessionPrincipal
1139
+ })(),
1140
+ ])
1141
+ if (betterAuth && identitySession && betterAuth.id !== identitySession.id) return null
1142
+ if (betterAuth && wallet && betterAuth.id !== wallet.id) return null
1143
+ if (identitySession && wallet && identitySession.id !== wallet.id) return null
1144
+ return betterAuth ?? identitySession ?? wallet
861
1145
  },
862
1146
  }
863
1147
 
864
1148
  const policy_public = policy({ public: true })
865
- const policy_session = policy({ public: true, session: true })
866
1149
  const describe = OpenApi.describeRoute({ hide: true })
867
1150
 
868
1151
  const app = new Hono<App.Environment>()
@@ -874,10 +1157,8 @@ export function install(options: install.Options) {
874
1157
  app.post(
875
1158
  '/v1/auth/siwe/challenge',
876
1159
  policy_public,
877
- OpenApi.validate('json', schema.challenge.Body, {
878
- code: 'body_invalid',
879
- message: 'Invalid request body',
880
- }),
1160
+ OpenApi.documentJsonRequest(schema.challenge.Body),
1161
+ validateJsonRequest(schema.challenge.Body),
881
1162
  OpenApi.describeRoute({
882
1163
  description:
883
1164
  'Issues a single-use SIWE challenge message to sign. The challenge expires after a short TTL.',
@@ -901,10 +1182,8 @@ export function install(options: install.Options) {
901
1182
  app.post(
902
1183
  '/v1/auth/siwe',
903
1184
  policy_public,
904
- OpenApi.validate('json', schema.verify.Body, {
905
- code: 'body_invalid',
906
- message: 'Invalid request body',
907
- }),
1185
+ OpenApi.documentJsonRequest(schema.verify.Body),
1186
+ validateJsonRequest(schema.verify.Body),
908
1187
  OpenApi.describeRoute({
909
1188
  description:
910
1189
  'Verifies the signed challenge and establishes a session. Sets a session cookie by default; pass `returnToken` to receive a bearer token instead.',
@@ -933,42 +1212,270 @@ export function install(options: install.Options) {
933
1212
  tags: ['Authentication'],
934
1213
  }),
935
1214
  )
1215
+ if (identity)
1216
+ app.post(
1217
+ '/v1/auth/identity',
1218
+ policy_public,
1219
+ OpenApi.documentJsonRequest(schema.identity.Body),
1220
+ validateJsonRequest(schema.identity.Body),
1221
+ OpenApi.describeRoute({
1222
+ description:
1223
+ 'Verifies a Wallet-issued OpenID Connect identity token and establishes a session.',
1224
+ hide: false,
1225
+ operationId: 'verifyIdentity',
1226
+ responses: {
1227
+ 200: {
1228
+ content: {
1229
+ 'application/json': { schema: OpenApi.resolver(schema.identity.Response) },
1230
+ },
1231
+ description: 'Session established.',
1232
+ headers: {
1233
+ ...OpenApi.successHeaders,
1234
+ 'Set-Cookie': {
1235
+ description: `Session cookie (${identityCookieName}).`,
1236
+ schema: { type: 'string' },
1237
+ },
1238
+ },
1239
+ },
1240
+ 400: OpenApi.standardError(400, 'Malformed request body.', ['body_invalid']),
1241
+ 401: OpenApi.standardError(401, 'Identity verification failed.', ['identity_invalid']),
1242
+ 429: OpenApi.standardError(429, 'Rate limited.'),
1243
+ 500: OpenApi.standardError(500, 'Internal server error.'),
1244
+ },
1245
+ summary: 'Authenticate identity',
1246
+ tags: ['Authentication'],
1247
+ }),
1248
+ async (c) => {
1249
+ const { idToken } = schema.identity.Body.parse(await c.req.json())
1250
+ const claims = await Accounts.Identity.verify(idToken, {
1251
+ audience: identity.audience,
1252
+ issuer: identity.issuer ?? walletIdentityIssuer,
1253
+ }).catch((error) => {
1254
+ // Issuer and network failures must reach the request error signal.
1255
+ if (isIdentityTokenError(error)) return undefined
1256
+ throw error
1257
+ })
1258
+ if (!claims || !Address.validate(claims.subject, { strict: false }))
1259
+ return Response.error(c, {
1260
+ code: 'identity_invalid',
1261
+ message: 'Invalid identity token',
1262
+ status: 401,
1263
+ })
1264
+
1265
+ const address = Address.checksum(claims.subject)
1266
+ await Users.upsertByAddress(Db.get(db), { address })
1267
+ const issuedAt = Math.floor(Date.now() / 1_000)
1268
+ const token = Hex.fromBytes(crypto.getRandomValues(new Uint8Array(32))).slice(2)
1269
+ await kv.store.put(
1270
+ identitySessionKey(token),
1271
+ JSON.stringify({
1272
+ address,
1273
+ ...(claims.email ? { email: claims.email } : {}),
1274
+ expiresAt: issuedAt + identitySessionTtl,
1275
+ issuedAt,
1276
+ } satisfies IdentitySession),
1277
+ { ttl: identitySessionTtl * 1_000 },
1278
+ )
1279
+ setCookie(c, identityCookieName, token, {
1280
+ httpOnly: true,
1281
+ maxAge: identitySessionTtl,
1282
+ path: '/',
1283
+ sameSite: 'Lax',
1284
+ secure: new URL(c.req.url).protocol === 'https:',
1285
+ })
1286
+ return c.json({}, 200)
1287
+ },
1288
+ )
936
1289
  app.post(
937
- '/v1/auth/siwe/logout',
938
- policy_session,
1290
+ '/v1/auth/logout',
1291
+ policy(false),
1292
+ createMiddleware<App.Environment>(async (c, next) => {
1293
+ const auth = c.get('auth')
1294
+ const principal = principalFromPublic(c, auth)
1295
+ const result = await consumeRateLimit(auth, {
1296
+ key: `public:${principal.id}`,
1297
+ limit: auth.publicRateLimit ?? defaultPublicRateLimit,
1298
+ })
1299
+ if (result) {
1300
+ setRateLimitHeaders(c, result)
1301
+ if (!result.allowed) return rateLimitExceeded(c, result)
1302
+ }
1303
+ c.set('principal', principal)
1304
+ await next()
1305
+ return undefined
1306
+ }),
939
1307
  OpenApi.describeRoute({
940
- description: 'Revokes the current session and clears the session cookie.',
1308
+ description: 'Revokes auth sessions and clears their cookies.',
941
1309
  hide: false,
942
- operationId: 'siweLogout',
1310
+ operationId: 'logout',
943
1311
  responses: {
944
- 204: { description: 'Session revoked and cookie cleared.' },
1312
+ 204: { description: 'Sessions revoked and cookies cleared.' },
945
1313
  429: OpenApi.standardError(429, 'Rate limited.'),
946
- 500: OpenApi.standardError(500, 'Internal server error.'),
1314
+ 500: OpenApi.standardError(500, 'Session logout failed.', ['session_logout_failed']),
947
1315
  },
948
1316
  summary: 'Sign out',
949
1317
  tags: ['Authentication'],
950
1318
  }),
1319
+ async (c) => {
1320
+ const walletHeaders = (() => {
1321
+ const authorization = c.req.header('authorization')
1322
+ const cookie = c.req.header('cookie')
1323
+ if (!authorization?.match(/^Bearer\s+.+$/i) || !cookie?.match(/(?:^|;\s*)accounts_auth=/))
1324
+ return [c.req.raw.headers]
1325
+ const bearer = new Headers(c.req.raw.headers)
1326
+ bearer.delete('cookie')
1327
+ const cookie_ = new Headers(c.req.raw.headers)
1328
+ cookie_.delete('authorization')
1329
+ return [bearer, cookie_]
1330
+ })()
1331
+ const [betterAuth, identityLogout, ...accounts] = await Promise.allSettled([
1332
+ BetterAuth.fromContext(c, options_betterAuth).api.signOut({
1333
+ headers: c.req.raw.headers,
1334
+ returnHeaders: true,
1335
+ }),
1336
+ (async () => {
1337
+ const token = getCookie(c, identityCookieName)
1338
+ deleteCookie(c, identityCookieName, { path: '/' })
1339
+ if (token) await kv.store.delete(identitySessionKey(token))
1340
+ })(),
1341
+ ...walletHeaders.map((headers) =>
1342
+ handler.request(
1343
+ new Request(new URL('/logout', c.req.url), {
1344
+ headers,
1345
+ method: 'POST',
1346
+ }),
1347
+ ),
1348
+ ),
1349
+ ])
1350
+
1351
+ if (betterAuth.status === 'fulfilled')
1352
+ for (const cookie of splitSetCookieHeader(
1353
+ betterAuth.value.headers.get('Set-Cookie') ?? '',
1354
+ ))
1355
+ c.header('Set-Cookie', cookie, { append: true })
1356
+ for (const result of accounts)
1357
+ if (result.status === 'fulfilled')
1358
+ for (const cookie of splitSetCookieHeader(result.value.headers.get('Set-Cookie') ?? ''))
1359
+ c.header('Set-Cookie', cookie, { append: true })
1360
+
1361
+ const error = (() => {
1362
+ const rejected = [betterAuth, identityLogout, ...accounts].find(
1363
+ (result) => result.status === 'rejected',
1364
+ )
1365
+ if (rejected?.status === 'rejected')
1366
+ return rejected.reason instanceof Error
1367
+ ? rejected.reason
1368
+ : new Error('Session logout failed', { cause: rejected.reason })
1369
+ const failed = accounts.find(
1370
+ (result) => result.status === 'fulfilled' && !result.value.ok,
1371
+ )
1372
+ if (failed?.status === 'fulfilled')
1373
+ return new Error(`Accounts session logout failed with status ${failed.value.status}`)
1374
+ return undefined
1375
+ })()
1376
+ if (error) {
1377
+ c.error = error
1378
+ return Response.error(c, {
1379
+ code: 'session_logout_failed',
1380
+ message: 'Session logout failed',
1381
+ status: 500,
1382
+ })
1383
+ }
1384
+ return c.body(null, 204)
1385
+ },
951
1386
  )
1387
+ app.route('/v1/auth/siwe', handler)
1388
+ app.on(['GET', 'POST'], '/v1/auth/*', policy_public, describe, async (c, next) => {
1389
+ if (
1390
+ c.req.method === 'POST' &&
1391
+ stripBasePath(c.req.path, basePath(c)) === '/v1/auth/email-otp/send-verification-otp'
1392
+ ) {
1393
+ const body: unknown = await c.req.raw
1394
+ .clone()
1395
+ .json()
1396
+ .catch(() => undefined)
1397
+ if (body && typeof body === 'object' && 'type' in body && body.type !== 'sign-in')
1398
+ return Response.error(c, {
1399
+ code: 'body_invalid',
1400
+ message: 'Only sign-in OTPs are supported',
1401
+ status: 400,
1402
+ })
1403
+ }
1404
+ const response = await BetterAuth.fromContext(c, options_betterAuth).handler(
1405
+ BetterAuth.request(c, options_betterAuth),
1406
+ )
1407
+ // Leave unmatched paths available to auth providers mounted by the host app.
1408
+ return response.status === 404 ? next() : response
1409
+ })
952
1410
  return Object.assign(
953
1411
  // The tag joins the `Management API` group at `management()`'s chosen slot;
954
1412
  // group listings filter to defined tags, so it drops out when unmounted.
955
- Metadata.attach(app.route('/v1/auth/siwe', handler), {
1413
+ Metadata.attach(app, {
1414
+ securitySchemes: {
1415
+ session: {
1416
+ description: 'Session cookie established by email OTP, Wallet identity, or SIWE sign-in. Browsers send `tempo_auth.session_token`, `tempo_identity`, or `accounts_auth`; Accounts sessions may also use `Authorization: Bearer <token>`.', // prettier-ignore
1417
+ in: 'header',
1418
+ name: 'Cookie',
1419
+ type: 'apiKey',
1420
+ },
1421
+ },
956
1422
  tags: [{ name: 'Authentication', description: 'Authenticate into the Tempo Platform.' }],
957
1423
  }),
958
1424
  { session },
959
1425
  )
960
1426
  })()
961
1427
 
1428
+ const resolve = createApiKeyResolver({
1429
+ apiKey: options_middleware.apiKey,
1430
+ db: options.db,
1431
+ scopeCatalog,
1432
+ })
1433
+ const defaults = laneDefaults(options_middleware)
1434
+ const base: require.Policy = {}
1435
+ const edgeRateLimit = (() => {
1436
+ if (options.auth === false || !options_edgeRateLimit) return undefined
1437
+ const superAdminTokenHash = options_middleware.superAdmin?.secret
1438
+ ? ApiKey.hash(options_middleware.superAdmin.secret)
1439
+ : undefined
1440
+
1441
+ return createMiddleware(async (c, next) => {
1442
+ const credential = getApiKeyCredential(c)
1443
+ const resolved = resolveRequestPolicy(c, { base, defaults, options: options_middleware })
1444
+ const isSuperAdmin =
1445
+ credential &&
1446
+ superAdminTokenHash !== undefined &&
1447
+ ApiKey.hash(credential.token) === superAdminTokenHash
1448
+ const canUseApiKeyQuota =
1449
+ credential &&
1450
+ !isSuperAdmin &&
1451
+ !hasPaymentCredential(c) &&
1452
+ options_middleware.apiKey !== false &&
1453
+ resolved?.policy?.apiKey &&
1454
+ (!resolved.management || (options_middleware.mpp !== false && resolved.policy.mpp))
1455
+ const cached = canUseApiKeyQuota ? resolve.peek(c, credential.token) : undefined
1456
+ if (cached) return next()
1457
+
1458
+ const response = await Timing.time(c, 'edge_rate_limit', () =>
1459
+ options_edgeRateLimit(c.req.raw),
1460
+ )
1461
+ if (response) return response
1462
+ if (canUseApiKeyQuota && cached === undefined) await resolve.resolve(c, credential.token)
1463
+ return next()
1464
+ })
1465
+ })()
962
1466
  const middleware_ =
963
1467
  options.auth === false
964
1468
  ? undefined
965
- : middleware({
966
- ...options_middleware,
967
- ...(app ? { session: app.session } : {}),
968
- scopeCatalog,
969
- })
1469
+ : createAuthMiddleware(
1470
+ {
1471
+ ...options_middleware,
1472
+ ...(app ? { session: app.session } : {}),
1473
+ scopeCatalog,
1474
+ },
1475
+ resolve,
1476
+ )
970
1477
 
971
- return { app, middleware: middleware_ }
1478
+ return { app, edgeRateLimit, middleware: middleware_ }
972
1479
  }
973
1480
 
974
1481
  export declare namespace install {
@@ -976,13 +1483,19 @@ export declare namespace install {
976
1483
  type Options = {
977
1484
  auth:
978
1485
  | (Omit<middleware.Options, 'scopeCatalog' | 'session'> & {
979
- /** Session sign-in surface: mounts `/v1/auth/siwe` (challenge/verify/logout) and enables the session lane. Pass true for defaults or a config object. Requires `kv`. */
1486
+ /** Request backstop skipped for cached API keys on routes with per-key quotas. */
1487
+ edgeRateLimit?: EdgeRateLimit | undefined
1488
+ /** Session sign-in surface: mounts Better Auth, Wallet identity, and SIWE routes and enables the session lane. Requires `kv`. */
980
1489
  session?: Session | undefined
981
1490
  })
982
1491
  | false
983
1492
  | undefined
1493
+ /** Normalized path prefix that contains the auth surface. */
1494
+ basePath: string
984
1495
  /** Authoritative database holding user rows. */
985
1496
  db: Db.Source
1497
+ /** Resolves the transactional email sender shared by authentication and route groups. */
1498
+ email: () => Email.Sender | undefined
986
1499
  /** Resolves the configured Tempo RPC client used for SIWE signature verification. */
987
1500
  getClient: (chainId: number) => Viem.getClient.ReturnType
988
1501
  /** KV state store, or undefined when key auth is closed. */
@@ -991,13 +1504,36 @@ export declare namespace install {
991
1504
  scopeCatalog: Scope.Catalog
992
1505
  }
993
1506
 
994
- /** Session sign-in surface configuration: `true` for defaults, or a config object. */
995
- type Session =
996
- | boolean
997
- | {
998
- /** SIWE wallet sign-in configuration. */
999
- wallet?: Wallet | undefined
1000
- }
1507
+ /** Session sign-in surface configuration. */
1508
+ type Session = {
1509
+ /** Google OpenID Connect configuration. */
1510
+ google?:
1511
+ | {
1512
+ /** OAuth client identifier. */
1513
+ clientId: string
1514
+ /** OAuth client secret. */
1515
+ clientSecret: string
1516
+ }
1517
+ | undefined
1518
+ /** Wallet-issued OpenID Connect identity sign-in configuration. */
1519
+ identity?: Identity | undefined
1520
+ /** High-entropy secret used to protect Better Auth credentials. */
1521
+ secret: string
1522
+ /** Additional browser origins accepted by Better Auth. */
1523
+ trustedOrigins?: readonly string[] | undefined
1524
+ /** SIWE wallet sign-in configuration. */
1525
+ wallet?: Wallet | undefined
1526
+ }
1527
+
1528
+ /** Wallet-issued OpenID Connect identity sign-in configuration. */
1529
+ type Identity = {
1530
+ /** Expected token audience, usually the Console origin. */
1531
+ audience: string
1532
+ /** Identity issuer override; defaults to Tempo Wallet. */
1533
+ issuer?: string | undefined
1534
+ /** Session lifetime in seconds. Defaults to 24 hours. */
1535
+ ttl?: number | undefined
1536
+ }
1001
1537
 
1002
1538
  /** SIWE wallet sign-in configuration. */
1003
1539
  type Wallet = {
@@ -1005,15 +1541,44 @@ export declare namespace install {
1005
1541
  issuer?: string | undefined
1006
1542
  /** Pinned absolute origin for SIWE domain binding. Required off-Workers; on Workers the edge proxy headers are trusted by default. */
1007
1543
  origin?: string | undefined
1008
- /** Reject sign-ins that carry no valid identity token, so every session holds a verified email. */
1544
+ /** Reject sign-ins without a valid identity token. Defaults to false. */
1009
1545
  requireEmail?: boolean | undefined
1010
1546
  /** Session and challenge TTL overrides, in seconds. */
1011
1547
  ttl?: { challenge?: number | undefined; session?: number | undefined } | undefined
1012
1548
  }
1013
1549
  }
1014
1550
 
1015
- /** Creates route middleware that contributes an auth policy override. */
1016
- export function policy(options: policy.Options): MiddlewareHandler {
1551
+ function validateJsonRequest<const schema extends z.ZodMiniType>(
1552
+ schema: schema,
1553
+ ): MiddlewareHandler {
1554
+ return async (c, next) => {
1555
+ if (!c.req.header('content-type')?.toLowerCase().startsWith('application/json'))
1556
+ return Response.error(c, {
1557
+ code: 'body_invalid',
1558
+ message: 'Invalid request body',
1559
+ status: 400,
1560
+ })
1561
+ const value = await (async () => {
1562
+ try {
1563
+ return await c.req.raw.clone().json()
1564
+ } catch {
1565
+ return undefined
1566
+ }
1567
+ })()
1568
+ const result = schema.safeParse(value)
1569
+ if (!result.success)
1570
+ return Response.error(c, {
1571
+ code: 'body_invalid',
1572
+ details: Response.validationDetails(result.error.issues),
1573
+ message: 'Invalid request body',
1574
+ status: 400,
1575
+ })
1576
+ return next()
1577
+ }
1578
+ }
1579
+
1580
+ /** Creates route middleware that contributes an auth policy override, or bypasses auth when passed `false`. */
1581
+ export function policy(options: policy.Options | false): MiddlewareHandler {
1017
1582
  const middleware = createMiddleware((_, next) => next()) as MiddlewareHandler & PolicyHandler
1018
1583
  middleware[policySymbol] = options
1019
1584
  return middleware
@@ -1042,7 +1607,7 @@ export function installMppManagementRoutes(
1042
1607
  if (route.method !== 'GET') continue
1043
1608
  const target = targets.get(route.path) ?? { path: route.path }
1044
1609
  const override = policyFromRoute(route)
1045
- if (override?.mpp !== undefined)
1610
+ if (override && override.mpp !== undefined)
1046
1611
  target.mpp = resolveMppLane(target.mpp, override.mpp, { session: {} })
1047
1612
 
1048
1613
  const spec = openApiSpec(route) as MppManagementSpec | undefined
@@ -1066,7 +1631,9 @@ export function installMppManagementRoutes(
1066
1631
  if (postPaths.has(target.path))
1067
1632
  throw new Error(`MPP management POST conflicts with an existing route: ${target.path}`)
1068
1633
 
1069
- const management = policy({ mpp }) as MiddlewareHandler & MppManagementHandler
1634
+ const management = policy({
1635
+ mpp: { session: mpp.session },
1636
+ }) as MiddlewareHandler & MppManagementHandler
1070
1637
  management[mppManagementSymbol] = { description: target.description }
1071
1638
  app.post(
1072
1639
  stripBasePath(target.path, options.basePath),
@@ -1127,7 +1694,7 @@ type OpenApiRoute = {
1127
1694
  }
1128
1695
 
1129
1696
  type PolicyHandler = {
1130
- [policySymbol]?: policy.Options | undefined
1697
+ [policySymbol]?: policy.Options | false | undefined
1131
1698
  }
1132
1699
 
1133
1700
  type MppManagementHandler = {
@@ -1168,7 +1735,7 @@ function laneDefaults(options: middleware.Options): LaneDefaults {
1168
1735
  scopes: apiKey?.scopes ?? [Scope.wildcard],
1169
1736
  },
1170
1737
  mpp: { session: {} },
1171
- public: { rateLimit: public_?.rateLimit ?? { limit: 60, period: 'minute' } },
1738
+ public: { rateLimit: public_?.rateLimit ?? defaultPublicRateLimit },
1172
1739
  session: true,
1173
1740
  }
1174
1741
  }
@@ -1230,6 +1797,7 @@ function resolveApiKeyLane(
1230
1797
  if (override === true) return current ?? default_
1231
1798
  const base = current ?? default_
1232
1799
  return {
1800
+ bucket: override.bucket ?? base.bucket,
1233
1801
  rateLimit: override.rateLimit ?? base.rateLimit,
1234
1802
  scopes: override.scopes ?? base.scopes,
1235
1803
  }
@@ -1245,6 +1813,7 @@ function resolveMppLane(
1245
1813
  if (override === true) return current ?? default_
1246
1814
  const base = current ?? default_
1247
1815
  return {
1816
+ bucket: override.bucket ?? base.bucket,
1248
1817
  rateLimit: override.rateLimit ?? base.rateLimit,
1249
1818
  session: { ...base.session, ...override.session },
1250
1819
  }
@@ -1259,7 +1828,10 @@ function resolvePublicLane(
1259
1828
  if (override === false) return undefined
1260
1829
  if (override === true) return current ?? default_
1261
1830
  const base = current ?? default_
1262
- return { rateLimit: override.rateLimit ?? base.rateLimit }
1831
+ return {
1832
+ bucket: override.bucket ?? base.bucket,
1833
+ rateLimit: override.rateLimit ?? base.rateLimit,
1834
+ }
1263
1835
  }
1264
1836
 
1265
1837
  function resolveSessionLane(
@@ -1304,7 +1876,7 @@ function policies(c: hono_Context) {
1304
1876
  return matchedRoutes(c)
1305
1877
  .slice(c.req.routeIndex + 1)
1306
1878
  .map(policyFromRoute)
1307
- .filter((routePolicy): routePolicy is policy.Options => routePolicy !== undefined)
1879
+ .filter((routePolicy): routePolicy is policy.Options | false => routePolicy !== undefined)
1308
1880
  }
1309
1881
 
1310
1882
  function openApiSpec(route: RouterRoute) {
@@ -1328,6 +1900,8 @@ function mppManagementFromRoute(route: RouterRoute) {
1328
1900
  export type OperationAccess = {
1329
1901
  /** Whether API-key access is allowed. */
1330
1902
  apiKey: boolean
1903
+ /** Whether this operation explicitly bypasses auth instead of inheriting document security. */
1904
+ bypass?: true | undefined
1331
1905
  /** Whether MPP payment is accepted (enables the `402` payment-challenge response). */
1332
1906
  mpp: boolean
1333
1907
  /** Whether anonymous public-quota access is allowed (keeps the anonymous security option). */
@@ -1346,14 +1920,14 @@ export type OperationAccess = {
1346
1920
  * operation surfaces only the lanes its route opts into via {@link policy}.
1347
1921
  */
1348
1922
  export function describeAccess(app: Hono<any, any>): Record<string, OperationAccess> {
1349
- const groups = new Map<string, { operationId?: string; overrides: PolicyOverride[] }>()
1923
+ const groups = new Map<string, { operationId?: string; overrides: (PolicyOverride | false)[] }>()
1350
1924
  for (const route of app.routes) {
1351
1925
  const key = `${route.method} ${route.path}`
1352
1926
  const group = groups.get(key) ?? { overrides: [] }
1353
1927
  const spec = openApiSpec(route) as { operationId?: unknown } | undefined
1354
1928
  if (typeof spec?.operationId === 'string') group.operationId = spec.operationId
1355
1929
  const override = policyFromRoute(route)
1356
- if (override) group.overrides.push(override)
1930
+ if (override !== undefined) group.overrides.push(override)
1357
1931
  groups.set(key, group)
1358
1932
  }
1359
1933
 
@@ -1365,7 +1939,12 @@ export function describeAccess(app: Hono<any, any>): Record<string, OperationAcc
1365
1939
  let public_ = false
1366
1940
  let mpp = false
1367
1941
  let session = false
1942
+ let bypass = false
1368
1943
  for (const override of overrides) {
1944
+ if (override === false) {
1945
+ bypass = true
1946
+ break
1947
+ }
1369
1948
  if (override.apiKey !== undefined) apiKey = override.apiKey !== false
1370
1949
  if (override.apiKey && override.apiKey !== true && override.apiKey.scopes)
1371
1950
  scopes = override.apiKey.scopes
@@ -1373,7 +1952,14 @@ export function describeAccess(app: Hono<any, any>): Record<string, OperationAcc
1373
1952
  if (override.mpp !== undefined) mpp = override.mpp !== false
1374
1953
  if (override.session !== undefined) session = override.session !== false
1375
1954
  }
1376
- access[operationId] = { apiKey, mpp, public: public_, scopes: apiKey ? scopes : [], session }
1955
+ access[operationId] = {
1956
+ apiKey,
1957
+ ...(bypass ? { bypass: true } : {}),
1958
+ mpp,
1959
+ public: public_,
1960
+ scopes: apiKey ? scopes : [],
1961
+ session,
1962
+ }
1377
1963
  }
1378
1964
  return access
1379
1965
  }
@@ -1417,16 +2003,23 @@ export function require<environment extends Environment = Environment>(
1417
2003
  const hasQueryApiKey = new URL(c.req.url).searchParams.has('key')
1418
2004
  // Auth owns `key`; strict route schemas must not validate it.
1419
2005
  stripApiKeyQuery(c)
1420
- // Reject unknown chains before MPP builds a chain-bound challenge. Route
1421
- // groups publish their supported chains into the shared app context.
1422
2006
  const chainId = explicitChainId(c)
1423
2007
  const supportedChainIds = (c.var as Record<string, unknown>)['supportedChainIds']
1424
- if (
1425
- chainId !== undefined &&
1426
- supportedChainIds instanceof Set &&
1427
- !supportedChainIds.has(chainId)
1428
- )
1429
- return Response.unsupportedChainId(c, chainId, supportedChainIds)
2008
+ const unsupportedChain = (() => {
2009
+ if (
2010
+ chainId === undefined ||
2011
+ !(supportedChainIds instanceof Set) ||
2012
+ supportedChainIds.has(chainId)
2013
+ )
2014
+ return undefined
2015
+ return { chainId, supportedChainIds }
2016
+ })()
2017
+ if (unsupportedChain && !credential)
2018
+ return Response.unsupportedChainId(
2019
+ c,
2020
+ unsupportedChain.chainId,
2021
+ unsupportedChain.supportedChainIds,
2022
+ )
1430
2023
  const proceed = async () => {
1431
2024
  await next()
1432
2025
  // Query credential responses must not enter shared caches.
@@ -1450,12 +2043,24 @@ export function require<environment extends Environment = Environment>(
1450
2043
  // The super admin secret precedes key lookup: it is not a stored key.
1451
2044
  // It must never reach KV resolution or scope/quota checks.
1452
2045
  if (auth.superAdmin && ApiKey.hash(credential.token) === auth.superAdmin.tokenHash) {
2046
+ if (unsupportedChain)
2047
+ return Response.unsupportedChainId(
2048
+ c,
2049
+ unsupportedChain.chainId,
2050
+ unsupportedChain.supportedChainIds,
2051
+ )
1453
2052
  c.set('principal', { actor: 'super_admin', id: 'super_admin', type: 'super_admin' })
1454
2053
  return proceed()
1455
2054
  }
1456
2055
 
1457
2056
  const apiKey_resolved = await auth.apiKey?.resolve(c, credential.token)
1458
2057
  if (!apiKey_resolved) {
2058
+ if (unsupportedChain)
2059
+ return Response.unsupportedChainId(
2060
+ c,
2061
+ unsupportedChain.chainId,
2062
+ unsupportedChain.supportedChainIds,
2063
+ )
1459
2064
  // A bearer session token is indistinguishable from an API key at the
1460
2065
  // header, so a failed key lookup falls through to the session lane
1461
2066
  // before rejecting.
@@ -1498,6 +2103,34 @@ export function require<environment extends Environment = Environment>(
1498
2103
  status: 403,
1499
2104
  })
1500
2105
 
2106
+ // Non-paid requests consume API-key quota before rejection. Paid
2107
+ // requests use the MPP quota after access checks.
2108
+ const scope = policy.apiKey.scopes[0] ?? Scope.wildcard
2109
+ const throttled = apiKey.environment === 'sandbox' && apiKey.billingActive !== true
2110
+ const limit = throttled
2111
+ ? (policy.public?.rateLimit ?? auth.publicRateLimit ?? { limit: 60, period: 'minute' })
2112
+ : resolveApiKeyLimit({ apiKey, auth, policy: policy.apiKey, scope })
2113
+ const paid = hasPayment && !throttled
2114
+ const result = paid
2115
+ ? null
2116
+ : await consumeRateLimit(auth, {
2117
+ key: rateLimitKey(`api_key:${apiKey.id}:scope:${scope}`, policy.apiKey.bucket),
2118
+ limit,
2119
+ })
2120
+ if (result) {
2121
+ setRateLimitHeaders(c, result)
2122
+ // Surface the bucket so callers can correlate a 429 with the exhausted
2123
+ // quota. MPP challenges own their headers and drop these by design.
2124
+ c.header('RateLimit-Scope', scope)
2125
+ }
2126
+
2127
+ if (unsupportedChain)
2128
+ return Response.unsupportedChainId(
2129
+ c,
2130
+ unsupportedChain.chainId,
2131
+ unsupportedChain.supportedChainIds,
2132
+ )
2133
+
1501
2134
  if (
1502
2135
  apiKey.allowedIps.length &&
1503
2136
  !(await IpAllowlist.allows(c, {
@@ -1532,14 +2165,7 @@ export function require<environment extends Environment = Environment>(
1532
2165
  status: 403,
1533
2166
  })
1534
2167
 
1535
- // Sandbox keys without active billing are throttled to the public quota.
1536
- // `billingActive` is snapshotted on the key record (stamped at mint,
1537
- // re-synced when billing changes), so this needs no billing read on the
1538
- // request path. Resolved before the paid lane so a payment credential
1539
- // can't buy past the throttle: sandbox is non-billable testnet.
1540
- const throttled = apiKey.environment === 'sandbox' && apiKey.billingActive !== true
1541
-
1542
- if (hasPayment && !throttled)
2168
+ if (paid)
1543
2169
  return requirePayment(c, proceed, {
1544
2170
  auth,
1545
2171
  payment: { reason: 'api_key_over_quota', type: 'mpp' },
@@ -1547,39 +2173,17 @@ export function require<environment extends Environment = Environment>(
1547
2173
  principal,
1548
2174
  })
1549
2175
 
1550
- if (policy.apiKey) {
1551
- // A route consumes exactly one quota bucket: its single required scope,
1552
- // else `'*'` (zero scopes). Routes today require at most one scope; a
1553
- // future multi-scope route buckets against its first scope.
1554
- const scope = policy.apiKey.scopes[0] ?? Scope.wildcard
1555
- // A throttled sandbox key shares the key's bucket but at the public
1556
- // ceiling, so activating billing lifts the limit on the same counter.
1557
- const limit = throttled
1558
- ? (policy.public?.rateLimit ?? auth.publicRateLimit ?? { limit: 60, period: 'minute' })
1559
- : resolveApiKeyLimit({ apiKey, auth, policy: policy.apiKey, scope })
1560
- const result = await consumeRateLimit(auth, {
1561
- key: `api_key:${apiKey.id}:scope:${scope}`,
1562
- limit,
2176
+ if (result && !result.allowed) {
2177
+ // A throttled sandbox key gets a plain 429, never an MPP challenge. It
2178
+ // must activate billing to lift the ceiling, not pay per request.
2179
+ if (throttled) return rateLimitExceeded(c, result)
2180
+ return requirePaymentOrRateLimit(c, proceed, {
2181
+ auth,
2182
+ payment: { reason: 'api_key_over_quota', type: 'mpp' },
2183
+ policy,
2184
+ principal,
2185
+ rateLimit: result,
1563
2186
  })
1564
- if (result) {
1565
- setRateLimitHeaders(c, result)
1566
- // Surface the bucket so callers can correlate a 429 with the exhausted
1567
- // quota. Set before the over-quota branch so it rides the 429 (an MPP
1568
- // 402 challenge is owned by mppx and drops these headers — by design).
1569
- c.header('RateLimit-Scope', scope)
1570
- }
1571
- if (result && !result.allowed) {
1572
- // A throttled sandbox key gets a plain 429, never an MPP challenge —
1573
- // it must activate billing to lift the ceiling, not pay per request.
1574
- if (throttled) return rateLimitExceeded(c, result)
1575
- return requirePaymentOrRateLimit(c, proceed, {
1576
- auth,
1577
- payment: { reason: 'api_key_over_quota', type: 'mpp' },
1578
- policy,
1579
- principal,
1580
- rateLimit: result,
1581
- })
1582
- }
1583
2187
  }
1584
2188
 
1585
2189
  return proceed()
@@ -1610,7 +2214,7 @@ export function require<environment extends Environment = Environment>(
1610
2214
  const limit = policy.public?.rateLimit
1611
2215
  if (limit) {
1612
2216
  const result = await consumeRateLimit(auth, {
1613
- key: `public:${publicPrincipal.id}`,
2217
+ key: rateLimitKey(`public:${publicPrincipal.id}`, policy.public?.bucket),
1614
2218
  limit,
1615
2219
  })
1616
2220
  if (result) setRateLimitHeaders(c, result)
@@ -1653,6 +2257,8 @@ export declare namespace require {
1653
2257
  /** API-key access policy. */
1654
2258
  apiKey?:
1655
2259
  | {
2260
+ /** Optional counter bucket that isolates this route's quota. */
2261
+ bucket?: string | undefined
1656
2262
  /** API-key quota override for this route (a protective per-route cap). */
1657
2263
  rateLimit?: RateLimit.Limit | undefined
1658
2264
  /**
@@ -1666,6 +2272,8 @@ export declare namespace require {
1666
2272
  /** MPP payment access policy. */
1667
2273
  mpp?:
1668
2274
  | {
2275
+ /** Optional counter bucket that isolates this route's quota. */
2276
+ bucket?: string | undefined
1669
2277
  /** Paid-request quota override for this route (a protective per-route cap). */
1670
2278
  rateLimit?: RateLimit.Limit | undefined
1671
2279
  /** Tempo Session request policy. */
@@ -1675,11 +2283,13 @@ export declare namespace require {
1675
2283
  /** Public access policy. */
1676
2284
  public?:
1677
2285
  | {
2286
+ /** Optional counter bucket that isolates this route's quota. */
2287
+ bucket?: string | undefined
1678
2288
  /** Anonymous public quota for this route. */
1679
2289
  rateLimit: RateLimit.Limit
1680
2290
  }
1681
2291
  | undefined
1682
- /** Session access policy: `true` allows signed-in wallet sessions. */
2292
+ /** Session access policy: `true` allows signed-in sessions. */
1683
2293
  session?: boolean | undefined
1684
2294
  }
1685
2295
  }
@@ -1709,7 +2319,8 @@ type RateLimitAccess = PaymentAccess & {
1709
2319
  */
1710
2320
  const rateLimitConsumeTimeout = 300
1711
2321
 
1712
- function consumeRateLimit(
2322
+ /** Consumes one quota and returns null when its counter is unavailable, allowing callers to fail open. */
2323
+ export function consumeRateLimit(
1713
2324
  auth: Context,
1714
2325
  options: RateLimit.Store.ConsumeOptions,
1715
2326
  ): Promise<RateLimit.Result | null> {
@@ -1818,14 +2429,24 @@ function getApiKeyCredential(c: hono_Context): ApiKeyCredential | false | null {
1818
2429
  }
1819
2430
 
1820
2431
  function clientIp(c: hono_Context, auth: Context): string | undefined {
1821
- return auth.publicClientIp ? auth.publicClientIp(c.req.raw) : c.req.header('cf-connecting-ip')
2432
+ return (
2433
+ trustedClientIps.get(c.req.raw) ??
2434
+ (auth.publicClientIp ? auth.publicClientIp(c.req.raw) : c.req.header('cf-connecting-ip'))
2435
+ )
1822
2436
  }
1823
2437
 
1824
2438
  function trustedClientIp(c: hono_Context, auth: Context): string | undefined {
1825
- if (auth.publicClientIp) return auth.publicClientIp(c.req.raw)
2439
+ return trustedClientIps.get(c.req.raw) ?? resolveTrustedClientIp(c.req.raw, auth.publicClientIp)
2440
+ }
2441
+
2442
+ function resolveTrustedClientIp(
2443
+ request: Request,
2444
+ resolve: ((request: Request) => string | undefined) | undefined,
2445
+ ) {
2446
+ if (resolve) return resolve(request)
1826
2447
  // Cloudflare supplies both the request metadata and this header.
1827
- if (!('cf' in c.req.raw)) return undefined
1828
- return c.req.header('cf-connecting-ip')
2448
+ if (!('cf' in request)) return undefined
2449
+ return request.headers.get('cf-connecting-ip') ?? undefined
1829
2450
  }
1830
2451
 
1831
2452
  /** Removes the reserved auth query parameter before route validation. */
@@ -1958,7 +2579,10 @@ async function requirePayment<environment extends Environment>(
1958
2579
  ) {
1959
2580
  if (hasPaymentCredential(c)) {
1960
2581
  const result = await consumeRateLimit(options.auth, {
1961
- key: `mpp:${options.principal.type}:${options.principal.id}`,
2582
+ key: rateLimitKey(
2583
+ `mpp:${options.principal.type}:${options.principal.id}`,
2584
+ options.policy.mpp?.bucket,
2585
+ ),
1962
2586
  limit: options.policy.mpp?.rateLimit ?? options.auth.mpp?.rateLimit ?? defaultMppRateLimit,
1963
2587
  })
1964
2588
  if (result) {
@@ -2015,6 +2639,10 @@ function requirePaymentOrRateLimit<environment extends Environment>(
2015
2639
  return rateLimitExceeded(c, options.rateLimit)
2016
2640
  }
2017
2641
 
2642
+ function rateLimitKey(key: string, bucket: string | undefined) {
2643
+ return bucket === undefined ? key : `${key}:bucket:${bucket}`
2644
+ }
2645
+
2018
2646
  /** Emits a `429` with a `Retry-After` derived from the window reset. */
2019
2647
  function rateLimitExceeded(c: hono_Context, result: RateLimit.Result) {
2020
2648
  c.header('Retry-After', String(Math.max(result.reset - Math.ceil(Date.now() / 1_000), 1)))
@@ -2050,17 +2678,12 @@ export type Session = {
2050
2678
  resolve: (c: hono_Context) => Promise<SessionPrincipal | null>
2051
2679
  }
2052
2680
 
2053
- // Resolve the session lane from the auth context's capability. Failures
2054
- // resolve to `null` so the remaining lanes and the final `401` still apply.
2681
+ // Resolve the session lane from the auth context's capability. Dependency
2682
+ // failures propagate to the app error boundary instead of becoming a `401`.
2055
2683
  async function resolveSession(c: hono_Context, auth: Context): Promise<SessionPrincipal | null> {
2056
2684
  const session = auth.session
2057
2685
  if (!session) return null
2058
- try {
2059
- return await session.resolve(c)
2060
- } catch (error) {
2061
- console.error('[auth] session resolve failed; treating as no session', error)
2062
- return null
2063
- }
2686
+ return session.resolve(c)
2064
2687
  }
2065
2688
 
2066
2689
  /** Maximum resolve-cache entries held per isolate before eviction. */
@@ -2078,40 +2701,53 @@ const cachedMaxEntries = 10_000
2078
2701
  function cachedResolve(
2079
2702
  resolve: (c: hono_Context, token: string) => Promise<ApiKey.ApiKey | null>,
2080
2703
  options: middleware.Cache,
2081
- ): (c: hono_Context, token: string) => Promise<ApiKey.ApiKey | null> {
2704
+ ) {
2082
2705
  const { negativeTtl = 10_000, now = Date.now, ttl = 60_000 } = options
2083
2706
  type Cell = { expiresAt: number; value: ApiKey.ApiKey | null }
2084
2707
  const cells = new Map<string, Cell>()
2085
2708
  const flights = new Map<string, Promise<ApiKey.ApiKey | null>>()
2086
2709
 
2087
- return async (c, token) => {
2088
- // Versioned so a future record-shape change can't serve stale shapes.
2089
- const key = `v1:${ApiKey.hash(token)}`
2090
- const cell = cells.get(key)
2091
- if (cell && cell.expiresAt > now()) return cell.value
2092
- if (cell) cells.delete(key)
2093
-
2094
- const existing = flights.get(key)
2095
- if (existing) return existing
2096
-
2097
- const flight = (async () => {
2098
- const value = await resolve(c, token)
2099
- // Bound the cache: random invalid tokens each add a (negative) entry,
2100
- // so sweep expired cells at the cap and then drop the oldest.
2101
- if (cells.size >= cachedMaxEntries) {
2102
- const time = now()
2103
- for (const [name, entry] of cells) if (entry.expiresAt <= time) cells.delete(name)
2104
- while (cells.size >= cachedMaxEntries) cells.delete(cells.keys().next().value as string)
2710
+ return {
2711
+ invalidate(token: string) {
2712
+ cells.delete(`v1:${ApiKey.hash(token)}`)
2713
+ },
2714
+ peek(token: string) {
2715
+ const key = `v1:${ApiKey.hash(token)}`
2716
+ const cell = cells.get(key)
2717
+ if (!cell) return undefined
2718
+ if (cell.expiresAt > now()) return cell.value
2719
+ cells.delete(key)
2720
+ return undefined
2721
+ },
2722
+ async resolve(c: hono_Context, token: string) {
2723
+ // Versioned so a future record-shape change can't serve stale shapes.
2724
+ const key = `v1:${ApiKey.hash(token)}`
2725
+ const cell = cells.get(key)
2726
+ if (cell && cell.expiresAt > now()) return cell.value
2727
+ if (cell) cells.delete(key)
2728
+
2729
+ const existing = flights.get(key)
2730
+ if (existing) return existing
2731
+
2732
+ const flight = (async () => {
2733
+ const value = await resolve(c, token)
2734
+ // Bound the cache: random invalid tokens each add a (negative) entry,
2735
+ // so sweep expired cells at the cap and then drop the oldest.
2736
+ if (cells.size >= cachedMaxEntries) {
2737
+ const time = now()
2738
+ for (const [name, entry] of cells) if (entry.expiresAt <= time) cells.delete(name)
2739
+ while (cells.size >= cachedMaxEntries) cells.delete(cells.keys().next().value as string)
2740
+ }
2741
+ cells.set(key, { expiresAt: now() + (value ? ttl : negativeTtl), value })
2742
+ return value
2743
+ })()
2744
+ flights.set(key, flight)
2745
+ try {
2746
+ return await flight
2747
+ } finally {
2748
+ flights.delete(key)
2105
2749
  }
2106
- cells.set(key, { expiresAt: now() + (value ? ttl : negativeTtl), value })
2107
- return value
2108
- })()
2109
- flights.set(key, flight)
2110
- try {
2111
- return await flight
2112
- } finally {
2113
- flights.delete(key)
2114
- }
2750
+ },
2115
2751
  }
2116
2752
  }
2117
2753