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
@@ -1,12 +1,9 @@
1
- import * as ApiKeys from '../../ApiKeys.js'
2
- import * as ZoneKeyApproval from '../../internal/ZoneKeyApproval.js'
3
- import * as Store from '../../internal/Store.js'
1
+ import * as ZoneDelegationApproval from '../../internal/ZoneDelegationApproval.js'
4
2
  import * as TestApp from '../../../test/App.js'
5
- import * as Requests from './zoneKeyRequests.js'
6
- import * as ApiKeyAdmissions from './apiKeyAdmissions.js'
3
+ import * as Requests from './zoneDelegationRequests.js'
7
4
 
8
5
  // Sessions outlive the approval lifetime so tests can isolate each bound.
9
- const expiresAt = new Date(Date.now() + 2 * ZoneKeyApproval.approvalLifetime).toISOString()
6
+ const expiresAt = new Date(Date.now() + 2 * ZoneDelegationApproval.approvalLifetime).toISOString()
10
7
  const requester = {
11
8
  email: 'requester@tempo.xyz',
12
9
  eligible: false,
@@ -17,17 +14,17 @@ const first = { email: 'first@tempo.xyz', eligible: true, expiresAt, id: 'employ
17
14
  const second = { email: 'second@tempo.xyz', eligible: true, expiresAt, id: 'employee_second' }
18
15
  const groupId = 'app-tempo-api-zone-issuers'
19
16
  const input = {
20
- allowedIps: ['203.0.113.7'],
17
+ accountsAll: true,
18
+ chainId: 421_700_001,
21
19
  environment: 'production' as const,
22
- name: 'Zone reader',
23
20
  orgId: 'org_fixture',
24
- scopes: ['zone:421700001:read'],
21
+ tokensAll: true,
25
22
  }
26
23
 
27
24
  describe('get', () => {
28
25
  test('reads only the requested approvals and returns null for a missing request', async () => {
29
26
  const db = TestApp.database()
30
- expect(await Requests.get(db, 'zkr_missing')).toBeNull()
27
+ expect(await Requests.get(db, 'zdr_missing')).toBeNull()
31
28
  const request = await Requests.create(db, { groupId, input, requester })
32
29
  expect((await Requests.get(db, request.id))?.approvals).toEqual([])
33
30
  const other = await Requests.create(db, { groupId, input, requester })
@@ -57,7 +54,7 @@ describe('approve', () => {
57
54
  lookup: async () => users,
58
55
  member: first,
59
56
  }),
60
- ).rejects.toThrow(ZoneKeyApproval.RequiredError)
57
+ ).rejects.toThrow(ZoneDelegationApproval.RequiredError)
61
58
  await expect(
62
59
  Requests.approve(db, {
63
60
  groupId,
@@ -83,7 +80,7 @@ describe('approve', () => {
83
80
  ])
84
81
  await expect(
85
82
  Requests.approve(db, { lookup, groupId, id: request.id, member }),
86
- ).rejects.toThrow(ZoneKeyApproval.RequiredError)
83
+ ).rejects.toThrow(ZoneDelegationApproval.RequiredError)
87
84
  await Requests.approve(db, { lookup, groupId, id: request.id, member: first })
88
85
  await Requests.approve(db, {
89
86
  lookup,
@@ -113,7 +110,7 @@ describe('claim', () => {
113
110
  lookup: () => lookup([requester.id, first.id, first.id, 'employee_unrecorded']),
114
111
  member: requester,
115
112
  }),
116
- ).rejects.toThrow(ZoneKeyApproval.RequiredError)
113
+ ).rejects.toThrow(ZoneDelegationApproval.RequiredError)
117
114
  expect((await Requests.get(db, request.id))?.status).toBe('pending')
118
115
  })
119
116
 
@@ -137,7 +134,7 @@ describe('claim', () => {
137
134
  lookup: async () => users,
138
135
  member: requester,
139
136
  }),
140
- ).rejects.toThrow(ZoneKeyApproval.RequiredError)
137
+ ).rejects.toThrow(ZoneDelegationApproval.RequiredError)
141
138
  expect((await Requests.get(db, request.id))?.status).toBe('pending')
142
139
  }
143
140
  await expect(
@@ -150,7 +147,7 @@ describe('claim', () => {
150
147
  member: requester,
151
148
  }),
152
149
  ).rejects.toThrow('Directory unavailable')
153
- expect((await Requests.get(db, request.id))?.keyId).toBeNull()
150
+ expect((await Requests.get(db, request.id))?.status).toBe('pending')
154
151
  await expect(
155
152
  Requests.claim(db, { groupId, id: request.id, lookup, member: requester }),
156
153
  ).resolves.toMatchObject({ input })
@@ -171,11 +168,11 @@ describe('claim', () => {
171
168
  id: request.id,
172
169
  member: requester,
173
170
  lookup: async (ids) => {
174
- vi.setSystemTime(now + ZoneKeyApproval.approvalLifetime)
171
+ vi.setSystemTime(now + ZoneDelegationApproval.approvalLifetime)
175
172
  return lookup(ids)
176
173
  },
177
174
  }),
178
- ).rejects.toThrow(ZoneKeyApproval.RequiredError)
175
+ ).rejects.toThrow(ZoneDelegationApproval.RequiredError)
179
176
  expect((await Requests.get(db, request.id))?.status).toBe('pending')
180
177
  } finally {
181
178
  vi.useRealTimers()
@@ -197,11 +194,11 @@ describe('claim', () => {
197
194
  short.expiresAt,
198
195
  )
199
196
  expect(stored?.approvals.find((a) => a.approverId === second.id)?.expiresAt).toBe(
200
- new Date(now + ZoneKeyApproval.approvalLifetime).toISOString(),
197
+ new Date(now + ZoneDelegationApproval.approvalLifetime).toISOString(),
201
198
  )
202
199
  vi.setSystemTime(now + 30_000)
203
200
  const claim = { lookup, groupId, id: request.id, member: requester }
204
- await expect(Requests.claim(db, claim)).rejects.toThrow(ZoneKeyApproval.RequiredError)
201
+ await expect(Requests.claim(db, claim)).rejects.toThrow(ZoneDelegationApproval.RequiredError)
205
202
  await Requests.approve(db, { lookup, groupId, id: request.id, member: first })
206
203
  expect((await Requests.get(db, request.id))?.approvals).toHaveLength(2)
207
204
  await expect(Requests.claim(db, claim)).resolves.toMatchObject({ input })
@@ -220,13 +217,13 @@ describe('claim', () => {
220
217
  for (const member of [first, second])
221
218
  await Requests.approve(db, { lookup, groupId, id: request.id, member })
222
219
  expect((await Requests.get(db, request.id))?.approvals.map((a) => a.expiresAt)).toEqual([
223
- new Date(now + ZoneKeyApproval.approvalLifetime).toISOString(),
224
- new Date(now + ZoneKeyApproval.approvalLifetime).toISOString(),
220
+ new Date(now + ZoneDelegationApproval.approvalLifetime).toISOString(),
221
+ new Date(now + ZoneDelegationApproval.approvalLifetime).toISOString(),
225
222
  ])
226
- vi.setSystemTime(now + ZoneKeyApproval.approvalLifetime)
223
+ vi.setSystemTime(now + ZoneDelegationApproval.approvalLifetime)
227
224
  await expect(
228
225
  Requests.claim(db, { lookup, groupId, id: request.id, member: requester }),
229
- ).rejects.toThrow(ZoneKeyApproval.RequiredError)
226
+ ).rejects.toThrow(ZoneDelegationApproval.RequiredError)
230
227
  expect((await Requests.get(db, request.id))?.status).toBe('pending')
231
228
  } finally {
232
229
  vi.useRealTimers()
@@ -237,9 +234,9 @@ describe('claim', () => {
237
234
  const db = TestApp.database()
238
235
  const request = await Requests.create(db, { groupId, input, requester })
239
236
  const claim = { lookup, groupId, id: request.id, member: requester }
240
- await expect(Requests.claim(db, claim)).rejects.toThrow(ZoneKeyApproval.RequiredError)
237
+ await expect(Requests.claim(db, claim)).rejects.toThrow(ZoneDelegationApproval.RequiredError)
241
238
  await Requests.approve(db, { lookup, groupId, id: request.id, member: first })
242
- await expect(Requests.claim(db, claim)).rejects.toThrow(ZoneKeyApproval.RequiredError)
239
+ await expect(Requests.claim(db, claim)).rejects.toThrow(ZoneDelegationApproval.RequiredError)
243
240
  await Requests.approve(db, { lookup, groupId, id: request.id, member: second })
244
241
  for (const options of [
245
242
  { ...claim, member: { ...requester, id: 'employee_recreated' } },
@@ -248,14 +245,15 @@ describe('claim', () => {
248
245
  { ...claim, member: null },
249
246
  { ...claim, groupId: 'replacement-group' },
250
247
  ])
251
- await expect(Requests.claim(db, options)).rejects.toThrow(ZoneKeyApproval.RequiredError)
248
+ await expect(Requests.claim(db, options)).rejects.toThrow(
249
+ ZoneDelegationApproval.RequiredError,
250
+ )
252
251
  const claimed = await Requests.claim(db, claim)
253
252
  expect(claimed.input).toEqual(input)
254
- expect(claimed.keyId.startsWith('key_')).toBe(true)
255
- await expect(Requests.claim(db, claim)).rejects.toThrow(ZoneKeyApproval.RequiredError)
253
+ await expect(Requests.claim(db, claim)).rejects.toThrow(ZoneDelegationApproval.RequiredError)
256
254
  })
257
255
 
258
- test('allows only one concurrent claim and retains the reserved key id', async () => {
256
+ test('allows only one concurrent claim and never replays a finished one', async () => {
259
257
  const factory = TestApp.databaseFactory()
260
258
  const db = factory()
261
259
  const request = await Requests.create(db, { groupId, input, requester })
@@ -273,19 +271,19 @@ describe('claim', () => {
273
271
  ]
274
272
  `)
275
273
  const stored = await Requests.get(db, request.id)
276
- expect(stored?.status).toBe('issuing')
277
- expect(stored?.keyId).toBeTruthy()
278
- await Requests.finish(db, request.id, 'failed')
279
- await expect(Requests.claim(db, options)).rejects.toThrow(ZoneKeyApproval.RequiredError)
274
+ expect(stored?.status).toBe('applying')
275
+ await Requests.finish(db, request.id, { status: 'failed' })
276
+ expect((await Requests.get(db, request.id))?.status).toBe('failed')
277
+ await expect(Requests.claim(db, options)).rejects.toThrow(ZoneDelegationApproval.RequiredError)
280
278
  })
281
279
 
282
- test('cancellation prevents approval and issuance', async () => {
280
+ test('cancellation prevents approval and application', async () => {
283
281
  const db = TestApp.database()
284
282
  const request = await Requests.create(db, { groupId, input, requester })
285
283
  await Requests.cancel(db, request.id)
286
284
  await expect(
287
285
  Requests.approve(db, { lookup, groupId, id: request.id, member: first }),
288
- ).rejects.toThrow(ZoneKeyApproval.RequiredError)
286
+ ).rejects.toThrow(ZoneDelegationApproval.RequiredError)
289
287
  await expect(
290
288
  Requests.claim(db, {
291
289
  lookup,
@@ -293,7 +291,7 @@ describe('claim', () => {
293
291
  id: request.id,
294
292
  member: requester,
295
293
  }),
296
- ).rejects.toThrow(ZoneKeyApproval.RequiredError)
294
+ ).rejects.toThrow(ZoneDelegationApproval.RequiredError)
297
295
  })
298
296
 
299
297
  test('requests expire after 24 hours', async () => {
@@ -304,53 +302,14 @@ describe('claim', () => {
304
302
  vi.setSystemTime(new Date(Date.parse(request.expiresAt) + 1))
305
303
  await expect(
306
304
  Requests.approve(db, { lookup, groupId, id: request.id, member: first }),
307
- ).rejects.toThrow(ZoneKeyApproval.RequiredError)
305
+ ).rejects.toThrow(ZoneDelegationApproval.RequiredError)
308
306
  } finally {
309
307
  vi.useRealTimers()
310
308
  }
311
309
  })
312
310
  })
313
311
 
314
- describe('direct issuance', () => {
315
- test('does not publish a protected scope intent through an ordinary update', async () => {
316
- const db = TestApp.database()
317
- const store = Store.memory()
318
- const { record } = await ApiKeys.mintBounded(db, store, { orgId: 'org_fixture', scopes: [] })
319
- await db.transaction(async (tx) => {
320
- await ApiKeyAdmissions.lock(tx, record.id)
321
- await ApiKeyAdmissions.setPendingScopes(tx, record.id, ['*'])
322
- })
323
- await expect(ApiKeys.updateBounded(db, store, record.id, { name: 'Changed' })).rejects.toThrow(
324
- ZoneKeyApproval.RequiredError,
325
- )
326
- expect((await ApiKeys.get(store, record.id))?.scopes).toEqual([])
327
- })
328
- test('blocks Zone read and wildcard minting at the shared admission boundary', async () => {
329
- const db = TestApp.database()
330
- const store = Store.memory()
331
- for (const scopes of [['zone:421700001:read'], ['*']])
332
- await expect(ApiKeys.mintBounded(db, store, { scopes })).rejects.toThrow(
333
- ZoneKeyApproval.RequiredError,
334
- )
335
- expect(await ApiKeys.list(store)).toEqual([])
336
- })
337
-
338
- test('blocks elevation and edits to existing protected keys while allowing revocation', async () => {
339
- const db = TestApp.database()
340
- const store = Store.memory()
341
- const plain = await ApiKeys.mint(store, { scopes: ['data:read'] })
342
- const protectedKey = await ApiKeys.mint(store, { scopes: ['zone:421700001:read'] })
343
- await expect(
344
- ApiKeys.updateBounded(db, store, plain.record.id, { scopes: ['*'] }),
345
- ).rejects.toThrow(ZoneKeyApproval.RequiredError)
346
- await expect(
347
- ApiKeys.updateBounded(db, store, protectedKey.record.id, { allowedIps: [] }),
348
- ).rejects.toThrow(ZoneKeyApproval.RequiredError)
349
- expect(await ApiKeys.revokeBounded(db, store, protectedKey.record.id)).toBe(true)
350
- })
351
- })
352
-
353
- async function lookup(ids: readonly string[]): Promise<ZoneKeyApproval.Status[]> {
312
+ async function lookup(ids: readonly string[]): Promise<ZoneDelegationApproval.Status[]> {
354
313
  return ids.map((id) => ({
355
314
  active: true,
356
315
  eligible: id !== 'employee_requester' && id !== 'employee_nonmember',
@@ -1,34 +1,37 @@
1
1
  import type { JSONColumnType } from 'kysely'
2
2
  import { jsonArrayFrom } from 'kysely/helpers/postgres'
3
3
 
4
- import * as ApiKey from '../../ApiKey.js'
5
4
  import * as Cursor from '../../internal/Cursor.js'
6
5
  import * as Id from '../../internal/Id.js'
7
- import * as ZoneKeyApproval from '../../internal/ZoneKeyApproval.js'
6
+ import * as ZoneDelegationApproval from '../../internal/ZoneDelegationApproval.js'
8
7
  import type * as Db from '../Db.js'
9
8
  import type * as Schema from '../Schema.js'
9
+ import type * as ZoneDelegations from './zoneDelegations.js'
10
10
 
11
- /** Persisted immutable request, without plaintext credentials. */
12
- export type Table = Omit<Schema.ZoneKeyRequest, 'input'> & {
13
- /** Validated settings persisted as JSON, never a plaintext credential. */
14
- input: JSONColumnType<Schema.ZoneKeyRequest['input']>
11
+ /** Settings a request asks approvers to review: the delegation to create. */
12
+ export type Input = ZoneDelegations.create.Input
13
+
14
+ /** Persisted immutable request for one Zone delegation. */
15
+ export type Table = Omit<Schema.ZoneDelegationRequest, 'input'> & {
16
+ /** Validated delegation settings persisted as JSON. */
17
+ input: JSONColumnType<Schema.ZoneDelegationRequest['input']>
15
18
  }
16
19
 
17
20
  /** One unique approver's decision. */
18
- export type ApprovalTable = Schema.ZoneKeyApproval
21
+ export type ApprovalTable = Schema.ZoneDelegationApproval
19
22
 
20
- /** Stores an immutable issuance request that expires after 24 hours. */
23
+ /** Stores an immutable delegation request that expires after 24 hours. */
21
24
  export async function create(db: Db.Db, options: create.Options) {
22
25
  const now = new Date()
23
26
  return db.kysely
24
- .insertInto('zone_key_requests')
27
+ .insertInto('zone_delegation_requests')
25
28
  .values({
26
29
  createdAt: now.toISOString(),
30
+ delegationId: null,
27
31
  expiresAt: new Date(now.getTime() + 86_400_000).toISOString(),
28
32
  groupId: options.groupId,
29
- id: Id.generate('zkr'),
33
+ id: Id.generate('zdr'),
30
34
  input: JSON.stringify(options.input),
31
- keyId: null,
32
35
  requesterEmail: options.requester.email,
33
36
  requesterId: options.requester.id,
34
37
  status: 'pending',
@@ -42,10 +45,10 @@ export declare namespace create {
42
45
  type Options = {
43
46
  /** Approver group pinned for this request. */
44
47
  groupId: string
45
- /** Exact key settings reviewed by approvers. */
46
- input: Schema.ZoneKeyRequest['input']
48
+ /** Exact delegation settings reviewed by approvers. */
49
+ input: Schema.ZoneDelegationRequest['input']
47
50
  /** Requester from the verified internal identity session. */
48
- requester: ZoneKeyApproval.Member
51
+ requester: ZoneDelegationApproval.Member
49
52
  }
50
53
  }
51
54
 
@@ -53,14 +56,14 @@ export declare namespace create {
53
56
  export async function get(db: Db.Db, id: string) {
54
57
  return (
55
58
  (await db.kysely
56
- .selectFrom('zone_key_requests')
59
+ .selectFrom('zone_delegation_requests')
57
60
  .selectAll()
58
61
  .select((eb) =>
59
62
  jsonArrayFrom(
60
63
  eb
61
- .selectFrom('zone_key_approvals')
64
+ .selectFrom('zone_delegation_approvals')
62
65
  .selectAll()
63
- .whereRef('requestId', '=', 'zone_key_requests.id')
66
+ .whereRef('requestId', '=', 'zone_delegation_requests.id')
64
67
  .orderBy('approvedAt'),
65
68
  ).as('approvals'),
66
69
  )
@@ -74,7 +77,7 @@ export async function list(db: Db.Db, options: list.Options = {}) {
74
77
  const limit = 50
75
78
  const cursor = options.cursor ? Cursor.decode(options.cursor, ['timestamp', 'id']) : undefined
76
79
  const rows = await db.kysely
77
- .selectFrom('zone_key_requests')
80
+ .selectFrom('zone_delegation_requests')
78
81
  .selectAll()
79
82
  .$if(Boolean(cursor), (query) =>
80
83
  query.where((eb) =>
@@ -99,26 +102,31 @@ export declare namespace list {
99
102
  }
100
103
  }
101
104
 
102
- /** Records one independent approval while serializing with issuance and cancellation. */
105
+ /** Records one independent approval while serializing with application and cancellation. */
103
106
  export async function approve(db: Db.Db, options: approve.Options) {
104
107
  return db.transaction(async (tx) => {
105
108
  const request = await pending(tx, options.id, options.groupId)
106
109
  const member = options.member
107
- if (!ZoneKeyApproval.active(member) || !member.eligible || member.id === request.requesterId)
108
- throw new ZoneKeyApproval.RequiredError(
110
+ if (
111
+ !ZoneDelegationApproval.active(member) ||
112
+ !member.eligible ||
113
+ member.id === request.requesterId
114
+ )
115
+ // prettier-ignore
116
+ throw new ZoneDelegationApproval.RequiredError(
109
117
  'Approval requires an active group member other than the requester.',
110
118
  )
111
119
  const users = await options.lookup([member.id])
112
120
  if (!users.some((user) => user.id === member.id && user.active && user.eligible))
113
- throw new ZoneKeyApproval.RequiredError('Approval requires a current active group member.')
114
- if (!ZoneKeyApproval.active(member) || Date.parse(request.expiresAt) <= Date.now())
115
- throw new ZoneKeyApproval.RequiredError('Approval request or session expired.')
121
+ throw new ZoneDelegationApproval.RequiredError('Approval requires a current active group member.') // prettier-ignore
122
+ if (!ZoneDelegationApproval.active(member) || Date.parse(request.expiresAt) <= Date.now())
123
+ throw new ZoneDelegationApproval.RequiredError('Approval request or session expired.')
116
124
  const now = new Date()
117
125
  const expiresAt = new Date(
118
- Math.min(Date.parse(member.expiresAt), now.getTime() + ZoneKeyApproval.approvalLifetime),
126
+ Math.min(Date.parse(member.expiresAt), now.getTime() + ZoneDelegationApproval.approvalLifetime), // prettier-ignore
119
127
  ).toISOString()
120
128
  await tx.kysely
121
- .insertInto('zone_key_approvals')
129
+ .insertInto('zone_delegation_approvals')
122
130
  .values({
123
131
  approvedAt: now.toISOString(),
124
132
  approverEmail: member.email,
@@ -146,30 +154,30 @@ export declare namespace approve {
146
154
  /** Request being approved. */
147
155
  id: string
148
156
  /** Fetches current account and approval-group status without caching. */
149
- lookup: ZoneKeyApproval.Lookup
157
+ lookup: ZoneDelegationApproval.Lookup
150
158
  /** Identity from the current verified session. */
151
- member: ZoneKeyApproval.Member | null
159
+ member: ZoneDelegationApproval.Member | null
152
160
  }
153
161
  }
154
162
 
155
- /** Consumes approval once, before external KV writes, and reserves the resulting key id. */
163
+ /** Consumes approval once, before the delegation is written, so a failed write cannot be replayed. */
156
164
  export async function claim(db: Db.Db, options: claim.Options) {
157
165
  return db.transaction(async (tx) => {
158
166
  const request = await pending(tx, options.id, options.groupId)
159
167
  const requester = options.member
160
- if (!ZoneKeyApproval.active(requester) || requester.id !== request.requesterId)
161
- throw new ZoneKeyApproval.RequiredError(
162
- 'Only the original active requester can issue this key.',
168
+ if (!ZoneDelegationApproval.active(requester) || requester.id !== request.requesterId)
169
+ throw new ZoneDelegationApproval.RequiredError(
170
+ 'Only the original active requester can apply this delegation.',
163
171
  )
164
172
  const approvals = await tx.kysely
165
- .selectFrom('zone_key_approvals')
173
+ .selectFrom('zone_delegation_approvals')
166
174
  .selectAll()
167
175
  .where('requestId', '=', request.id)
168
176
  .where('approverId', '!=', requester.id)
169
177
  .where('expiresAt', '>', new Date().toISOString())
170
178
  .execute()
171
- if (approvals.length < ZoneKeyApproval.quorum)
172
- throw new ZoneKeyApproval.RequiredError(
179
+ if (approvals.length < ZoneDelegationApproval.quorum)
180
+ throw new ZoneDelegationApproval.RequiredError(
173
181
  'Two distinct, unexpired group approvals are required.',
174
182
  )
175
183
  // Keep the request locked while revalidating the requester and recorded approvers.
@@ -178,25 +186,24 @@ export async function claim(db: Db.Db, options: claim.Options) {
178
186
  ...approvals.map((approval) => approval.approverId),
179
187
  ])
180
188
  if (!users.some((user) => user.id === requester.id && user.active))
181
- throw new ZoneKeyApproval.RequiredError('The requester is no longer active.')
189
+ throw new ZoneDelegationApproval.RequiredError('The requester is no longer active.')
182
190
  const current = new Set(
183
191
  users.filter((user) => user.active && user.eligible).map((user) => user.id),
184
192
  )
185
193
  const valid = approvals.filter(
186
194
  (approval) => current.has(approval.approverId) && Date.parse(approval.expiresAt) > Date.now(),
187
195
  )
188
- if (valid.length < ZoneKeyApproval.quorum)
189
- throw new ZoneKeyApproval.RequiredError('Two current active group approvals are required.')
196
+ if (valid.length < ZoneDelegationApproval.quorum)
197
+ throw new ZoneDelegationApproval.RequiredError('Two current active group approvals are required.') // prettier-ignore
190
198
  // Lookup latency must not extend the request, session, or approval lifetime.
191
- if (!ZoneKeyApproval.active(requester) || Date.parse(request.expiresAt) <= Date.now())
192
- throw new ZoneKeyApproval.RequiredError('Approval request expired.')
193
- const keyId = ApiKey.generateId()
199
+ if (!ZoneDelegationApproval.active(requester) || Date.parse(request.expiresAt) <= Date.now())
200
+ throw new ZoneDelegationApproval.RequiredError('Approval request expired.')
194
201
  await tx.kysely
195
- .updateTable('zone_key_requests')
196
- .set({ keyId, status: 'issuing' })
202
+ .updateTable('zone_delegation_requests')
203
+ .set({ status: 'applying' })
197
204
  .where('id', '=', request.id)
198
205
  .execute()
199
- return { ...request, keyId }
206
+ return request
200
207
  })
201
208
  }
202
209
 
@@ -205,20 +212,30 @@ export declare namespace claim {
205
212
  type Options = approve.Options
206
213
  }
207
214
 
208
- /** Records the terminal issuance outcome; a failed or interrupted claim cannot be replayed. */
209
- export async function finish(db: Db.Db, id: string, status: 'issued' | 'failed') {
215
+ /** Records the terminal outcome; a failed or interrupted claim cannot be replayed. */
216
+ export async function finish(db: Db.Db, id: string, outcome: finish.Outcome) {
210
217
  await db.kysely
211
- .updateTable('zone_key_requests')
212
- .set({ status })
218
+ .updateTable('zone_delegation_requests')
219
+ .set({ delegationId: outcome.delegationId ?? null, status: outcome.status })
213
220
  .where('id', '=', id)
214
- .where('status', '=', 'issuing')
221
+ .where('status', '=', 'applying')
215
222
  .execute()
216
223
  }
217
224
 
225
+ export declare namespace finish {
226
+ /** How the claimed request ended. */
227
+ type Outcome = {
228
+ /** Delegation the request created, when applied. */
229
+ delegationId?: string | undefined
230
+ /** Terminal status. */
231
+ status: 'applied' | 'failed'
232
+ }
233
+ }
234
+
218
235
  /** Cancels a pending request without needing quorum. */
219
236
  export async function cancel(db: Db.Db, id: string) {
220
237
  return db.kysely
221
- .updateTable('zone_key_requests')
238
+ .updateTable('zone_delegation_requests')
222
239
  .set({ status: 'cancelled' })
223
240
  .where('id', '=', id)
224
241
  .where('status', '=', 'pending')
@@ -229,7 +246,7 @@ export async function cancel(db: Db.Db, id: string) {
229
246
  /** Locks and validates the request before a state transition. */
230
247
  async function pending(db: Db.Db, id: string, groupId: string) {
231
248
  const request = await db.kysely
232
- .selectFrom('zone_key_requests')
249
+ .selectFrom('zone_delegation_requests')
233
250
  .selectAll()
234
251
  .where('id', '=', id)
235
252
  .forUpdate()
@@ -240,7 +257,7 @@ async function pending(db: Db.Db, id: string, groupId: string) {
240
257
  request.groupId !== groupId ||
241
258
  Date.parse(request.expiresAt) <= Date.now()
242
259
  )
243
- throw new ZoneKeyApproval.RequiredError(
260
+ throw new ZoneDelegationApproval.RequiredError(
244
261
  'Request is missing, expired, consumed, cancelled, or belongs to a different approver group.',
245
262
  )
246
263
  return request
@@ -26,7 +26,6 @@ describe('create', () => {
26
26
  "chainId": 421700001,
27
27
  "environment": "production",
28
28
  "orgId": "org_zd",
29
- "projects": "all",
30
29
  "tokensAll": true,
31
30
  }
32
31
  `)
@@ -58,13 +57,13 @@ describe('create', () => {
58
57
  })
59
58
 
60
59
  describe('update', () => {
61
- test('changes flags and projects of an active delegation only', async () => {
60
+ test('changes flags of an active delegation only', async () => {
62
61
  const db = TestApp.database()
63
62
  await Organizations.create(db, { id: 'org_up', name: 'Update' })
64
- const input = { accountsAll: true, chainId, environment: 'production', orgId: 'org_up', projects: 'all', tokensAll: true } as const // prettier-ignore
63
+ const input = { accountsAll: true, chainId, environment: 'production', orgId: 'org_up', tokensAll: true } as const // prettier-ignore
65
64
  const created = await ZoneDelegations.create(db, input)
66
- const updated = await ZoneDelegations.update(db, created.id, { accountsAll: false, projects: ['prj_1'] }) // prettier-ignore
67
- expect([updated?.id === created.id, updated?.accountsAll, updated?.projects, updated?.tokensAll]).toEqual([true, false, ['prj_1'], true]) // prettier-ignore
65
+ const updated = await ZoneDelegations.update(db, created.id, { accountsAll: false })
66
+ expect([updated?.id === created.id, updated?.accountsAll, updated?.tokensAll]).toEqual([true, false, true]) // prettier-ignore
68
67
  await ZoneDelegations.revoke(db, created.id)
69
68
  expect(await ZoneDelegations.update(db, created.id, { accountsAll: true })).toBeUndefined()
70
69
  expect(await ZoneDelegations.update(db, 'zd_missing', { accountsAll: true })).toBeUndefined()
@@ -119,7 +118,7 @@ describe('Members', () => {
119
118
  test('pages by address with a cursor', async () => {
120
119
  const db = TestApp.database()
121
120
  await Organizations.create(db, { id: 'org_p', name: 'Pages' })
122
- const created = await ZoneDelegations.create(db, { accountsAll: false, chainId, environment: 'sandbox', orgId: 'org_p', projects: 'all', tokensAll: true }) // prettier-ignore
121
+ const created = await ZoneDelegations.create(db, { accountsAll: false, chainId, environment: 'sandbox', orgId: 'org_p', tokensAll: true }) // prettier-ignore
123
122
  const addresses = Array.from({ length: 150 }, (_, i) => `0x${i.toString(16).padStart(40, '0')}`)
124
123
  await ZoneDelegations.Members.add(db, { addresses, id: created.id, kind: 'account' })
125
124
  const first = await ZoneDelegations.Members.list(db, { id: created.id, kind: 'account' }) // prettier-ignore
@@ -17,8 +17,8 @@ export type Table = Omit<Schema.ZoneDelegation, 'chainId' | 'projects'> & {
17
17
  /** Columns of the `zone_delegation_members` table. */
18
18
  export type MemberTable = Schema.ZoneDelegationMember
19
19
 
20
- /** A stored delegation; a `null` revocation reads as absent. */
21
- export type Record = Omit<Schema.ZoneDelegation, 'revokedAt'> & {
20
+ /** A stored delegation; a `null` revocation reads as absent. The retired `projects` column is not surfaced. */
21
+ export type Record = Omit<Schema.ZoneDelegation, 'projects' | 'revokedAt'> & {
22
22
  /** When the delegation was revoked (ISO 8601); absent while active. */
23
23
  revokedAt?: string | undefined
24
24
  }
@@ -36,7 +36,7 @@ export type Scope = Pick<Record, 'chainId' | 'environment' | 'orgId'>
36
36
  export type Owner = Pick<Record, 'environment' | 'orgId'>
37
37
 
38
38
  /** Coverage settings on the delegation row itself. */
39
- export type Coverage = Pick<Record, 'accountsAll' | 'projects' | 'tokensAll'>
39
+ export type Coverage = Pick<Record, 'accountsAll' | 'tokensAll'>
40
40
 
41
41
  /** Creates an active delegation with optional initial members; an active one for the same Zone is a conflict. */
42
42
  export function create(db: Db.Db, input: create.Input): Promise<Record> {
@@ -164,7 +164,6 @@ export async function update(
164
164
  .updateTable('zone_delegations')
165
165
  .set({
166
166
  ...(patch.accountsAll === undefined ? {} : { accountsAll: patch.accountsAll }),
167
- ...(patch.projects === undefined ? {} : { projects: JSON.stringify(patch.projects) }),
168
167
  ...(patch.tokensAll === undefined ? {} : { tokensAll: patch.tokensAll }),
169
168
  updatedAt: new Date().toISOString(),
170
169
  })
@@ -180,8 +179,6 @@ export declare namespace update {
180
179
  type Patch = {
181
180
  /** Whether every account is covered. */
182
181
  accountsAll?: boolean | undefined
183
- /** Covered projects (`all` or a list of ids). */
184
- projects?: ZoneDelegation.Selection | undefined
185
182
  /** Whether every token is covered. */
186
183
  tokensAll?: boolean | undefined
187
184
  }
@@ -217,6 +214,25 @@ export namespace Members {
217
214
  })
218
215
  }
219
216
 
217
+ /**
218
+ * Adds members only while the list's flag is `all`, so the add changes no live
219
+ * access; `widens` when the list is enforced. The row stays locked through the
220
+ * insert, so a concurrent narrowing cannot turn the add into a widening.
221
+ */
222
+ export function addInert(
223
+ db: Db.Db,
224
+ options: Options,
225
+ ): Promise<Mutation<readonly Member[]> | { status: 'widens' }> {
226
+ return db.transaction(async (tx) => {
227
+ const now = new Date().toISOString()
228
+ const claimed = await claim(tx, options.id, now)
229
+ if (claimed.status !== 'ok') return claimed
230
+ if (!claimed.all[options.kind]) return { status: 'widens' } as const
231
+ const data = await insertMembers(tx, { ...options, now })
232
+ return { all: true, data, status: 'ok' }
233
+ })
234
+ }
235
+
220
236
  /** Removes active members and returns the addresses removed. */
221
237
  export function remove(db: Db.Db, options: Options): Promise<Mutation<readonly string[]>> {
222
238
  return db.transaction(async (tx) => {
@@ -370,7 +386,8 @@ function storage(input: ensure.Input, now: string) {
370
386
  environment: input.environment,
371
387
  id: Id.generate('zd'),
372
388
  orgId: input.orgId,
373
- projects: JSON.stringify(input.projects),
389
+ // The column stays NOT NULL until a later cleanup drops it; every row covers every project.
390
+ projects: JSON.stringify('all'),
374
391
  revokedAt: null,
375
392
  tokensAll: input.tokensAll,
376
393
  updatedAt: now,
@@ -378,7 +395,7 @@ function storage(input: ensure.Input, now: string) {
378
395
  }
379
396
 
380
397
  function domain(row: Selectable<Table>): Record {
381
- const { revokedAt, ...rest } = row
398
+ const { projects: _projects, revokedAt, ...rest } = row
382
399
  return {
383
400
  ...rest,
384
401
  chainId: Number(row.chainId),