tapimo 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (494) hide show
  1. package/README.md +13 -5
  2. package/dist/ApiKey.d.ts +2 -2
  3. package/dist/ApiKey.d.ts.map +1 -1
  4. package/dist/ApiKey.js +2 -2
  5. package/dist/ApiKey.js.map +1 -1
  6. package/dist/ApiKeys.d.ts +85 -11
  7. package/dist/ApiKeys.d.ts.map +1 -1
  8. package/dist/ApiKeys.js +218 -56
  9. package/dist/ApiKeys.js.map +1 -1
  10. package/dist/App.d.ts +12543 -13912
  11. package/dist/App.d.ts.map +1 -1
  12. package/dist/App.js +4 -5
  13. package/dist/App.js.map +1 -1
  14. package/dist/Scope.d.ts +12 -20
  15. package/dist/Scope.d.ts.map +1 -1
  16. package/dist/Scope.js +20 -36
  17. package/dist/Scope.js.map +1 -1
  18. package/dist/admin/App.d.ts +871 -828
  19. package/dist/admin/App.d.ts.map +1 -1
  20. package/dist/admin/App.js +14 -26
  21. package/dist/admin/App.js.map +1 -1
  22. package/dist/admin/apps/api-keys.d.ts +93 -186
  23. package/dist/admin/apps/api-keys.d.ts.map +1 -1
  24. package/dist/admin/apps/api-keys.js +3 -5
  25. package/dist/admin/apps/api-keys.js.map +1 -1
  26. package/dist/admin/apps/audit-logs.d.ts +18 -18
  27. package/dist/admin/apps/audit-logs.js +1 -1
  28. package/dist/admin/apps/audit-logs.js.map +1 -1
  29. package/dist/admin/apps/earn-vaults.d.ts +27 -27
  30. package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
  31. package/dist/admin/apps/earn-vaults.js +11 -5
  32. package/dist/admin/apps/earn-vaults.js.map +1 -1
  33. package/dist/admin/apps/organizations.d.ts +17 -17
  34. package/dist/admin/apps/prop-amms.d.ts +4 -4
  35. package/dist/admin/apps/routes-support.js +1 -38
  36. package/dist/admin/apps/routes-support.js.map +1 -1
  37. package/dist/admin/apps/routes.d.ts +153 -153
  38. package/dist/admin/apps/sentinel.d.ts +4 -4
  39. package/dist/admin/apps/verified-tokens.d.ts +24 -24
  40. package/dist/admin/apps/zone-delegation-requests.d.ts +332 -0
  41. package/dist/admin/apps/zone-delegation-requests.d.ts.map +1 -0
  42. package/dist/admin/apps/zone-delegation-requests.js +200 -0
  43. package/dist/admin/apps/zone-delegation-requests.js.map +1 -0
  44. package/dist/admin/apps/zone-delegations.d.ts +512 -52
  45. package/dist/admin/apps/zone-delegations.d.ts.map +1 -1
  46. package/dist/admin/apps/zone-delegations.js +134 -44
  47. package/dist/admin/apps/zone-delegations.js.map +1 -1
  48. package/dist/admin/index.d.ts +1 -1
  49. package/dist/admin/index.d.ts.map +1 -1
  50. package/dist/admin/index.js +1 -1
  51. package/dist/admin/index.js.map +1 -1
  52. package/dist/admin/ui.generated.d.ts +1 -1
  53. package/dist/admin/ui.generated.d.ts.map +1 -1
  54. package/dist/admin/ui.generated.js +341 -397
  55. package/dist/admin/ui.generated.js.map +1 -1
  56. package/dist/analytics/tables/requestEvents.d.ts.map +1 -1
  57. package/dist/analytics/tables/requestEvents.js +4 -2
  58. package/dist/analytics/tables/requestEvents.js.map +1 -1
  59. package/dist/apps/data/App.d.ts +11932 -13214
  60. package/dist/apps/data/App.d.ts.map +1 -1
  61. package/dist/apps/data/App.js +32 -13
  62. package/dist/apps/data/App.js.map +1 -1
  63. package/dist/apps/data/ZoneSelection.d.ts +1 -1
  64. package/dist/apps/data/ZoneSelection.d.ts.map +1 -1
  65. package/dist/apps/data/ZoneSelection.js +2 -2
  66. package/dist/apps/data/ZoneSelection.js.map +1 -1
  67. package/dist/apps/data/routes/activities.d.ts +60 -27
  68. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  69. package/dist/apps/data/routes/activities.js +91 -16
  70. package/dist/apps/data/routes/activities.js.map +1 -1
  71. package/dist/apps/data/routes/addresses.d.ts +893 -875
  72. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  73. package/dist/apps/data/routes/balances.d.ts +36 -36
  74. package/dist/apps/data/routes/balances.d.ts.map +1 -1
  75. package/dist/apps/data/routes/balances.js +3 -1
  76. package/dist/apps/data/routes/balances.js.map +1 -1
  77. package/dist/apps/data/routes/blocks.d.ts +40 -40
  78. package/dist/apps/data/routes/blocks.d.ts.map +1 -1
  79. package/dist/apps/data/routes/blocks.js +3 -7
  80. package/dist/apps/data/routes/blocks.js.map +1 -1
  81. package/dist/apps/data/routes/coingecko.d.ts +236 -236
  82. package/dist/apps/data/routes/earn-transactions.d.ts +14 -14
  83. package/dist/apps/data/routes/earn.d.ts +261 -1445
  84. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  85. package/dist/apps/data/routes/earn.js +64 -490
  86. package/dist/apps/data/routes/earn.js.map +1 -1
  87. package/dist/apps/data/routes/exchanges.d.ts +144 -144
  88. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  89. package/dist/apps/data/routes/exchanges.js +5 -15
  90. package/dist/apps/data/routes/exchanges.js.map +1 -1
  91. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  92. package/dist/apps/data/routes/fee-amm.js +3 -9
  93. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  94. package/dist/apps/data/routes/indexer.d.ts +13 -13
  95. package/dist/apps/data/routes/receipts.d.ts +53 -53
  96. package/dist/apps/data/routes/receipts.js +1 -1
  97. package/dist/apps/data/routes/receipts.js.map +1 -1
  98. package/dist/apps/data/routes/rpc.d.ts +52 -0
  99. package/dist/apps/data/routes/rpc.d.ts.map +1 -1
  100. package/dist/apps/data/routes/rpc.js +19 -18
  101. package/dist/apps/data/routes/rpc.js.map +1 -1
  102. package/dist/apps/data/routes/tokenlist.d.ts +14 -14
  103. package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
  104. package/dist/apps/data/routes/tokenlist.js +1 -3
  105. package/dist/apps/data/routes/tokenlist.js.map +1 -1
  106. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  107. package/dist/apps/data/routes/tokens.js +7 -5
  108. package/dist/apps/data/routes/tokens.js.map +1 -1
  109. package/dist/apps/data/routes/transactions.d.ts +281 -281
  110. package/dist/apps/data/routes/transactions.js +3 -3
  111. package/dist/apps/data/routes/transactions.js.map +1 -1
  112. package/dist/apps/data/routes/transfers.d.ts +12 -12
  113. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  114. package/dist/apps/data/routes/transfers.js +1 -3
  115. package/dist/apps/data/routes/transfers.js.map +1 -1
  116. package/dist/apps/data/routes/valuation.d.ts +30 -30
  117. package/dist/apps/data/routes/valuation.d.ts.map +1 -1
  118. package/dist/apps/data/routes/valuation.js +1 -3
  119. package/dist/apps/data/routes/valuation.js.map +1 -1
  120. package/dist/apps/data/routes/verified-tokens.d.ts +86 -86
  121. package/dist/apps/data/routes/webhooks.d.ts +102 -102
  122. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  123. package/dist/apps/data/routes/webhooks.js +9 -23
  124. package/dist/apps/data/routes/webhooks.js.map +1 -1
  125. package/dist/apps/data/routes/zone-deposits.d.ts +16 -16
  126. package/dist/apps/data/routes/zone-withdrawals.d.ts +31 -31
  127. package/dist/apps/data/routes/zones.d.ts +28 -28
  128. package/dist/apps/management/App.d.ts +18 -102
  129. package/dist/apps/management/App.d.ts.map +1 -1
  130. package/dist/apps/management/App.js +1 -1
  131. package/dist/apps/management/App.js.map +1 -1
  132. package/dist/apps/management/routes/api-keys.d.ts +253 -339
  133. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  134. package/dist/apps/management/routes/api-keys.js +25 -11
  135. package/dist/apps/management/routes/api-keys.js.map +1 -1
  136. package/dist/apps/management/routes/billing.d.ts +92 -92
  137. package/dist/apps/management/routes/billing.d.ts.map +1 -1
  138. package/dist/apps/management/routes/billing.js +5 -13
  139. package/dist/apps/management/routes/billing.js.map +1 -1
  140. package/dist/apps/management/routes/cli.d.ts.map +1 -1
  141. package/dist/apps/management/routes/cli.js +3 -9
  142. package/dist/apps/management/routes/cli.js.map +1 -1
  143. package/dist/apps/management/routes/faucet.d.ts +16 -16
  144. package/dist/apps/management/routes/fee-payer-usage.d.ts +38 -38
  145. package/dist/apps/management/routes/fee-payer-usage.d.ts.map +1 -1
  146. package/dist/apps/management/routes/fee-payer-usage.js +2 -4
  147. package/dist/apps/management/routes/fee-payer-usage.js.map +1 -1
  148. package/dist/apps/management/routes/invitations.d.ts +52 -52
  149. package/dist/apps/management/routes/invitations.d.ts.map +1 -1
  150. package/dist/apps/management/routes/invitations.js +4 -12
  151. package/dist/apps/management/routes/invitations.js.map +1 -1
  152. package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
  153. package/dist/apps/management/routes/invite-links.js +6 -14
  154. package/dist/apps/management/routes/invite-links.js.map +1 -1
  155. package/dist/apps/management/routes/me.d.ts +6 -6
  156. package/dist/apps/management/routes/me.d.ts.map +1 -1
  157. package/dist/apps/management/routes/me.js +3 -7
  158. package/dist/apps/management/routes/me.js.map +1 -1
  159. package/dist/apps/management/routes/members.d.ts +84 -84
  160. package/dist/apps/management/routes/members.d.ts.map +1 -1
  161. package/dist/apps/management/routes/members.js +2 -4
  162. package/dist/apps/management/routes/members.js.map +1 -1
  163. package/dist/apps/management/routes/orgs.d.ts +44 -44
  164. package/dist/apps/management/routes/orgs.d.ts.map +1 -1
  165. package/dist/apps/management/routes/orgs.js +2 -6
  166. package/dist/apps/management/routes/orgs.js.map +1 -1
  167. package/dist/apps/management/routes/projects.d.ts.map +1 -1
  168. package/dist/apps/management/routes/projects.js +2 -6
  169. package/dist/apps/management/routes/projects.js.map +1 -1
  170. package/dist/apps/management/routes/route-usage.d.ts +34 -34
  171. package/dist/apps/management/routes/route-usage.d.ts.map +1 -1
  172. package/dist/apps/management/routes/route-usage.js +2 -4
  173. package/dist/apps/management/routes/route-usage.js.map +1 -1
  174. package/dist/apps/management/routes/routes-access-requests.d.ts +120 -91
  175. package/dist/apps/management/routes/routes-access-requests.d.ts.map +1 -1
  176. package/dist/apps/management/routes/routes-access-requests.js +49 -9
  177. package/dist/apps/management/routes/routes-access-requests.js.map +1 -1
  178. package/dist/apps/management/routes/usage.d.ts.map +1 -1
  179. package/dist/apps/management/routes/usage.js +8 -16
  180. package/dist/apps/management/routes/usage.js.map +1 -1
  181. package/dist/apps/management/routes/verified-token-requests.d.ts +39 -39
  182. package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
  183. package/dist/apps/management/routes/verified-token-requests.js +3 -7
  184. package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
  185. package/dist/apps/management/routes/webhooks.d.ts +2089 -2089
  186. package/dist/apps/management/routes/zone-delegations.d.ts +14 -17
  187. package/dist/apps/management/routes/zone-delegations.d.ts.map +1 -1
  188. package/dist/apps/management/routes/zone-delegations.js +1 -6
  189. package/dist/apps/management/routes/zone-delegations.js.map +1 -1
  190. package/dist/apps/mpp/App.d.ts +44 -44
  191. package/dist/apps/mpp/App.js +3 -3
  192. package/dist/apps/mpp/App.js.map +1 -1
  193. package/dist/apps/mpp/internal/Adapter.js +1 -1
  194. package/dist/apps/mpp/internal/Adapter.js.map +1 -1
  195. package/dist/apps/mpp/internal/Error.d.ts.map +1 -1
  196. package/dist/apps/mpp/internal/Error.js +1 -0
  197. package/dist/apps/mpp/internal/Error.js.map +1 -1
  198. package/dist/apps/mpp/internal/Policy.d.ts +5 -1
  199. package/dist/apps/mpp/internal/Policy.d.ts.map +1 -1
  200. package/dist/apps/mpp/internal/Policy.js +35 -13
  201. package/dist/apps/mpp/internal/Policy.js.map +1 -1
  202. package/dist/apps/relay/App.d.ts +2 -2
  203. package/dist/apps/relay/App.d.ts.map +1 -1
  204. package/dist/apps/relay/App.js +25 -16
  205. package/dist/apps/relay/App.js.map +1 -1
  206. package/dist/apps/routes/App.d.ts +311 -311
  207. package/dist/apps/routes/routes/deposit-addresses.d.ts +1099 -1099
  208. package/dist/apps/routes/routes/list.d.ts +74 -74
  209. package/dist/apps/routes/routes/transfers.d.ts +94 -94
  210. package/dist/cli/ApiKeys.d.ts +19 -26
  211. package/dist/cli/ApiKeys.d.ts.map +1 -1
  212. package/dist/db/Db.d.ts +3 -3
  213. package/dist/db/Db.d.ts.map +1 -1
  214. package/dist/db/Db.js +27 -0
  215. package/dist/db/Db.js.map +1 -1
  216. package/dist/db/Schema.d.ts +28 -62
  217. package/dist/db/Schema.d.ts.map +1 -1
  218. package/dist/db/Schema.js +18 -18
  219. package/dist/db/Schema.js.map +1 -1
  220. package/dist/db/tables/rewardRuns.d.ts +21 -0
  221. package/dist/db/tables/rewardRuns.d.ts.map +1 -1
  222. package/dist/db/tables/rewardRuns.js +19 -0
  223. package/dist/db/tables/rewardRuns.js.map +1 -1
  224. package/dist/db/tables/routesAccessRequests.d.ts +13 -0
  225. package/dist/db/tables/routesAccessRequests.d.ts.map +1 -1
  226. package/dist/db/tables/routesAccessRequests.js +12 -0
  227. package/dist/db/tables/routesAccessRequests.js.map +1 -1
  228. package/dist/db/tables/zoneDelegationRequests.d.ts +165 -0
  229. package/dist/db/tables/zoneDelegationRequests.d.ts.map +1 -0
  230. package/dist/db/tables/{zoneKeyRequests.js → zoneDelegationRequests.js} +43 -42
  231. package/dist/db/tables/zoneDelegationRequests.js.map +1 -0
  232. package/dist/db/tables/zoneDelegations.d.ts +11 -5
  233. package/dist/db/tables/zoneDelegations.d.ts.map +1 -1
  234. package/dist/db/tables/zoneDelegations.js +21 -3
  235. package/dist/db/tables/zoneDelegations.js.map +1 -1
  236. package/dist/handlers/internal/accounts.d.ts +7 -0
  237. package/dist/handlers/internal/accounts.d.ts.map +1 -0
  238. package/dist/handlers/internal/{multisig.js → accounts.js} +10 -10
  239. package/dist/handlers/internal/{multisig.js.map → accounts.js.map} +1 -1
  240. package/dist/handlers/internal/sponsorship.js +17 -17
  241. package/dist/handlers/internal/sponsorship.js.map +1 -1
  242. package/dist/handlers/relay.d.ts +6 -6
  243. package/dist/handlers/relay.d.ts.map +1 -1
  244. package/dist/handlers/relay.js +15 -15
  245. package/dist/handlers/relay.js.map +1 -1
  246. package/dist/internal/Auth.d.ts.map +1 -1
  247. package/dist/internal/Auth.js +4 -8
  248. package/dist/internal/Auth.js.map +1 -1
  249. package/dist/internal/EarnRates.d.ts.map +1 -1
  250. package/dist/internal/EarnRates.js +1 -3
  251. package/dist/internal/EarnRates.js.map +1 -1
  252. package/dist/internal/EarnVaults.js +2 -2
  253. package/dist/internal/Log.d.ts +2 -4
  254. package/dist/internal/Log.d.ts.map +1 -1
  255. package/dist/internal/Log.js +0 -3
  256. package/dist/internal/Log.js.map +1 -1
  257. package/dist/internal/Response.d.ts +1 -1
  258. package/dist/internal/Response.d.ts.map +1 -1
  259. package/dist/internal/Response.js +0 -3
  260. package/dist/internal/Response.js.map +1 -1
  261. package/dist/internal/Schema.d.ts +11 -0
  262. package/dist/internal/Schema.d.ts.map +1 -1
  263. package/dist/internal/Schema.js +24 -1
  264. package/dist/internal/Schema.js.map +1 -1
  265. package/dist/internal/ZoneAccess.d.ts +70 -35
  266. package/dist/internal/ZoneAccess.d.ts.map +1 -1
  267. package/dist/internal/ZoneAccess.js +312 -131
  268. package/dist/internal/ZoneAccess.js.map +1 -1
  269. package/dist/internal/ZoneDelegation.d.ts +7 -19
  270. package/dist/internal/ZoneDelegation.d.ts.map +1 -1
  271. package/dist/internal/ZoneDelegation.js +8 -29
  272. package/dist/internal/ZoneDelegation.js.map +1 -1
  273. package/dist/internal/{ZoneKeyApproval.d.ts → ZoneDelegationApproval.d.ts} +3 -5
  274. package/dist/internal/ZoneDelegationApproval.d.ts.map +1 -0
  275. package/dist/internal/ZoneDelegationApproval.js +16 -0
  276. package/dist/internal/ZoneDelegationApproval.js.map +1 -0
  277. package/dist/internal/ZoneKeyRewrite.d.ts +98 -0
  278. package/dist/internal/ZoneKeyRewrite.d.ts.map +1 -0
  279. package/dist/internal/ZoneKeyRewrite.js +151 -0
  280. package/dist/internal/ZoneKeyRewrite.js.map +1 -0
  281. package/dist/internal/rewards/Campaigns.d.ts +2 -0
  282. package/dist/internal/rewards/Campaigns.d.ts.map +1 -1
  283. package/dist/internal/rewards/Campaigns.js.map +1 -1
  284. package/dist/internal/rewards/Distributions.d.ts.map +1 -1
  285. package/dist/internal/rewards/Distributions.js +2 -6
  286. package/dist/internal/rewards/Distributions.js.map +1 -1
  287. package/dist/internal/rewards/Monitor.d.ts +4 -1
  288. package/dist/internal/rewards/Monitor.d.ts.map +1 -1
  289. package/dist/internal/rewards/Monitor.js +19 -2
  290. package/dist/internal/rewards/Monitor.js.map +1 -1
  291. package/dist/internal/rewards/Runner.d.ts.map +1 -1
  292. package/dist/internal/rewards/Runner.js +9 -1
  293. package/dist/internal/rewards/Runner.js.map +1 -1
  294. package/dist/internal/routes/Action.d.ts.map +1 -1
  295. package/dist/internal/routes/Action.js +2 -3
  296. package/dist/internal/routes/Action.js.map +1 -1
  297. package/dist/internal/routes/Deposit.d.ts.map +1 -1
  298. package/dist/internal/routes/Deposit.js +2 -6
  299. package/dist/internal/routes/Deposit.js.map +1 -1
  300. package/dist/internal/routes/DepositAddress.d.ts.map +1 -1
  301. package/dist/internal/routes/DepositAddress.js +4 -10
  302. package/dist/internal/routes/DepositAddress.js.map +1 -1
  303. package/dist/internal/routes/Policy.d.ts.map +1 -1
  304. package/dist/internal/routes/Policy.js +2 -1
  305. package/dist/internal/routes/Policy.js.map +1 -1
  306. package/dist/internal/routes/Provider.js +8 -8
  307. package/dist/internal/routes/Provider.js.map +1 -1
  308. package/dist/internal/routes/Reconciliation.d.ts.map +1 -1
  309. package/dist/internal/routes/Reconciliation.js +3 -2
  310. package/dist/internal/routes/Reconciliation.js.map +1 -1
  311. package/dist/internal/routes/Transfer.d.ts.map +1 -1
  312. package/dist/internal/routes/Transfer.js +4 -12
  313. package/dist/internal/routes/Transfer.js.map +1 -1
  314. package/dist/internal/routes/UniversalDepositAddress.d.ts.map +1 -1
  315. package/dist/internal/routes/UniversalDepositAddress.js +3 -6
  316. package/dist/internal/routes/UniversalDepositAddress.js.map +1 -1
  317. package/dist/internal/routes/providers/SquidOrder.d.ts.map +1 -1
  318. package/dist/internal/routes/providers/SquidOrder.js +3 -2
  319. package/dist/internal/routes/providers/SquidOrder.js.map +1 -1
  320. package/dist/internal/routes/providers/relay.d.ts.map +1 -1
  321. package/dist/internal/routes/providers/relay.js +4 -3
  322. package/dist/internal/routes/providers/relay.js.map +1 -1
  323. package/package.json +20 -5
  324. package/src/ApiKey.ts +2 -2
  325. package/src/ApiKeys.test.ts +284 -51
  326. package/src/ApiKeys.ts +297 -64
  327. package/src/App.ts +4 -5
  328. package/src/Client.test-d.ts +33 -126
  329. package/src/Scope.test.ts +26 -45
  330. package/src/Scope.ts +24 -37
  331. package/src/admin/App.test.ts +51 -4
  332. package/src/admin/App.ts +25 -33
  333. package/src/admin/Mcp.test.ts +2 -1
  334. package/src/admin/apps/api-keys.test.ts +90 -20
  335. package/src/admin/apps/api-keys.ts +5 -8
  336. package/src/admin/apps/audit-logs.ts +1 -1
  337. package/src/admin/apps/earn-vaults.test.ts +19 -19
  338. package/src/admin/apps/earn-vaults.ts +11 -5
  339. package/src/admin/apps/routes-support.test.ts +254 -3
  340. package/src/admin/apps/routes-support.ts +1 -44
  341. package/src/admin/apps/scopes.test.ts +3 -3
  342. package/src/admin/apps/zone-delegation-requests.test.ts +246 -0
  343. package/src/admin/apps/zone-delegation-requests.ts +240 -0
  344. package/src/admin/apps/zone-delegations.test.ts +218 -58
  345. package/src/admin/apps/zone-delegations.ts +146 -46
  346. package/src/admin/index.ts +1 -1
  347. package/src/admin/ui/src/components/ApiKeyForm.tsx +4 -3
  348. package/src/admin/ui/src/lib/config.ts +3 -3
  349. package/src/admin/ui/src/lib/query-client.ts +1 -1
  350. package/src/admin/ui/src/lib/review-queues.ts +10 -10
  351. package/src/admin/ui/src/lib/routes-setup.test.ts +1 -2
  352. package/src/admin/ui/src/lib/routes-setup.ts +3 -5
  353. package/src/admin/ui/src/lib/scopes.test.ts +3 -6
  354. package/src/admin/ui/src/lib/scopes.ts +2 -9
  355. package/src/admin/ui/src/lib/{zone-key-requests.ts → zone-delegation-requests.ts} +27 -31
  356. package/src/admin/ui/src/routeTree.gen.ts +17 -17
  357. package/src/admin/ui/src/routes/__root.tsx +1 -1
  358. package/src/admin/ui/src/routes/api-keys.tsx +2 -15
  359. package/src/admin/ui/src/routes/audit-logs.tsx +2 -2
  360. package/src/admin/ui/src/routes/index.tsx +11 -11
  361. package/src/admin/ui/src/routes/organizations.tsx +3 -1
  362. package/src/admin/ui/src/routes/organizations_.$orgId.tsx +3 -1
  363. package/src/admin/ui/src/routes/organizations_.$orgId_.setup.tsx +1 -3
  364. package/src/admin/ui/src/routes/{zone-key-requests.tsx → zone-delegation-requests.tsx} +228 -172
  365. package/src/admin/ui/vite.config.ts +14 -1
  366. package/src/admin/ui.generated.ts +412 -583
  367. package/src/analytics/tables/requestEvents.test.ts +13 -3
  368. package/src/analytics/tables/requestEvents.ts +4 -3
  369. package/src/apps/data/App.test.ts +72 -35
  370. package/src/apps/data/App.ts +29 -13
  371. package/src/apps/data/ZoneSelection.test.ts +53 -70
  372. package/src/apps/data/ZoneSelection.ts +2 -2
  373. package/src/apps/data/routes/activities.test.ts +140 -6
  374. package/src/apps/data/routes/activities.ts +124 -18
  375. package/src/apps/data/routes/balances.ts +5 -1
  376. package/src/apps/data/routes/blocks.ts +9 -13
  377. package/src/apps/data/routes/earn-transactions.local.test.ts +6 -1
  378. package/src/apps/data/routes/earn-transactions.test.ts +7 -3
  379. package/src/apps/data/routes/earn.bench.ts +0 -14
  380. package/src/apps/data/routes/earn.discovery.test.ts +4 -39
  381. package/src/apps/data/routes/earn.local.test.ts +27 -34
  382. package/src/apps/data/routes/earn.test.ts +172 -490
  383. package/src/apps/data/routes/earn.ts +103 -652
  384. package/src/apps/data/routes/exchanges.ts +20 -30
  385. package/src/apps/data/routes/fee-amm.ts +12 -18
  386. package/src/apps/data/routes/indexer.test.ts +14 -12
  387. package/src/apps/data/routes/receipts.ts +1 -1
  388. package/src/apps/data/routes/rpc.test.ts +23 -18
  389. package/src/apps/data/routes/rpc.ts +21 -21
  390. package/src/apps/data/routes/rpc.zone.test.ts +60 -6
  391. package/src/apps/data/routes/tokenlist.ts +4 -6
  392. package/src/apps/data/routes/tokens.test.ts +20 -0
  393. package/src/apps/data/routes/tokens.ts +10 -5
  394. package/src/apps/data/routes/transactions.ts +3 -3
  395. package/src/apps/data/routes/transfers.ts +4 -6
  396. package/src/apps/data/routes/valuation.test.ts +2 -4
  397. package/src/apps/data/routes/valuation.ts +4 -6
  398. package/src/apps/data/routes/webhooks.test.ts +1 -5
  399. package/src/apps/data/routes/webhooks.ts +30 -44
  400. package/src/apps/data/routes/zones.test.ts +35 -19
  401. package/src/apps/management/App.ts +3 -1
  402. package/src/apps/management/routes/api-keys.test.ts +112 -22
  403. package/src/apps/management/routes/api-keys.ts +30 -15
  404. package/src/apps/management/routes/billing.ts +17 -25
  405. package/src/apps/management/routes/cli.ts +12 -18
  406. package/src/apps/management/routes/fee-payer-usage.ts +5 -4
  407. package/src/apps/management/routes/invitations.ts +16 -21
  408. package/src/apps/management/routes/invite-links.ts +18 -26
  409. package/src/apps/management/routes/me.ts +9 -13
  410. package/src/apps/management/routes/members.ts +5 -7
  411. package/src/apps/management/routes/orgs.ts +8 -12
  412. package/src/apps/management/routes/projects.ts +8 -12
  413. package/src/apps/management/routes/route-usage.ts +5 -4
  414. package/src/apps/management/routes/routes-access-requests.test.ts +64 -2
  415. package/src/apps/management/routes/routes-access-requests.ts +99 -15
  416. package/src/apps/management/routes/scopes.test.ts +3 -3
  417. package/src/apps/management/routes/usage.ts +20 -28
  418. package/src/apps/management/routes/verified-token-requests.ts +9 -13
  419. package/src/apps/management/routes/zone-delegations.test.ts +3 -5
  420. package/src/apps/management/routes/zone-delegations.ts +4 -9
  421. package/src/apps/mpp/App.ts +3 -3
  422. package/src/apps/mpp/Mpp.zone.test.ts +49 -18
  423. package/src/apps/mpp/internal/Adapter.ts +1 -1
  424. package/src/apps/mpp/internal/Error.test.ts +3 -0
  425. package/src/apps/mpp/internal/Error.ts +1 -0
  426. package/src/apps/mpp/internal/Policy.test.ts +9 -8
  427. package/src/apps/mpp/internal/Policy.ts +37 -14
  428. package/src/apps/relay/App.sandbox.test.ts +15 -14
  429. package/src/apps/relay/App.test.ts +120 -61
  430. package/src/apps/relay/App.ts +28 -18
  431. package/src/apps/relay/App.zone-billing.test.ts +9 -4
  432. package/src/apps/routes/App.test.ts +21 -22
  433. package/src/db/Db.ts +34 -3
  434. package/src/db/Schema.ts +26 -26
  435. package/src/db/tables/rewardRuns.ts +39 -0
  436. package/src/db/tables/routesAccessRequests.test.ts +65 -0
  437. package/src/db/tables/routesAccessRequests.ts +25 -0
  438. package/src/db/tables/{zoneKeyRequests.test.ts → zoneDelegationRequests.test.ts} +36 -77
  439. package/src/db/tables/{zoneKeyRequests.ts → zoneDelegationRequests.ts} +69 -52
  440. package/src/db/tables/zoneDelegations.test.ts +5 -6
  441. package/src/db/tables/zoneDelegations.ts +25 -8
  442. package/src/handlers/internal/{multisig.store.test.ts → accounts.store.test.ts} +16 -16
  443. package/src/handlers/internal/{multisig.test.ts → accounts.test.ts} +85 -82
  444. package/src/handlers/internal/{multisig.ts → accounts.ts} +9 -9
  445. package/src/handlers/internal/sponsorship.ts +20 -20
  446. package/src/handlers/relay.test.ts +48 -46
  447. package/src/handlers/relay.ts +26 -26
  448. package/src/internal/Auth.test.ts +6 -2
  449. package/src/internal/Auth.ts +4 -10
  450. package/src/internal/EarnRates.ts +4 -6
  451. package/src/internal/EarnVaults.ts +2 -2
  452. package/src/internal/Log.test-d.ts +1 -0
  453. package/src/internal/Log.test.ts +4 -6
  454. package/src/internal/Log.ts +2 -6
  455. package/src/internal/Response.ts +0 -3
  456. package/src/internal/Schema.test.ts +42 -0
  457. package/src/internal/Schema.ts +36 -1
  458. package/src/internal/ZoneAccess.test.ts +515 -312
  459. package/src/internal/ZoneAccess.ts +410 -158
  460. package/src/internal/ZoneDelegation.test.ts +1 -41
  461. package/src/internal/ZoneDelegation.ts +10 -48
  462. package/src/internal/ZoneDelegationApproval.test.ts +22 -0
  463. package/src/internal/{ZoneKeyApproval.ts → ZoneDelegationApproval.ts} +4 -11
  464. package/src/internal/ZoneKeyRewrite.ts +231 -0
  465. package/src/internal/rewards/Campaigns.ts +2 -0
  466. package/src/internal/rewards/Distributions.ts +8 -12
  467. package/src/internal/rewards/Monitor.test.ts +64 -0
  468. package/src/internal/rewards/Monitor.ts +27 -4
  469. package/src/internal/rewards/Runner.ts +9 -1
  470. package/src/internal/routes/Action.ts +5 -6
  471. package/src/internal/routes/Deposit.ts +8 -12
  472. package/src/internal/routes/DepositAddress.ts +13 -19
  473. package/src/internal/routes/Policy.ts +2 -1
  474. package/src/internal/routes/Provider.ts +8 -8
  475. package/src/internal/routes/Reconciliation.ts +3 -2
  476. package/src/internal/routes/Transfer.ts +16 -24
  477. package/src/internal/routes/UniversalDepositAddress.ts +9 -12
  478. package/src/internal/routes/providers/SquidOrder.ts +3 -2
  479. package/src/internal/routes/providers/relay.ts +4 -3
  480. package/dist/admin/apps/zone-key-requests.d.ts +0 -406
  481. package/dist/admin/apps/zone-key-requests.d.ts.map +0 -1
  482. package/dist/admin/apps/zone-key-requests.js +0 -183
  483. package/dist/admin/apps/zone-key-requests.js.map +0 -1
  484. package/dist/db/tables/zoneKeyRequests.d.ts +0 -289
  485. package/dist/db/tables/zoneKeyRequests.d.ts.map +0 -1
  486. package/dist/db/tables/zoneKeyRequests.js.map +0 -1
  487. package/dist/handlers/internal/multisig.d.ts +0 -7
  488. package/dist/handlers/internal/multisig.d.ts.map +0 -1
  489. package/dist/internal/ZoneKeyApproval.d.ts.map +0 -1
  490. package/dist/internal/ZoneKeyApproval.js +0 -21
  491. package/dist/internal/ZoneKeyApproval.js.map +0 -1
  492. package/src/admin/apps/zone-key-requests.test.ts +0 -272
  493. package/src/admin/apps/zone-key-requests.ts +0 -231
  494. package/src/internal/ZoneKeyApproval.test.ts +0 -46
package/src/admin/App.ts CHANGED
@@ -15,6 +15,7 @@ import * as OpenApi from '../internal/OpenApi.js'
15
15
  import * as RateLimit from '../internal/RateLimit.js'
16
16
  import type * as Store from '../internal/Store.js'
17
17
  import * as Response from '../internal/Response.js'
18
+ import * as ZoneDelegationApproval from '../internal/ZoneDelegationApproval.js'
18
19
  import * as Viem from '../internal/Viem.js'
19
20
  import * as Tidx from '../internal/Tidx.js'
20
21
  import * as Zones from '../apps/Zones.js'
@@ -34,9 +35,8 @@ import { sentinel } from './apps/sentinel.js'
34
35
  import { subsidies } from './apps/subsidies.js'
35
36
  import { verifiedTokens } from './apps/verified-tokens.js'
36
37
  import * as Ui from './ui.generated.js'
37
- import * as ZoneKeyApproval from '../internal/ZoneKeyApproval.js'
38
+ import * as ZoneDelegationRequests from './apps/zone-delegation-requests.js'
38
39
  import * as ZoneDelegations from './apps/zone-delegations.js'
39
- import * as ZoneKeyRequests from './apps/zone-key-requests.js'
40
40
  import * as AuditLogs from './apps/audit-logs.js'
41
41
 
42
42
  /** A verified admin identity, as returned by {@link create.Options.identify}. */
@@ -72,10 +72,10 @@ export type Environment = {
72
72
  metrics: Metrics.Metrics | undefined
73
73
  /** Zone chains available to admin routes. */
74
74
  zones: readonly Chain[]
75
- /** Configured authoritative approval flow, absent until provisioned. */
76
- zoneKeyApproval: create.Options['zoneKeyApproval']
77
- /** Verified session used only by the Zone-key approval routes. */
78
- zoneKeyMember: ZoneKeyApproval.Member
75
+ /** Configured approval flow for Zone delegations, absent until provisioned. */
76
+ delegationApproval: create.Options['delegationApproval']
77
+ /** Verified session used only by the delegation-request routes. */
78
+ approver: ZoneDelegationApproval.Member
79
79
  }
80
80
  }
81
81
 
@@ -117,7 +117,7 @@ export function create(options: create.Options) {
117
117
  c.set('metrics', options.metrics)
118
118
  c.set('rateLimit', rateLimit)
119
119
  c.set('zones', zones)
120
- c.set('zoneKeyApproval', options.zoneKeyApproval)
120
+ c.set('delegationApproval', options.delegationApproval)
121
121
  c.set('identity', await identify(c.req.raw, c))
122
122
  try {
123
123
  return await next()
@@ -148,29 +148,29 @@ export function create(options: create.Options) {
148
148
  // `/config.json` and inlined into the shell, so the UI reads it synchronously.
149
149
  async function bootstrapConfig(c: Context<Environment>) {
150
150
  const identity = c.get('identity')
151
- // Only steers navigation; the approval routes re-verify membership on every decision.
152
- const zoneKeyApprover = await (async () => {
153
- const config = c.get('zoneKeyApproval')
151
+ // Only steers navigation; the request routes re-verify membership on every decision.
152
+ const delegationApprover = await (async () => {
153
+ const config = c.get('delegationApproval')
154
154
  if (!identity || !config?.groupId || !config.lookup) return false
155
155
  try {
156
156
  const member = await config.identify(c.req.raw, c)
157
157
  return (
158
- ZoneKeyApproval.active(member) &&
158
+ ZoneDelegationApproval.active(member) &&
159
159
  member.eligible &&
160
160
  member.email.toLowerCase() === identity.email.toLowerCase()
161
161
  )
162
162
  } catch {
163
- c.get('metrics')?.count('zone_key_approval_failure_count', 1)
163
+ c.get('metrics')?.count('zone_delegation_approval_failure_count', 1)
164
164
  // Unknown, not a denial: the UI keeps Approve and the server re-checks membership.
165
165
  return null
166
166
  }
167
167
  })()
168
168
  return {
169
169
  auth: {
170
+ delegationApprover,
170
171
  identity,
171
172
  ...(ui?.loginUrl ? { loginUrl: ui.loginUrl } : {}),
172
173
  ...(ui?.logoutUrl ? { logoutUrl: ui.logoutUrl } : {}),
173
- zoneKeyApprover,
174
174
  },
175
175
  rewards: {
176
176
  chainId: options.rewardsChainId ?? Viem.chainId.mainnet,
@@ -212,35 +212,23 @@ export function create(options: create.Options) {
212
212
  })
213
213
  return next()
214
214
  }
215
+ // Hono's `/x/*` also matches `/x`; listing both would run each middleware (and audit) twice.
215
216
  const protectedPaths = [
216
217
  '/config.json',
217
- '/api-keys',
218
218
  '/api-keys/*',
219
219
  '/audit-logs/*',
220
- '/zone-delegations',
221
220
  '/zone-delegations/*',
222
- '/zone-key-requests',
223
- '/zone-key-requests/*',
224
- '/early-access',
221
+ '/zone-delegation-requests/*',
225
222
  '/early-access/*',
226
223
  '/openapi.json',
227
- '/earn/verified-vaults',
228
224
  '/earn/verified-vaults/*',
229
- '/prop-amms',
230
225
  '/prop-amms/*',
231
- '/routes',
232
226
  '/routes/*',
233
- '/route-policies',
234
227
  '/route-policies/*',
235
- '/organizations',
236
228
  '/organizations/*',
237
- '/scopes',
238
229
  '/scopes/*',
239
- '/sentinel',
240
230
  '/sentinel/*',
241
- '/subsidies',
242
231
  '/subsidies/*',
243
- '/verified-tokens',
244
232
  '/verified-tokens/*',
245
233
  ] as const
246
234
  for (const path of protectedPaths) app.use(path, requireAuth)
@@ -296,7 +284,7 @@ export function create(options: create.Options) {
296
284
  .route('/api-keys', apiKeys())
297
285
  .route('/audit-logs', AuditLogs.auditLogs())
298
286
  .route('/zone-delegations', ZoneDelegations.zoneDelegations())
299
- .route('/zone-key-requests', ZoneKeyRequests.zoneKeyRequests())
287
+ .route('/zone-delegation-requests', ZoneDelegationRequests.zoneDelegationRequests())
300
288
  .route('/early-access', earlyAccess())
301
289
  .route(
302
290
  '/earn/verified-vaults',
@@ -323,7 +311,8 @@ export function create(options: create.Options) {
323
311
  )
324
312
 
325
313
  app.onError((cause, c) => {
326
- if (cause instanceof ZoneKeyApproval.RequiredError) return Response.keyUpstream(c, cause)
314
+ if (cause instanceof ZoneDelegationApproval.RequiredError)
315
+ return Response.error(c, { code: 'zone_delegation_approval_required', message: cause.message, status: 403 }) // prettier-ignore
327
316
  if (cause instanceof HTTPException) return cause.getResponse()
328
317
  // Redact any leaked API-key token from the logged error/stack.
329
318
  console.error(
@@ -364,8 +353,8 @@ export declare namespace create {
364
353
 
365
354
  /** Options for {@link create}. */
366
355
  type Options = {
367
- /** Verified identity integration for the Zone key quorum workflow. */
368
- zoneKeyApproval?:
356
+ /** Verified identity integration for the Zone delegation quorum workflow. */
357
+ delegationApproval?:
369
358
  | {
370
359
  /** Exact internal identity group required for approvals. */
371
360
  groupId: string
@@ -373,9 +362,12 @@ export declare namespace create {
373
362
  identify: (
374
363
  request: Request,
375
364
  context: Context<Environment>,
376
- ) => ZoneKeyApproval.Member | null | Promise<ZoneKeyApproval.Member | null>
365
+ ) => ZoneDelegationApproval.Member | null | Promise<ZoneDelegationApproval.Member | null>
377
366
  /** Fetches fresh account/group status using the current request; failures must throw. */
378
- lookup: (request: Request, ids: readonly string[]) => ReturnType<ZoneKeyApproval.Lookup>
367
+ lookup: (
368
+ request: Request,
369
+ ids: readonly string[],
370
+ ) => ReturnType<ZoneDelegationApproval.Lookup>
379
371
  }
380
372
  | undefined
381
373
  /** ClickHouse analytics source used by operational usage reads. */
@@ -84,7 +84,8 @@ describe('create', () => {
84
84
  'subsidies_transactions_get',
85
85
  'subsidies_transactions_id_meter-event',
86
86
  'verified-tokens_get',
87
- 'zone-key-requests_get',
87
+ 'zone-delegation-requests_get',
88
+ 'zone-delegations_rewrite-keys_get',
88
89
  ]),
89
90
  )
90
91
  expect(names.filter((name) => name.includes('logo'))).toEqual([])
@@ -116,17 +116,55 @@ describe('POST /api-keys', () => {
116
116
  expect(resolved?.environment).toBe('sandbox')
117
117
  })
118
118
 
119
- test('mints a key with concrete Zone write scopes', async () => {
120
- const { client, store } = await setup()
121
- const scopes = ['zone:421700001:write'] as const
119
+ test('refuses fresh per-Zone write scopes', async () => {
120
+ const { client } = await setup()
122
121
  const response = await client['api-keys'].$post({
123
- json: { ...validBody, scopes },
122
+ json: { ...validBody, scopes: ['zone:421700001:write'] },
124
123
  })
125
- const body = await TestApp.json(response, ApiKeys.schema.createApiKey.Response)
124
+ expect(response.status).toBe(400)
125
+ expect(await response.json()).toMatchObject({ error: { code: 'body_invalid' } })
126
+ })
126
127
 
128
+ test('mints generic Zone write keys only with tags inside active delegations', async () => {
129
+ const { client, db, store } = await setup()
130
+ await TestApp.delegateZone(db, { chainIds: [421700001], orgId: validBody.orgId })
131
+ const mint = (json: object) =>
132
+ client['api-keys'].$post({ json: { ...validBody, scopes: ['zone:write'], ...json } as never })
133
+
134
+ // Admin mints follow the same bound: a broadcasting key names only delegated Zones.
135
+ for (const json of [
136
+ {},
137
+ { zoneTags: [421700002] },
138
+ { environment: 'sandbox', zoneTags: [421700001] },
139
+ { orgId: undefined, projectId: undefined },
140
+ ]) {
141
+ const response = await mint(json)
142
+ expect(response.status).toBe(400)
143
+ expect(await response.json()).toMatchObject({ error: { code: 'body_invalid' } })
144
+ }
145
+ const response = await mint({ zoneTags: [421700001] })
146
+ const body = await TestApp.json(response, ApiKeys.schema.createApiKey.Response)
127
147
  expect(response.status).toBe(200)
128
- expect(body.scopes).toEqual(scopes)
129
- expect((await core_ApiKeys.resolve(store, body.token))?.scopes).toEqual(scopes)
148
+ expect(await core_ApiKeys.resolve(store, body.token)).toMatchObject({
149
+ scopes: ['zone:write'],
150
+ zoneTags: [421700001],
151
+ })
152
+
153
+ // Granting the scope by PATCH is bounded the same way; admin read tags are not.
154
+ const plain = await TestApp.json(
155
+ await client['api-keys'].$post({ json: validBody }),
156
+ ApiKeys.schema.createApiKey.Response,
157
+ )
158
+ const ungranted = await client['api-keys'][':id'].$patch({ json: { scopes: ['zone:write'] }, param: { id: plain.id } }) // prettier-ignore
159
+ expect(ungranted.status).toBe(400)
160
+ const granted = await client['api-keys'][':id'].$patch({ json: { scopes: ['zone:write'], zoneTags: [421700001] }, param: { id: plain.id } }) // prettier-ignore
161
+ expect(granted.status).toBe(200)
162
+ expect(await core_ApiKeys.resolve(store, plain.token)).toMatchObject({
163
+ scopes: ['zone:write'],
164
+ zoneTags: [421700001],
165
+ })
166
+ const reader = await client['api-keys'].$post({ json: { ...validBody, scopes: ['zone:read'], zoneTags: [421700009] } }) // prettier-ignore
167
+ expect(reader.status).toBe(200)
130
168
  })
131
169
 
132
170
  test('records the expiry when provided', async () => {
@@ -429,8 +467,10 @@ describe('POST /api-keys/:id/rotate', () => {
429
467
  orgId: 'org_privy',
430
468
  projectId: 'prj_privy',
431
469
  rateLimits: { '*': { limit: 10_000, period: 'minute' } },
432
- scopes: ['zone:421700001:write'],
470
+ scopes: ['zone:write'],
471
+ zoneTags: [421700001],
433
472
  })
473
+ await TestApp.delegateZone(db, { chainIds: [421700001], environment: 'sandbox', orgId: 'org_privy' }) // prettier-ignore
434
474
  await RoutesPolicies.save(db, {
435
475
  policy: { maxAmount: '12' },
436
476
  scope: {
@@ -477,20 +517,48 @@ describe('POST /api-keys/:id/rotate', () => {
477
517
  ).toMatchObject({ policy: { maxAmount: '12' }, version: 1 })
478
518
  })
479
519
 
480
- test('keeps the approval quorum on Zone read key rotation', async () => {
520
+ test('rotates Zone read keys, copying their tags', async () => {
481
521
  const { client, db, store } = await setup()
482
522
  await Organizations.create(db, { id: 'org_zone', name: 'Zone' })
483
523
  const { record: source } = await core_ApiKeys.mint(store, {
484
524
  name: 'Zone reader',
485
525
  orgId: 'org_zone',
486
- scopes: ['zone:421700001:read'],
526
+ scopes: ['zone:read'],
527
+ zoneTags: [421700001],
487
528
  })
488
529
 
489
- // A rotation hands out a working credential, so one admin alone may not perform it.
490
530
  const response = await client['api-keys'][':id'].rotate.$post({ param: { id: source.id } })
491
- expect(response.status).toBe(403)
492
- expect(await response.json()).toMatchObject({ error: { code: 'zone_key_approval_required' } })
493
- expect(await core_ApiKeys.listByOrg(store, 'org_zone')).toHaveLength(1)
531
+ expect(response.status).toBe(200)
532
+ expect(await response.json()).toMatchObject({ scopes: ['zone:read'], zoneTags: [421700001] })
533
+ expect(await core_ApiKeys.listByOrg(store, 'org_zone')).toHaveLength(2)
534
+ })
535
+
536
+ test('drops the retired per-Zone read scope when rotating or reassigning a rewritten key', async () => {
537
+ const { client, db, store } = await setup()
538
+ await Organizations.create(db, { id: 'org_zone', name: 'Zone' })
539
+ // A record as the rewrite leaves it: the legacy scope beside `zone:read` and its tag.
540
+ const stored = async (id: string, extra: Record<string, unknown>) => {
541
+ const token = `secret_${id}`
542
+ await store.put(
543
+ ApiKey.keyFor(token),
544
+ JSON.stringify({ createdAt: '2026-01-01T00:00:00.000Z', environment: 'production', id, scopes: ['zone:421700001:read', 'zone:read'], tokenLast4: token.slice(-4), zoneTags: [421700001], ...extra }), // prettier-ignore
545
+ )
546
+ return token
547
+ }
548
+ await stored('key_rewritten', { orgId: 'org_zone' })
549
+ const orphan = await stored('key_orphan', { orgId: 'key_orphan' })
550
+ await core_ApiKeys.backfill(store)
551
+
552
+ const rotated = await client['api-keys'][':id'].rotate.$post({ param: { id: 'key_rewritten' } })
553
+ expect(rotated.status).toBe(200)
554
+ expect(await rotated.json()).toMatchObject({ scopes: ['zone:read'], zoneTags: [421700001] })
555
+
556
+ const reassigned = await client['api-keys'][':id'].organization.$put({
557
+ json: { orgId: 'org_zone' },
558
+ param: { id: 'key_orphan' },
559
+ })
560
+ expect(reassigned.status).toBe(200)
561
+ expect(await core_ApiKeys.resolve(store, orphan)).toMatchObject({ orgId: 'org_zone', scopes: ['zone:read'], zoneTags: [421700001] }) // prettier-ignore
494
562
  })
495
563
 
496
564
  test('unknown id → 404', async () => {
@@ -567,7 +635,8 @@ describe('PUT /api-keys/:id/organization', () => {
567
635
  const project = await Projects.create(db, { name: 'Zones', orgId: validBody.orgId })
568
636
  const { record, token } = await core_ApiKeys.mint(store, {
569
637
  name: 'Legacy zone',
570
- scopes: ['zone:421700001:read', 'data:read'],
638
+ scopes: ['zone:read', 'data:read'],
639
+ zoneTags: [421700001],
571
640
  })
572
641
  expect(record.orgId).toBe(record.id)
573
642
 
@@ -591,7 +660,7 @@ describe('PUT /api-keys/:id/organization', () => {
591
660
  record.id,
592
661
  ])
593
662
 
594
- // The route covers only the first owner; further moves keep their reviewed path.
663
+ // The route covers only the first owner; further moves go through PATCH like any key edit.
595
664
  const again = await client['api-keys'][':id'].organization.$put({
596
665
  json: { orgId: validBody.orgId },
597
666
  param: { id: record.id },
@@ -602,7 +671,7 @@ describe('PUT /api-keys/:id/organization', () => {
602
671
  json: { orgId: validBody.orgId },
603
672
  param: { id: record.id },
604
673
  })
605
- expect(patched.status).toBe(403)
674
+ expect(patched.status).toBe(200)
606
675
  })
607
676
 
608
677
  test('rejects unknown owners and projects of another organization', async () => {
@@ -611,7 +680,8 @@ describe('PUT /api-keys/:id/organization', () => {
611
680
  const project = await Projects.create(db, { name: 'Elsewhere', orgId: other.id })
612
681
  const { record } = await core_ApiKeys.mint(store, {
613
682
  name: 'Legacy zone',
614
- scopes: ['zone:421700001:read'],
683
+ scopes: ['zone:read'],
684
+ zoneTags: [421700001],
615
685
  })
616
686
 
617
687
  const unknownOrg = await client['api-keys'][':id'].organization.$put({
@@ -686,14 +756,14 @@ describe('PATCH /api-keys/:id', () => {
686
756
  })
687
757
 
688
758
  const response = await client['api-keys'][':id'].$patch({
689
- json: { scopes: ['management:read', 'zone:421700001:write'] },
759
+ json: { scopes: ['management:read', 'webhooks:write'] },
690
760
  param: { id: record.id },
691
761
  })
692
762
 
693
763
  expect(response.status).toBe(200)
694
764
  expect((await core_ApiKeys.resolve(store, token))?.scopes).toEqual([
695
765
  'management:read',
696
- 'zone:421700001:write',
766
+ 'webhooks:write',
697
767
  ])
698
768
  })
699
769
 
@@ -137,12 +137,10 @@ export namespace schema {
137
137
  z.describe('Replacement per-key quota overrides.'),
138
138
  ),
139
139
  scopes: z.optional(GrantedScopes).check(z.describe('Replacement granted scopes.')),
140
- zoneTags: z
141
- .optional(z.nullable(core_ApiKey.schema.ZoneTags))
142
- .check(
143
- z.describe('Replacement Zone chain id tags, or null to read no Zone.'),
144
- z.meta({ examples: [[421700001]] }),
145
- ),
140
+ zoneTags: z.optional(z.nullable(core_ApiKey.schema.ZoneTags)).check(
141
+ z.describe('Replacement Zone chain id tags, or null to use no Zone. A `zone:write` key keeps every tag within delegated Zones.'), // prettier-ignore
142
+ z.meta({ examples: [[421700001]] }),
143
+ ),
146
144
  }),
147
145
  'Metadata to apply to an API key.',
148
146
  )
@@ -408,7 +406,6 @@ export function apiKeys() {
408
406
  })
409
407
 
410
408
  try {
411
- // Admin rotation returns a fresh secret, so protected Zone read keys keep their approval quorum until M3.
412
409
  const { record, token } = await ApiKeys.mintBounded(
413
410
  Db.get(c.get('db')),
414
411
  store,
@@ -549,7 +546,7 @@ export function apiKeys() {
549
546
  message: 'API key not found.',
550
547
  status: 404,
551
548
  })
552
- // Keys minted before organizations existed own themselves; every other move keeps its reviewed path.
549
+ // Keys minted before organizations existed own themselves; every other move is an ordinary PATCH.
553
550
  if (record.orgId !== record.id)
554
551
  return Response.error(c, {
555
552
  code: 'organization_assigned',
@@ -82,7 +82,7 @@ export namespace schema {
82
82
  .optional(z.string().check(z.maxLength(1024)))
83
83
  .check(
84
84
  z.describe('Literal admin API path prefix.'),
85
- z.meta({ examples: ['/zone-key-requests'] }),
85
+ z.meta({ examples: ['/zone-delegations'] }),
86
86
  ),
87
87
  requestId: z
88
88
  .optional(z.string().check(z.maxLength(256)))
@@ -104,9 +104,15 @@ describe('getVerifiedEarnVault', () => {
104
104
  TestApp.json(response, App.schema.getVerifiedEarnVault.Response),
105
105
  TestApp.json(publicResponse, Earn.schema.getEarnVault.Response),
106
106
  ])
107
- // Public vault fields stay identical; earnings configuration is admin-only.
107
+ // Public vault fields stay identical; curated branding and earnings are admin-only.
108
108
  expect(publicVault.meta).toBeUndefined()
109
- expect(vault).toStrictEqual({ ...publicVault, earnings: null })
109
+ expect(vault).toStrictEqual({
110
+ ...publicVault,
111
+ description: null,
112
+ earnings: null,
113
+ label: publicVault.shareToken.name,
114
+ slug: null,
115
+ })
110
116
  expect({
111
117
  description: vault.description,
112
118
  slug: vault.slug,
@@ -161,25 +167,26 @@ describe('listVerifiedEarnVaults', () => {
161
167
  })
162
168
 
163
169
  test.runIf(Runtime.get().mode === 'testnet')(
164
- 'matches the public verified collection',
170
+ 'matches the public vault fields',
165
171
  async () => {
166
172
  const db = TestApp.database()
167
- await core_EarnVaults.upsert(db, TestEarn.verifiedVault)
173
+ const record = await core_EarnVaults.upsert(db, TestEarn.verifiedVault)
168
174
  const { app } = TestAdmin.setup({ db, zones: [TestEarn.zone] })
169
175
  const publicApp = TestApp.create({ auth: false, db, zones: [TestEarn.zone] })
170
- const query = `?chainId=${tempoTestnet.id}&include=access,capabilities,zone&limit=5`
176
+ const query = `?chainId=${tempoTestnet.id}&include=access,capabilities,zone`
171
177
  const [response, publicResponse] = await Promise.all([
172
- app.request(`/earn/verified-vaults${query}`),
173
- publicApp.request(`/v1/earn/vaults/verified${query}`),
178
+ app.request(`/earn/verified-vaults${query}&limit=5`),
179
+ publicApp.request(`/v1/earn/vaults/${TestEarn.verifiedVault.vaultAddress}${query}`),
174
180
  ])
175
181
  expect([response.status, publicResponse.status]).toEqual([200, 200])
176
- const [body, publicBody] = await Promise.all([
182
+ const [body, publicVault] = await Promise.all([
177
183
  TestApp.json(response, App.schema.listVerifiedEarnVaults.Response),
178
- TestApp.json(publicResponse, Earn.schema.getVerifiedEarnVaults.Response),
184
+ TestApp.json(publicResponse, Earn.schema.getEarnVault.Response),
179
185
  ])
186
+ const { description, label, slug } = record
180
187
  expect(body).toStrictEqual({
181
- ...publicBody,
182
- data: publicBody.data.map((vault) => ({ ...vault, earnings: null })),
188
+ data: [{ ...publicVault, description, earnings: null, label, slug }],
189
+ nextCursor: null,
183
190
  })
184
191
  },
185
192
  90_000,
@@ -934,14 +941,7 @@ describe('deleteVerifiedEarnVault', () => {
934
941
  )
935
942
  expect(publicResponse.status).toBe(200)
936
943
  const vault = await TestApp.json(publicResponse, Earn.schema.getEarnVault.Response)
937
- expect({
938
- description: vault.description,
939
- slug: vault.slug,
940
- verified: vault.verified,
941
- zone: vault.zone,
942
- }).toStrictEqual({
943
- description: null,
944
- slug: null,
944
+ expect({ verified: vault.verified, zone: vault.zone }).toStrictEqual({
945
945
  verified: false,
946
946
  zone: null,
947
947
  })
@@ -38,7 +38,7 @@ export namespace schema {
38
38
  })
39
39
 
40
40
  /** One Earn vault with its private accounting configuration. */
41
- export const Vault = z.intersection(Earn.schema.Vault, earnings)
41
+ export const Vault = z.intersection(Earn.schema.CuratedVault, earnings)
42
42
 
43
43
  /** One registry-curated Earn vault with its accounting configuration. */
44
44
  export const VerifiedVault = z.intersection(Earn.schema.VerifiedVault, earnings)
@@ -46,12 +46,12 @@ export namespace schema {
46
46
  /** Schemas for the listVerifiedEarnVaults operation. */
47
47
  export namespace listVerifiedEarnVaults {
48
48
  /** Query parameters for verified Earn vaults, without the public rate window. */
49
- export const Query = Earn.schema.getVerifiedEarnVaults.BaseQuery
49
+ export const Query = Earn.schema.VaultCollectionQuery
50
50
 
51
51
  /** Paginated verified Earn vaults. */
52
52
  export const Response = z.object({
53
53
  data: z.array(VerifiedVault),
54
- nextCursor: Earn.schema.getVerifiedEarnVaults.Response.shape.nextCursor,
54
+ nextCursor: Schema.NextCursor,
55
55
  })
56
56
  }
57
57
 
@@ -518,7 +518,7 @@ export namespace schema {
518
518
  z
519
519
  .extend(Distributions.schema.Recipient, {
520
520
  firstRegisteredAt: z
521
- .nullable(z.iso.datetime())
521
+ .nullable(Schema.dateTime())
522
522
  .check(
523
523
  z.describe(
524
524
  'First recorded registration time, independent of payment evidence.',
@@ -1611,7 +1611,13 @@ async function serializeVault(
1611
1611
  zoneRoutes: options.zoneRoutes,
1612
1612
  zones: c.get('zones'),
1613
1613
  })
1614
- return { ...vault, earnings: options.record?.earnings ?? null }
1614
+ return {
1615
+ ...vault,
1616
+ description: options.record?.description ?? null,
1617
+ earnings: options.record?.earnings ?? null,
1618
+ label: options.record?.label ?? shareToken.name,
1619
+ slug: options.record?.slug ?? null,
1620
+ }
1615
1621
  }
1616
1622
 
1617
1623
  declare namespace serializeVault {