tapimo 0.11.0 → 0.12.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 (339) hide show
  1. package/dist/App.d.ts +2296 -1010
  2. package/dist/App.d.ts.map +1 -1
  3. package/dist/App.js +2 -2
  4. package/dist/App.js.map +1 -1
  5. package/dist/Assets.d.ts +15 -0
  6. package/dist/Assets.d.ts.map +1 -1
  7. package/dist/Assets.js +7 -0
  8. package/dist/Assets.js.map +1 -1
  9. package/dist/admin/App.d.ts +53 -4
  10. package/dist/admin/App.d.ts.map +1 -1
  11. package/dist/admin/apps/api-keys.d.ts +4 -4
  12. package/dist/admin/apps/earn-vaults.d.ts +114 -0
  13. package/dist/admin/apps/earn-vaults.d.ts.map +1 -1
  14. package/dist/admin/apps/earn-vaults.js +59 -6
  15. package/dist/admin/apps/earn-vaults.js.map +1 -1
  16. package/dist/admin/apps/organizations.d.ts.map +1 -1
  17. package/dist/admin/apps/organizations.js +4 -2
  18. package/dist/admin/apps/organizations.js.map +1 -1
  19. package/dist/admin/apps/verified-tokens.d.ts +9 -9
  20. package/dist/admin/ui.generated.d.ts +1 -1
  21. package/dist/admin/ui.generated.d.ts.map +1 -1
  22. package/dist/admin/ui.generated.js +151 -151
  23. package/dist/admin/ui.generated.js.map +1 -1
  24. package/dist/apps/data/App.d.ts +1699 -749
  25. package/dist/apps/data/App.d.ts.map +1 -1
  26. package/dist/apps/data/App.js +56 -7
  27. package/dist/apps/data/App.js.map +1 -1
  28. package/dist/apps/data/ZoneSelection.d.ts +62 -0
  29. package/dist/apps/data/ZoneSelection.d.ts.map +1 -0
  30. package/dist/apps/data/ZoneSelection.js +44 -0
  31. package/dist/apps/data/ZoneSelection.js.map +1 -0
  32. package/dist/apps/data/routes/activities.d.ts +2367 -4
  33. package/dist/apps/data/routes/activities.d.ts.map +1 -1
  34. package/dist/apps/data/routes/activities.js +368 -87
  35. package/dist/apps/data/routes/activities.js.map +1 -1
  36. package/dist/apps/data/routes/addresses.d.ts +471 -340
  37. package/dist/apps/data/routes/addresses.d.ts.map +1 -1
  38. package/dist/apps/data/routes/balances.d.ts +28 -28
  39. package/dist/apps/data/routes/balances.js +1 -1
  40. package/dist/apps/data/routes/balances.js.map +1 -1
  41. package/dist/apps/data/routes/blocks.d.ts +4 -4
  42. package/dist/apps/data/routes/blocks.js +1 -1
  43. package/dist/apps/data/routes/blocks.js.map +1 -1
  44. package/dist/apps/data/routes/coingecko.d.ts +176 -176
  45. package/dist/apps/data/routes/earn.d.ts +131 -6
  46. package/dist/apps/data/routes/earn.d.ts.map +1 -1
  47. package/dist/apps/data/routes/earn.js +157 -25
  48. package/dist/apps/data/routes/earn.js.map +1 -1
  49. package/dist/apps/data/routes/exchanges.d.ts +825 -119
  50. package/dist/apps/data/routes/exchanges.d.ts.map +1 -1
  51. package/dist/apps/data/routes/exchanges.js +16 -13
  52. package/dist/apps/data/routes/exchanges.js.map +1 -1
  53. package/dist/apps/data/routes/fee-amm.d.ts.map +1 -1
  54. package/dist/apps/data/routes/fee-amm.js +9 -11
  55. package/dist/apps/data/routes/fee-amm.js.map +1 -1
  56. package/dist/apps/data/routes/indexer.d.ts +34 -34
  57. package/dist/apps/data/routes/receipts.d.ts +230 -230
  58. package/dist/apps/data/routes/receipts.js +1 -1
  59. package/dist/apps/data/routes/receipts.js.map +1 -1
  60. package/dist/apps/data/routes/rpc.js +24 -10
  61. package/dist/apps/data/routes/rpc.js.map +1 -1
  62. package/dist/apps/data/routes/tokenlist.d.ts.map +1 -1
  63. package/dist/apps/data/routes/tokenlist.js +16 -15
  64. package/dist/apps/data/routes/tokenlist.js.map +1 -1
  65. package/dist/apps/data/routes/tokens.d.ts +14 -0
  66. package/dist/apps/data/routes/tokens.d.ts.map +1 -1
  67. package/dist/apps/data/routes/tokens.js +34 -15
  68. package/dist/apps/data/routes/tokens.js.map +1 -1
  69. package/dist/apps/data/routes/transactions.js +1 -1
  70. package/dist/apps/data/routes/transactions.js.map +1 -1
  71. package/dist/apps/data/routes/transfers.d.ts.map +1 -1
  72. package/dist/apps/data/routes/transfers.js +7 -9
  73. package/dist/apps/data/routes/transfers.js.map +1 -1
  74. package/dist/apps/data/routes/webhooks.d.ts +4 -4
  75. package/dist/apps/data/routes/webhooks.d.ts.map +1 -1
  76. package/dist/apps/data/routes/webhooks.js +2 -2
  77. package/dist/apps/data/routes/webhooks.js.map +1 -1
  78. package/dist/apps/data/routes/zones.d.ts +30 -30
  79. package/dist/apps/funding/App.d.ts +27 -27
  80. package/dist/apps/funding/routes/chains.d.ts.map +1 -1
  81. package/dist/apps/funding/routes/chains.js +5 -4
  82. package/dist/apps/funding/routes/chains.js.map +1 -1
  83. package/dist/apps/funding/routes/deposit-addresses.d.ts +16 -16
  84. package/dist/apps/funding/routes/deposit-addresses.d.ts.map +1 -1
  85. package/dist/apps/funding/routes/deposit-addresses.js +8 -8
  86. package/dist/apps/funding/routes/deposit-addresses.js.map +1 -1
  87. package/dist/apps/funding/routes/providers.d.ts +13 -13
  88. package/dist/apps/funding/routes/providers.d.ts.map +1 -1
  89. package/dist/apps/funding/routes/providers.js +3 -2
  90. package/dist/apps/funding/routes/providers.js.map +1 -1
  91. package/dist/apps/funding/routes/quotes.d.ts.map +1 -1
  92. package/dist/apps/funding/routes/quotes.js +2 -2
  93. package/dist/apps/funding/routes/quotes.js.map +1 -1
  94. package/dist/apps/management/App.d.ts +627 -293
  95. package/dist/apps/management/App.d.ts.map +1 -1
  96. package/dist/apps/management/Billing.d.ts.map +1 -1
  97. package/dist/apps/management/Billing.js +19 -6
  98. package/dist/apps/management/Billing.js.map +1 -1
  99. package/dist/apps/management/routes/api-keys.d.ts +114 -54
  100. package/dist/apps/management/routes/api-keys.d.ts.map +1 -1
  101. package/dist/apps/management/routes/api-keys.js +76 -30
  102. package/dist/apps/management/routes/api-keys.js.map +1 -1
  103. package/dist/apps/management/routes/billing.d.ts +103 -30
  104. package/dist/apps/management/routes/billing.d.ts.map +1 -1
  105. package/dist/apps/management/routes/billing.js +91 -32
  106. package/dist/apps/management/routes/billing.js.map +1 -1
  107. package/dist/apps/management/routes/faucet.d.ts +33 -33
  108. package/dist/apps/management/routes/faucet.d.ts.map +1 -1
  109. package/dist/apps/management/routes/faucet.js +23 -12
  110. package/dist/apps/management/routes/faucet.js.map +1 -1
  111. package/dist/apps/management/routes/invitations.d.ts +46 -13
  112. package/dist/apps/management/routes/invitations.d.ts.map +1 -1
  113. package/dist/apps/management/routes/invitations.js +79 -29
  114. package/dist/apps/management/routes/invitations.js.map +1 -1
  115. package/dist/apps/management/routes/invite-links.d.ts +86 -41
  116. package/dist/apps/management/routes/invite-links.d.ts.map +1 -1
  117. package/dist/apps/management/routes/invite-links.js +100 -41
  118. package/dist/apps/management/routes/invite-links.js.map +1 -1
  119. package/dist/apps/management/routes/me.d.ts +5 -5
  120. package/dist/apps/management/routes/me.d.ts.map +1 -1
  121. package/dist/apps/management/routes/me.js +14 -10
  122. package/dist/apps/management/routes/me.js.map +1 -1
  123. package/dist/apps/management/routes/members.d.ts +93 -72
  124. package/dist/apps/management/routes/members.d.ts.map +1 -1
  125. package/dist/apps/management/routes/members.js +37 -18
  126. package/dist/apps/management/routes/members.js.map +1 -1
  127. package/dist/apps/management/routes/orgs.d.ts +48 -8
  128. package/dist/apps/management/routes/orgs.d.ts.map +1 -1
  129. package/dist/apps/management/routes/orgs.js +48 -19
  130. package/dist/apps/management/routes/orgs.js.map +1 -1
  131. package/dist/apps/management/routes/projects.d.ts +90 -28
  132. package/dist/apps/management/routes/projects.d.ts.map +1 -1
  133. package/dist/apps/management/routes/projects.js +72 -21
  134. package/dist/apps/management/routes/projects.js.map +1 -1
  135. package/dist/apps/management/routes/scopes.d.ts.map +1 -1
  136. package/dist/apps/management/routes/scopes.js +8 -5
  137. package/dist/apps/management/routes/scopes.js.map +1 -1
  138. package/dist/apps/management/routes/usage.d.ts +78 -78
  139. package/dist/apps/management/routes/usage.d.ts.map +1 -1
  140. package/dist/apps/management/routes/usage.js +41 -31
  141. package/dist/apps/management/routes/usage.js.map +1 -1
  142. package/dist/apps/management/routes/verified-token-requests.d.ts +34 -6
  143. package/dist/apps/management/routes/verified-token-requests.d.ts.map +1 -1
  144. package/dist/apps/management/routes/verified-token-requests.js +36 -17
  145. package/dist/apps/management/routes/verified-token-requests.js.map +1 -1
  146. package/dist/apps/management/routes/webhooks.d.ts +147 -130
  147. package/dist/apps/management/routes/webhooks.d.ts.map +1 -1
  148. package/dist/apps/management/routes/webhooks.js +80 -35
  149. package/dist/apps/management/routes/webhooks.js.map +1 -1
  150. package/dist/apps/mpp/internal/Adapter.d.ts +1 -1
  151. package/dist/apps/mpp/internal/Adapter.d.ts.map +1 -1
  152. package/dist/apps/mpp/internal/Adapter.js +12 -0
  153. package/dist/apps/mpp/internal/Adapter.js.map +1 -1
  154. package/dist/db/Db.d.ts +2 -0
  155. package/dist/db/Db.d.ts.map +1 -1
  156. package/dist/db/Db.js +40 -0
  157. package/dist/db/Db.js.map +1 -1
  158. package/dist/db/Schema.d.ts +23 -1
  159. package/dist/db/Schema.d.ts.map +1 -1
  160. package/dist/db/Schema.js +19 -3
  161. package/dist/db/Schema.js.map +1 -1
  162. package/dist/db/tables/earnVaults.d.ts +5 -1
  163. package/dist/db/tables/earnVaults.d.ts.map +1 -1
  164. package/dist/db/tables/earnVaults.js +5 -0
  165. package/dist/db/tables/earnVaults.js.map +1 -1
  166. package/dist/db/tables/webhookDeliveries.d.ts.map +1 -1
  167. package/dist/db/tables/webhookDeliveries.js +10 -0
  168. package/dist/db/tables/webhookDeliveries.js.map +1 -1
  169. package/dist/db/tables/webhookQueueCompletions.d.ts +15 -0
  170. package/dist/db/tables/webhookQueueCompletions.d.ts.map +1 -0
  171. package/dist/db/tables/webhookQueueCompletions.js +32 -0
  172. package/dist/db/tables/webhookQueueCompletions.js.map +1 -0
  173. package/dist/db/tables/webhookQueueEvents.d.ts +14 -20
  174. package/dist/db/tables/webhookQueueEvents.d.ts.map +1 -1
  175. package/dist/db/tables/webhookQueueEvents.js +68 -47
  176. package/dist/db/tables/webhookQueueEvents.js.map +1 -1
  177. package/dist/db/tables/webhookSubscriptions.d.ts +16 -5
  178. package/dist/db/tables/webhookSubscriptions.d.ts.map +1 -1
  179. package/dist/db/tables/webhookSubscriptions.js +29 -5
  180. package/dist/db/tables/webhookSubscriptions.js.map +1 -1
  181. package/dist/internal/Auth.d.ts +8 -1
  182. package/dist/internal/Auth.d.ts.map +1 -1
  183. package/dist/internal/Auth.js +13 -3
  184. package/dist/internal/Auth.js.map +1 -1
  185. package/dist/internal/Cache.d.ts.map +1 -1
  186. package/dist/internal/Cache.js +11 -7
  187. package/dist/internal/Cache.js.map +1 -1
  188. package/dist/internal/EarnVaults.d.ts +41 -2
  189. package/dist/internal/EarnVaults.d.ts.map +1 -1
  190. package/dist/internal/EarnVaults.js +167 -0
  191. package/dist/internal/EarnVaults.js.map +1 -1
  192. package/dist/internal/OpenApi.d.ts +26 -22
  193. package/dist/internal/OpenApi.d.ts.map +1 -1
  194. package/dist/internal/OpenApi.js +128 -39
  195. package/dist/internal/OpenApi.js.map +1 -1
  196. package/dist/internal/Response.d.ts +13 -8
  197. package/dist/internal/Response.d.ts.map +1 -1
  198. package/dist/internal/Response.js +16 -5
  199. package/dist/internal/Response.js.map +1 -1
  200. package/dist/internal/Schema.d.ts +5 -7
  201. package/dist/internal/Schema.d.ts.map +1 -1
  202. package/dist/internal/Schema.js +6 -7
  203. package/dist/internal/Schema.js.map +1 -1
  204. package/dist/internal/Store.d.ts +15 -6
  205. package/dist/internal/Store.d.ts.map +1 -1
  206. package/dist/internal/Store.js +45 -15
  207. package/dist/internal/Store.js.map +1 -1
  208. package/dist/internal/Tidx.d.ts +2 -0
  209. package/dist/internal/Tidx.d.ts.map +1 -1
  210. package/dist/internal/Tidx.js +16 -4
  211. package/dist/internal/Tidx.js.map +1 -1
  212. package/dist/internal/Webhooks.d.ts +29 -12
  213. package/dist/internal/Webhooks.d.ts.map +1 -1
  214. package/dist/internal/Webhooks.js +37 -20
  215. package/dist/internal/Webhooks.js.map +1 -1
  216. package/dist/internal/funding/Deposit.d.ts +2 -2
  217. package/dist/internal/funding/Deposit.d.ts.map +1 -1
  218. package/dist/internal/funding/Deposit.js +9 -8
  219. package/dist/internal/funding/Deposit.js.map +1 -1
  220. package/dist/internal/funding/DepositAddress.d.ts +4 -4
  221. package/dist/internal/funding/DepositAddress.d.ts.map +1 -1
  222. package/dist/internal/funding/DepositAddress.js +9 -8
  223. package/dist/internal/funding/DepositAddress.js.map +1 -1
  224. package/dist/internal/funding/Provider.d.ts.map +1 -1
  225. package/dist/internal/funding/Provider.js +13 -12
  226. package/dist/internal/funding/Provider.js.map +1 -1
  227. package/dist/internal/funding/providers/stargate.d.ts +19 -0
  228. package/dist/internal/funding/providers/stargate.d.ts.map +1 -0
  229. package/dist/internal/funding/providers/stargate.js +143 -0
  230. package/dist/internal/funding/providers/stargate.js.map +1 -0
  231. package/dist/providers/index.d.ts +7 -0
  232. package/dist/providers/index.d.ts.map +1 -1
  233. package/dist/providers/index.js +3 -0
  234. package/dist/providers/index.js.map +1 -1
  235. package/package.json +2 -2
  236. package/src/App.test.ts +48 -0
  237. package/src/App.ts +4 -2
  238. package/src/Assets.test.ts +18 -0
  239. package/src/Assets.ts +22 -0
  240. package/src/Client.test-d.ts +265 -16
  241. package/src/admin/apps/earn-vaults.test.ts +143 -0
  242. package/src/admin/apps/earn-vaults.ts +83 -6
  243. package/src/admin/apps/organizations.ts +6 -2
  244. package/src/admin/ui/src/routes/api-keys.tsx +36 -0
  245. package/src/admin/ui.generated.ts +151 -189
  246. package/src/apps/data/App.test.ts +31 -0
  247. package/src/apps/data/App.ts +56 -8
  248. package/src/apps/data/ZoneSelection.test.ts +196 -0
  249. package/src/apps/data/ZoneSelection.ts +108 -0
  250. package/src/apps/data/routes/activities.test.ts +328 -1
  251. package/src/apps/data/routes/activities.ts +498 -93
  252. package/src/apps/data/routes/balances.ts +1 -1
  253. package/src/apps/data/routes/blocks.ts +1 -1
  254. package/src/apps/data/routes/earn.test.ts +183 -23
  255. package/src/apps/data/routes/earn.ts +225 -29
  256. package/src/apps/data/routes/earn.zone-access.test.ts +46 -0
  257. package/src/apps/data/routes/exchanges.test.ts +31 -1
  258. package/src/apps/data/routes/exchanges.ts +19 -15
  259. package/src/apps/data/routes/fee-amm.ts +18 -11
  260. package/src/apps/data/routes/receipts.ts +1 -1
  261. package/src/apps/data/routes/rpc.test.ts +75 -0
  262. package/src/apps/data/routes/rpc.ts +23 -9
  263. package/src/apps/data/routes/tokenlist.ts +21 -18
  264. package/src/apps/data/routes/tokens.test.ts +29 -0
  265. package/src/apps/data/routes/tokens.ts +38 -15
  266. package/src/apps/data/routes/transactions.ts +1 -1
  267. package/src/apps/data/routes/transfers.test.ts +3 -3
  268. package/src/apps/data/routes/transfers.ts +12 -9
  269. package/src/apps/data/routes/webhooks.ts +6 -2
  270. package/src/apps/data/routes/zones.test.ts +19 -13
  271. package/src/apps/funding/routes/chains.test.ts +211 -7
  272. package/src/apps/funding/routes/chains.ts +19 -12
  273. package/src/apps/funding/routes/deposit-addresses.test.ts +394 -0
  274. package/src/apps/funding/routes/deposit-addresses.ts +84 -72
  275. package/src/apps/funding/routes/providers.ts +9 -5
  276. package/src/apps/funding/routes/quotes.test.ts +46 -0
  277. package/src/apps/funding/routes/quotes.ts +8 -5
  278. package/src/apps/funding/routes/transfers.test.ts +35 -32
  279. package/src/apps/management/Billing.test.ts +26 -0
  280. package/src/apps/management/Billing.ts +24 -7
  281. package/src/apps/management/routes/api-keys.test.ts +178 -0
  282. package/src/apps/management/routes/api-keys.ts +203 -144
  283. package/src/apps/management/routes/billing.test.ts +209 -0
  284. package/src/apps/management/routes/billing.ts +254 -177
  285. package/src/apps/management/routes/faucet.test.ts +39 -0
  286. package/src/apps/management/routes/faucet.ts +75 -41
  287. package/src/apps/management/routes/invitations.test.ts +216 -0
  288. package/src/apps/management/routes/invitations.ts +186 -109
  289. package/src/apps/management/routes/invite-links.test.ts +263 -1
  290. package/src/apps/management/routes/invite-links.ts +295 -214
  291. package/src/apps/management/routes/me.test.ts +49 -0
  292. package/src/apps/management/routes/me.ts +42 -32
  293. package/src/apps/management/routes/members.test.ts +124 -1
  294. package/src/apps/management/routes/members.ts +81 -51
  295. package/src/apps/management/routes/orgs.test.ts +176 -0
  296. package/src/apps/management/routes/orgs.ts +101 -59
  297. package/src/apps/management/routes/projects.test.ts +183 -0
  298. package/src/apps/management/routes/projects.ts +124 -60
  299. package/src/apps/management/routes/scopes.test.ts +44 -0
  300. package/src/apps/management/routes/scopes.ts +37 -28
  301. package/src/apps/management/routes/usage.test.ts +92 -0
  302. package/src/apps/management/routes/usage.ts +186 -151
  303. package/src/apps/management/routes/verified-token-requests.test.ts +114 -0
  304. package/src/apps/management/routes/verified-token-requests.ts +166 -133
  305. package/src/apps/management/routes/webhooks.test.ts +234 -0
  306. package/src/apps/management/routes/webhooks.ts +191 -78
  307. package/src/apps/mpp/internal/Adapter.ts +13 -1
  308. package/src/db/Db.test.ts +41 -0
  309. package/src/db/Db.ts +62 -0
  310. package/src/db/Schema.ts +28 -3
  311. package/src/db/tables/earnVaults.test.ts +22 -0
  312. package/src/db/tables/earnVaults.ts +11 -1
  313. package/src/db/tables/webhookDeliveries.ts +13 -0
  314. package/src/db/tables/webhookQueueCompletions.ts +55 -0
  315. package/src/db/tables/webhookQueueEvents.ts +95 -61
  316. package/src/db/tables/webhookSubscriptions.ts +45 -6
  317. package/src/internal/Auth.ts +23 -5
  318. package/src/internal/Cache.ts +14 -7
  319. package/src/internal/EarnVaults.capabilities.test.ts +33 -0
  320. package/src/internal/EarnVaults.test.ts +79 -0
  321. package/src/internal/EarnVaults.ts +277 -0
  322. package/src/internal/OpenApi.ts +165 -49
  323. package/src/internal/Response.test.ts +95 -0
  324. package/src/internal/Response.ts +40 -2
  325. package/src/internal/Schema.test.ts +16 -0
  326. package/src/internal/Schema.ts +7 -7
  327. package/src/internal/Store.test.ts +186 -0
  328. package/src/internal/Store.ts +57 -17
  329. package/src/internal/Tidx.test.ts +19 -0
  330. package/src/internal/Tidx.ts +16 -4
  331. package/src/internal/Webhooks.test.ts +122 -8
  332. package/src/internal/Webhooks.ts +59 -29
  333. package/src/internal/funding/Deposit.ts +71 -64
  334. package/src/internal/funding/DepositAddress.ts +50 -43
  335. package/src/internal/funding/Provider.ts +164 -142
  336. package/src/internal/funding/providers/index.test.ts +185 -0
  337. package/src/internal/funding/providers/stargate.ts +184 -0
  338. package/src/providers/index.test.ts +1 -0
  339. package/src/providers/index.ts +9 -0
@@ -25,40 +25,55 @@ export namespace schema {
25
25
  )
26
26
 
27
27
  /** One organization: the top-level tenant that owns API keys. */
28
- export const Organization = Schema.describe(
29
- z.object({
30
- createdAt: z
31
- .string()
32
- .check(
33
- z.describe('When the organization was created (ISO 8601).'),
34
- z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
35
- ),
36
- id: z
37
- .string()
38
- .check(
39
- z.describe('Opaque organization id (`org_…`).'),
40
- z.meta({ examples: ['org_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
41
- ),
42
- name: z
43
- .string()
44
- .check(
45
- z.describe('Human-readable organization name.'),
46
- z.meta({ examples: ['Acme, Inc.'] }),
47
- ),
48
- role: z
49
- .optional(z.enum(Memberships.roles))
50
- .check(
51
- z.describe("The caller's role; absent for API keys and the super admin."),
52
- z.meta({ examples: ['owner'] }),
53
- ),
54
- updatedAt: z
55
- .string()
56
- .check(
57
- z.describe('When the organization was last updated (ISO 8601).'),
58
- z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
59
- ),
60
- }),
61
- 'An organization: the top-level tenant that owns API keys.',
28
+ export const Organization = OpenApi.component(
29
+ Schema.describe(
30
+ z.object({
31
+ createdAt: z.iso
32
+ .datetime()
33
+ .check(
34
+ z.describe('When the organization was created (ISO 8601).'),
35
+ z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
36
+ ),
37
+ id: z
38
+ .string()
39
+ .check(
40
+ z.describe('Opaque organization id (`org_…`).'),
41
+ z.meta({ examples: ['org_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
42
+ ),
43
+ name: z
44
+ .string()
45
+ .check(
46
+ z.describe('Human-readable organization name.'),
47
+ z.meta({ examples: ['Acme, Inc.'] }),
48
+ ),
49
+ role: z
50
+ .optional(z.enum(Memberships.roles))
51
+ .check(
52
+ z.describe("The caller's role; absent for API keys and the super admin."),
53
+ z.meta({ examples: ['owner'] }),
54
+ ),
55
+ updatedAt: z.iso
56
+ .datetime()
57
+ .check(
58
+ z.describe('When the organization was last updated (ISO 8601).'),
59
+ z.meta({ examples: ['2026-01-01T00:00:00.000Z'] }),
60
+ ),
61
+ }),
62
+ 'An organization: the top-level tenant that owns API keys.',
63
+ ),
64
+ 'Organization',
65
+ )
66
+
67
+ /** Request body creating an organization. */
68
+ export const CreateOrganizationRequest = OpenApi.component(
69
+ z.object({ name }).check(z.describe('Fields for creating an organization.')),
70
+ 'CreateOrganizationRequest',
71
+ )
72
+
73
+ /** Request body updating an organization. */
74
+ export const UpdateOrganizationRequest = OpenApi.component(
75
+ z.object({ name }).check(z.describe('Fields for updating an organization.')),
76
+ 'UpdateOrganizationRequest',
62
77
  )
63
78
 
64
79
  /** Path parameters addressing one organization. */
@@ -73,34 +88,35 @@ export namespace schema {
73
88
  })
74
89
  .check(z.describe('Path parameters for one organization.'))
75
90
 
76
- /** Request body creating or renaming an organization. */
77
- export const OrganizationBody = z
78
- .object({ name })
79
- .check(z.describe('Fields for creating or renaming an organization.'))
80
-
81
91
  /** Schemas for the deleteOrganization operation. */
82
92
  export namespace deleteOrganization {
83
93
  /** Confirmation that the organization was deleted. */
84
- export const Response = z
85
- .object({
86
- id: z
87
- .string()
88
- .check(
89
- z.describe('ID of the organization that was deleted.'),
90
- z.meta({ examples: ['org_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
91
- ),
92
- })
93
- .check(z.describe('Confirmation that the organization was deleted.'))
94
+ export const Response = OpenApi.component(
95
+ z
96
+ .object({
97
+ id: z
98
+ .string()
99
+ .check(
100
+ z.describe('ID of the organization that was deleted.'),
101
+ z.meta({ examples: ['org_1a2b3c4d5e6f7g8h9j0k1m2n'] }),
102
+ ),
103
+ })
104
+ .check(z.describe('Confirmation that the organization was deleted.')),
105
+ 'DeleteOrganizationResponse',
106
+ )
94
107
  }
95
108
 
96
109
  /** Schemas for the listOrganizations operation. */
97
110
  export namespace listOrganizations {
98
111
  /** Non-paginated list of organizations. */
99
- export const Response = Schema.describe(
100
- z.object({
101
- data: z.array(Organization).check(z.describe('The organizations, newest first.')),
102
- }),
103
- 'A non-paginated list of organizations.',
112
+ export const Response = OpenApi.component(
113
+ Schema.describe(
114
+ z.object({
115
+ data: z.array(Organization).check(z.describe('The organizations, newest first.')),
116
+ }),
117
+ 'A non-paginated list of organizations.',
118
+ ),
119
+ 'OrganizationList',
104
120
  )
105
121
  }
106
122
  }
@@ -116,6 +132,7 @@ export function orgs() {
116
132
  OpenApi.describeRoute({
117
133
  operationId: 'listOrganizations',
118
134
  responses: OpenApi.responses({
135
+ errors: { 400: { codes: [], description: 'Malformed API key.' } },
119
136
  success: {
120
137
  description: 'The organizations, newest first.',
121
138
  schema: schema.listOrganizations.Response,
@@ -154,13 +171,16 @@ export function orgs() {
154
171
  .post(
155
172
  '/v1/orgs',
156
173
  Auth.policy({ session: true }),
157
- OpenApi.validate('json', schema.OrganizationBody, {
174
+ OpenApi.validate('json', schema.CreateOrganizationRequest, {
158
175
  code: 'body_invalid',
159
176
  message: 'Check the request body and try again.',
160
177
  }),
161
178
  OpenApi.describeRoute({
162
179
  operationId: 'createOrganization',
163
180
  responses: OpenApi.responses({
181
+ errors: {
182
+ 400: { codes: ['body_invalid'], description: 'Malformed API key or invalid body.' },
183
+ },
164
184
  success: {
165
185
  description: 'The created organization.',
166
186
  schema: schema.Organization,
@@ -218,7 +238,13 @@ export function orgs() {
218
238
  OpenApi.describeRoute({
219
239
  operationId: 'getOrganization',
220
240
  responses: OpenApi.responses({
221
- errors: { 404: 'No accessible organization was found for this id.' },
241
+ errors: {
242
+ 400: { codes: ['param_invalid'], description: 'Malformed API key or invalid path.' },
243
+ 404: {
244
+ codes: ['organization_not_found'],
245
+ description: 'No accessible organization was found for this id.',
246
+ },
247
+ },
222
248
  success: { description: 'One organization.', schema: schema.Organization },
223
249
  }),
224
250
  summary: 'Get organization',
@@ -250,14 +276,23 @@ export function orgs() {
250
276
  code: 'param_invalid',
251
277
  message: 'Check the path parameters and try again.',
252
278
  }),
253
- OpenApi.validate('json', schema.OrganizationBody, {
279
+ OpenApi.validate('json', schema.UpdateOrganizationRequest, {
254
280
  code: 'body_invalid',
255
281
  message: 'Check the request body and try again.',
256
282
  }),
257
283
  OpenApi.describeRoute({
258
284
  operationId: 'updateOrganization',
259
285
  responses: OpenApi.responses({
260
- errors: { 404: 'No accessible organization was found for this id.' },
286
+ errors: {
287
+ 400: {
288
+ codes: ['body_invalid', 'param_invalid'],
289
+ description: 'Malformed API key, invalid path, or invalid body.',
290
+ },
291
+ 404: {
292
+ codes: ['organization_not_found'],
293
+ description: 'No accessible organization was found for this id.',
294
+ },
295
+ },
261
296
  success: { description: 'The updated organization.', schema: schema.Organization },
262
297
  }),
263
298
  summary: 'Update organization',
@@ -265,6 +300,8 @@ export function orgs() {
265
300
  }),
266
301
  async (c) => {
267
302
  if (Auth.narrowAccess) return Auth.accessError(c)
303
+ if (Auth.narrowScope) return Auth.ensureOrgError(c)
304
+ if (Auth.narrowOrgRole) return Auth.ensureOrgRoleError(c)
268
305
  if (OpenApi.narrowValidation)
269
306
  return OpenApi.validationError(c, {
270
307
  code: 'param_invalid',
@@ -306,7 +343,11 @@ export function orgs() {
306
343
  operationId: 'deleteOrganization',
307
344
  responses: OpenApi.responses({
308
345
  errors: {
309
- 404: 'No accessible organization was found for this id.',
346
+ 400: { codes: ['param_invalid'], description: 'Malformed API key or invalid path.' },
347
+ 404: {
348
+ codes: ['organization_not_found'],
349
+ description: 'No accessible organization was found for this id.',
350
+ },
310
351
  409: {
311
352
  codes: ['sponsorships_unreported'],
312
353
  description: 'Billable sponsorships are still awaiting settlement.',
@@ -323,6 +364,7 @@ export function orgs() {
323
364
  async (c) => {
324
365
  if (Auth.narrowAccess) return Auth.accessError(c)
325
366
  if (Auth.narrowScope) return Auth.ensureOrgError(c)
367
+ if (Auth.narrowOrgRole) return Auth.ensureOrgRoleError(c)
326
368
  if (OpenApi.narrowValidation)
327
369
  return OpenApi.validationError(c, {
328
370
  code: 'param_invalid',
@@ -20,6 +20,189 @@ function createApp() {
20
20
  return TestApp.create({ session: { wallet: { origin } } })
21
21
  }
22
22
 
23
+ test('publishes generator-ready OpenAPI contracts', async () => {
24
+ const app = createApp()
25
+ const spec = await (await app.request('/openapi.json')).json()
26
+ const collection = spec.paths['/v1/orgs/{orgId}/projects']
27
+ const detail = spec.paths['/v1/orgs/{orgId}/projects/{projectId}']
28
+
29
+ expect({
30
+ components: [
31
+ 'CreateProjectRequest',
32
+ 'DeleteProjectResponse',
33
+ 'Project',
34
+ 'ProjectList',
35
+ 'UpdateProjectRequest',
36
+ ].filter((name) => spec.components.schemas[name]),
37
+ create: {
38
+ errors: {
39
+ 400: collection.post.responses[400].content['application/json'].schema,
40
+ 401: collection.post.responses[401].content['application/json'].schema,
41
+ 403: collection.post.responses[403].content['application/json'].schema,
42
+ 404: collection.post.responses[404].content['application/json'].schema,
43
+ 502: collection.post.responses[502].content['application/json'].schema,
44
+ },
45
+ operationId: collection.post.operationId,
46
+ request: collection.post.requestBody.content['application/json'].schema,
47
+ response: collection.post.responses[200].content['application/json'].schema,
48
+ },
49
+ delete: {
50
+ operationId: detail.delete.operationId,
51
+ response: detail.delete.responses[200].content['application/json'].schema,
52
+ },
53
+ errorComponents: {
54
+ detail: {
55
+ reference:
56
+ spec.components.schemas.ApiKeyMalformedOrParamInvalidError.properties.error.properties
57
+ .details.items,
58
+ required: spec.components.schemas.ErrorDetail.required,
59
+ },
60
+ invalidBodyOrParameters:
61
+ spec.components.schemas.ApiKeyMalformedOrBodyInvalidOrParamInvalidError.properties.error
62
+ .properties.code.enum,
63
+ invalidParameters:
64
+ spec.components.schemas.ApiKeyMalformedOrParamInvalidError.properties.error.properties.code
65
+ .enum,
66
+ forbidden: spec.components.schemas.ForbiddenError.properties.error.properties.code.enum,
67
+ organizationNotFound:
68
+ spec.components.schemas.OrganizationNotFoundError.properties.error.properties.code.enum,
69
+ organizationOrProjectNotFound:
70
+ spec.components.schemas.OrganizationNotFoundOrProjectNotFoundError.properties.error
71
+ .properties.code.enum,
72
+ },
73
+ list: {
74
+ operationId: collection.get.operationId,
75
+ response: collection.get.responses[200].content['application/json'].schema,
76
+ },
77
+ sharedResponses: {
78
+ internal: spec.components.responses.InternalError.content['application/json'].schema,
79
+ rateLimit: spec.components.responses.RateLimited.content['application/json'].schema,
80
+ },
81
+ timestamps: {
82
+ createdAt: spec.components.schemas.Project.properties.createdAt.format,
83
+ updatedAt: spec.components.schemas.Project.properties.updatedAt.format,
84
+ },
85
+ update: {
86
+ operationId: detail.patch.operationId,
87
+ request: detail.patch.requestBody.content['application/json'].schema,
88
+ response: detail.patch.responses[200].content['application/json'].schema,
89
+ },
90
+ }).toMatchInlineSnapshot(`
91
+ {
92
+ "components": [
93
+ "CreateProjectRequest",
94
+ "DeleteProjectResponse",
95
+ "Project",
96
+ "ProjectList",
97
+ "UpdateProjectRequest",
98
+ ],
99
+ "create": {
100
+ "errors": {
101
+ "400": {
102
+ "$ref": "#/components/schemas/ApiKeyMalformedOrBodyInvalidOrParamInvalidError",
103
+ },
104
+ "401": {
105
+ "$ref": "#/components/schemas/AuthenticationError",
106
+ },
107
+ "403": {
108
+ "$ref": "#/components/schemas/ForbiddenError",
109
+ },
110
+ "404": {
111
+ "$ref": "#/components/schemas/OrganizationNotFoundError",
112
+ },
113
+ "502": {
114
+ "$ref": "#/components/schemas/UpstreamError",
115
+ },
116
+ },
117
+ "operationId": "createProject",
118
+ "request": {
119
+ "$ref": "#/components/schemas/CreateProjectRequest",
120
+ },
121
+ "response": {
122
+ "$ref": "#/components/schemas/Project",
123
+ },
124
+ },
125
+ "delete": {
126
+ "operationId": "deleteProject",
127
+ "response": {
128
+ "$ref": "#/components/schemas/DeleteProjectResponse",
129
+ },
130
+ },
131
+ "errorComponents": {
132
+ "detail": {
133
+ "reference": {
134
+ "$ref": "#/components/schemas/ErrorDetail",
135
+ },
136
+ "required": [
137
+ "message",
138
+ ],
139
+ },
140
+ "forbidden": [
141
+ "api_key_forbidden",
142
+ "api_key_ip_forbidden",
143
+ "forbidden",
144
+ ],
145
+ "invalidBodyOrParameters": [
146
+ "api_key_malformed",
147
+ "body_invalid",
148
+ "param_invalid",
149
+ ],
150
+ "invalidParameters": [
151
+ "api_key_malformed",
152
+ "param_invalid",
153
+ ],
154
+ "organizationNotFound": [
155
+ "organization_not_found",
156
+ ],
157
+ "organizationOrProjectNotFound": [
158
+ "organization_not_found",
159
+ "project_not_found",
160
+ ],
161
+ },
162
+ "list": {
163
+ "operationId": "listProjects",
164
+ "response": {
165
+ "$ref": "#/components/schemas/ProjectList",
166
+ },
167
+ },
168
+ "sharedResponses": {
169
+ "internal": {
170
+ "$ref": "#/components/schemas/InternalError",
171
+ },
172
+ "rateLimit": {
173
+ "$ref": "#/components/schemas/RateLimitError",
174
+ },
175
+ },
176
+ "timestamps": {
177
+ "createdAt": "date-time",
178
+ "updatedAt": "date-time",
179
+ },
180
+ "update": {
181
+ "operationId": "updateProject",
182
+ "request": {
183
+ "$ref": "#/components/schemas/UpdateProjectRequest",
184
+ },
185
+ "response": {
186
+ "$ref": "#/components/schemas/Project",
187
+ },
188
+ },
189
+ }
190
+ `)
191
+
192
+ expect(detail.patch.responses[400].content['application/json'].schema).toEqual(
193
+ collection.post.responses[400].content['application/json'].schema,
194
+ )
195
+ expect(collection.get.responses[404].content['application/json'].schema).toEqual(
196
+ collection.post.responses[404].content['application/json'].schema,
197
+ )
198
+ expect(detail.patch.responses[404].content['application/json'].schema).toEqual(
199
+ detail.get.responses[404].content['application/json'].schema,
200
+ )
201
+ expect(detail.delete.responses[404].content['application/json'].schema).toEqual(
202
+ detail.get.responses[404].content['application/json'].schema,
203
+ )
204
+ })
205
+
23
206
  /** Signs in a fresh scripted account; returns its session cookie. */
24
207
  async function session(app: TestApp.signIn.App) {
25
208
  const account = privateKeyToAccount(generatePrivateKey())