@volter/twin-stripe 2.0.38 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (402) hide show
  1. package/README.md +112 -207
  2. package/dist/generated/pack-facts.json +94 -0
  3. package/dist/journeys/coverage.json +596 -0
  4. package/dist/journeys/customer-life.json +6108 -0
  5. package/dist/journeys/customer-life.outline.md +371 -0
  6. package/dist/journeys/decisions.json +677 -0
  7. package/dist/journeys/demand.json +706 -0
  8. package/dist/journeys/score.json +853 -0
  9. package/dist/journeys/unreachable.json +102 -0
  10. package/dist/journeys/vendor-examples.json +8010 -0
  11. package/dist/spec/SOURCE.md +18 -0
  12. package/dist/spec/doc-examples.json +445 -0
  13. package/dist/spec/fixtures3.json.gz +0 -0
  14. package/dist/spec/openapi.json.gz +0 -0
  15. package/dist/spec/patches.json +34 -0
  16. package/dist/spec/sources.json +306 -0
  17. package/dist/src/cli.d.ts +0 -1
  18. package/dist/src/cli.js +11 -31
  19. package/dist/src/engine/after-payment.d.ts +8 -0
  20. package/dist/src/engine/after-payment.js +27 -0
  21. package/dist/src/engine/apps-secrets.d.ts +1 -0
  22. package/dist/src/engine/apps-secrets.js +3 -0
  23. package/dist/src/engine/balance.d.ts +5 -0
  24. package/dist/src/engine/balance.js +15 -0
  25. package/dist/src/engine/checkout.d.ts +24 -0
  26. package/dist/src/engine/checkout.js +30 -0
  27. package/dist/src/engine/common.d.ts +19 -0
  28. package/dist/src/engine/common.js +34 -0
  29. package/dist/src/engine/connect.d.ts +45 -0
  30. package/dist/src/engine/connect.js +108 -0
  31. package/dist/src/engine/customers.d.ts +4 -0
  32. package/dist/src/engine/customers.js +8 -0
  33. package/dist/src/engine/display.d.ts +11 -0
  34. package/dist/src/engine/display.js +13 -0
  35. package/dist/src/engine/files.d.ts +11 -0
  36. package/dist/src/engine/files.js +23 -0
  37. package/dist/src/engine/invoices.d.ts +21 -0
  38. package/dist/src/engine/invoices.js +84 -0
  39. package/dist/src/engine/issuing.d.ts +33 -0
  40. package/dist/src/engine/issuing.js +54 -0
  41. package/dist/src/engine/ledger.d.ts +8 -0
  42. package/dist/src/engine/ledger.js +8 -0
  43. package/dist/src/engine/oauth.d.ts +4 -0
  44. package/dist/src/engine/oauth.js +24 -0
  45. package/dist/src/engine/onboarding.d.ts +13 -0
  46. package/dist/src/engine/onboarding.js +42 -0
  47. package/dist/src/{stripe-params.d.ts → engine/params.d.ts} +20 -3
  48. package/dist/src/{stripe-params.js → engine/params.js} +7 -60
  49. package/dist/src/engine/payment-intents.d.ts +10 -0
  50. package/dist/src/engine/payment-intents.js +27 -0
  51. package/dist/src/engine/payment-methods.d.ts +16 -0
  52. package/dist/src/engine/payment-methods.js +22 -0
  53. package/dist/src/engine/radar.d.ts +2 -0
  54. package/dist/src/engine/radar.js +5 -0
  55. package/dist/src/engine/refunds.d.ts +1 -0
  56. package/dist/src/engine/refunds.js +3 -0
  57. package/dist/src/engine/renewals.d.ts +36 -0
  58. package/dist/src/engine/renewals.js +65 -0
  59. package/dist/src/{stripe-twin.d.ts → engine/stripe.d.ts} +12 -45
  60. package/dist/src/{stripe-twin.js → engine/stripe.js} +53 -387
  61. package/dist/src/engine/subscriptions.d.ts +11 -0
  62. package/dist/src/engine/subscriptions.js +30 -0
  63. package/dist/src/engine/transfers.d.ts +2 -0
  64. package/dist/src/engine/transfers.js +1 -0
  65. package/dist/src/{stripe-version.d.ts → engine/version.d.ts} +0 -2
  66. package/dist/src/{stripe-version.js → engine/version.js} +21 -9
  67. package/dist/src/engine/webhook-endpoints.d.ts +1 -0
  68. package/dist/src/engine/webhook-endpoints.js +12 -0
  69. package/dist/src/engine/webhooks.d.ts +31 -0
  70. package/dist/src/engine/webhooks.js +68 -0
  71. package/dist/src/fetch.d.ts +2 -0
  72. package/dist/src/fetch.js +26 -0
  73. package/dist/src/generated/surface.gen.json +1 -1
  74. package/dist/src/generated/ui.gen.json +1 -1
  75. package/dist/src/index.d.ts +5 -14
  76. package/dist/src/index.js +10 -75
  77. package/dist/src/manifest.js +478 -876
  78. package/dist/src/screens/billing-portal.d.ts +3 -0
  79. package/dist/src/screens/{portal.js → billing-portal.js} +32 -58
  80. package/dist/src/screens/checkout-js.d.ts +2 -0
  81. package/dist/src/screens/checkout-js.js +84 -0
  82. package/dist/src/screens/checkout.d.ts +2 -31
  83. package/dist/src/screens/checkout.js +32 -121
  84. package/dist/src/screens/connect-onboarding.d.ts +3 -0
  85. package/dist/src/screens/{onboarding.js → connect-onboarding.js} +38 -104
  86. package/dist/src/screens/dashboard.d.ts +3 -0
  87. package/dist/src/screens/dashboard.js +116 -0
  88. package/dist/src/screens/shared.d.ts +27 -0
  89. package/dist/src/screens/shared.js +87 -0
  90. package/dist/src/screens/stripe-js.d.ts +3 -0
  91. package/dist/src/screens/stripe-js.js +95 -0
  92. package/dist/src/semantics/account.d.ts +2 -0
  93. package/dist/src/semantics/account.js +8 -0
  94. package/dist/src/semantics/account_links.d.ts +2 -0
  95. package/dist/src/semantics/account_links.js +22 -0
  96. package/dist/src/semantics/accounts.d.ts +4 -0
  97. package/dist/src/semantics/accounts.js +40 -0
  98. package/dist/src/semantics/apps.d.ts +4 -0
  99. package/dist/src/semantics/{apps-secrets.js → apps.js} +14 -26
  100. package/dist/src/semantics/around.d.ts +2 -0
  101. package/dist/src/semantics/around.js +13 -0
  102. package/dist/src/semantics/balance.d.ts +2 -11
  103. package/dist/src/semantics/balance.js +3 -194
  104. package/dist/src/semantics/balance_transactions.d.ts +2 -0
  105. package/dist/src/semantics/balance_transactions.js +15 -0
  106. package/dist/src/semantics/billing_portal.d.ts +4 -0
  107. package/dist/src/semantics/billing_portal.js +36 -0
  108. package/dist/src/semantics/charges.d.ts +3 -28
  109. package/dist/src/semantics/charges.js +5 -202
  110. package/dist/src/semantics/checkout.d.ts +3 -20
  111. package/dist/src/semantics/checkout.js +21 -271
  112. package/dist/src/semantics/clock.d.ts +2 -0
  113. package/dist/src/semantics/clock.js +15 -0
  114. package/dist/src/semantics/coupons.d.ts +2 -6
  115. package/dist/src/semantics/coupons.js +2 -60
  116. package/dist/src/semantics/customers.d.ts +5 -6
  117. package/dist/src/semantics/customers.js +47 -413
  118. package/dist/src/semantics/doors.d.ts +23 -0
  119. package/dist/src/semantics/doors.js +73 -0
  120. package/dist/src/semantics/entitlements.d.ts +0 -2
  121. package/dist/src/semantics/entitlements.js +4 -95
  122. package/dist/src/semantics/events.d.ts +11 -0
  123. package/dist/src/semantics/events.js +31 -0
  124. package/dist/src/semantics/index.d.ts +2 -0
  125. package/dist/src/semantics/index.js +85 -0
  126. package/dist/src/semantics/invoice_payments.d.ts +2 -0
  127. package/dist/src/semantics/invoice_payments.js +12 -0
  128. package/dist/src/semantics/invoices.d.ts +11 -18
  129. package/dist/src/semantics/invoices.js +121 -440
  130. package/dist/src/semantics/issuing.d.ts +6 -13
  131. package/dist/src/semantics/issuing.js +58 -556
  132. package/dist/src/semantics/payment_intents.d.ts +3 -0
  133. package/dist/src/semantics/payment_intents.js +71 -0
  134. package/dist/src/semantics/payment_methods.d.ts +3 -0
  135. package/dist/src/semantics/payment_methods.js +15 -0
  136. package/dist/src/semantics/payouts.d.ts +3 -0
  137. package/dist/src/semantics/payouts.js +28 -0
  138. package/dist/src/semantics/prices.d.ts +4 -0
  139. package/dist/src/semantics/prices.js +37 -0
  140. package/dist/src/semantics/products.d.ts +4 -2
  141. package/dist/src/semantics/products.js +12 -138
  142. package/dist/src/semantics/promotion_codes.d.ts +3 -0
  143. package/dist/src/semantics/promotion_codes.js +35 -0
  144. package/dist/src/semantics/radar.d.ts +2 -2
  145. package/dist/src/semantics/radar.js +5 -74
  146. package/dist/src/semantics/refunds.d.ts +2 -9
  147. package/dist/src/semantics/refunds.js +3 -193
  148. package/dist/src/semantics/shared.d.ts +558 -55
  149. package/dist/src/semantics/shared.js +2070 -114
  150. package/dist/src/semantics/states.d.ts +462 -0
  151. package/dist/src/semantics/states.js +634 -0
  152. package/dist/src/semantics/subscriptions.d.ts +6 -11
  153. package/dist/src/semantics/subscriptions.js +37 -530
  154. package/dist/src/semantics/test_helpers.d.ts +3 -0
  155. package/dist/src/semantics/test_helpers.js +125 -0
  156. package/dist/src/semantics/transfers.d.ts +2 -2
  157. package/dist/src/semantics/transfers.js +6 -101
  158. package/dist/src/semantics/webhook_endpoints.d.ts +2 -0
  159. package/dist/src/semantics/webhook_endpoints.js +26 -0
  160. package/dist/src/server.d.ts +7 -0
  161. package/dist/src/server.js +7 -0
  162. package/generated/pack-facts.json +94 -0
  163. package/journeys/coverage.json +596 -0
  164. package/journeys/customer-life.json +6108 -0
  165. package/journeys/customer-life.outline.md +371 -0
  166. package/journeys/decisions.json +677 -0
  167. package/journeys/demand.json +706 -0
  168. package/journeys/score.json +853 -0
  169. package/journeys/unreachable.json +102 -0
  170. package/journeys/vendor-examples.json +8010 -0
  171. package/package.json +11 -20
  172. package/spec/SOURCE.md +18 -0
  173. package/spec/doc-examples.json +445 -0
  174. package/spec/fixtures3.json.gz +0 -0
  175. package/spec/openapi.json.gz +0 -0
  176. package/spec/patches.json +34 -0
  177. package/spec/sources.json +306 -0
  178. package/src/cli.ts +11 -28
  179. package/src/engine/after-payment.ts +29 -0
  180. package/src/engine/apps-secrets.ts +4 -0
  181. package/src/engine/balance.ts +32 -0
  182. package/src/engine/checkout.ts +39 -0
  183. package/src/engine/common.ts +49 -0
  184. package/src/engine/connect.ts +106 -0
  185. package/src/engine/customers.ts +10 -0
  186. package/src/engine/display.ts +18 -0
  187. package/src/engine/files.ts +28 -0
  188. package/src/engine/invoices.ts +102 -0
  189. package/src/engine/issuing.ts +66 -0
  190. package/src/engine/ledger.ts +48 -0
  191. package/src/engine/oauth.ts +18 -0
  192. package/src/engine/onboarding.ts +53 -0
  193. package/src/{stripe-params.ts → engine/params.ts} +7 -56
  194. package/src/engine/payment-intents.ts +32 -0
  195. package/src/engine/payment-methods.ts +24 -0
  196. package/src/engine/radar.ts +6 -0
  197. package/src/engine/refunds.ts +3 -0
  198. package/src/engine/renewals.ts +72 -0
  199. package/src/{stripe-twin.ts → engine/stripe.ts} +57 -400
  200. package/src/engine/subscriptions.ts +37 -0
  201. package/src/engine/transfers.ts +22 -0
  202. package/src/{stripe-version.ts → engine/version.ts} +19 -10
  203. package/src/engine/webhook-endpoints.ts +14 -0
  204. package/src/engine/webhooks.ts +70 -0
  205. package/src/fetch.ts +27 -0
  206. package/src/generated/surface.gen.json +1 -1
  207. package/src/generated/ui.gen.json +1 -1
  208. package/src/index.ts +10 -116
  209. package/src/manifest.ts +480 -904
  210. package/src/screens/{portal.tsx → billing-portal.tsx} +35 -42
  211. package/src/screens/checkout-js.ts +80 -0
  212. package/src/screens/checkout.tsx +32 -96
  213. package/src/screens/{onboarding.tsx → connect-onboarding.tsx} +39 -85
  214. package/src/screens/dashboard.tsx +178 -0
  215. package/src/screens/shared.tsx +84 -0
  216. package/src/screens/stripe-js.ts +102 -0
  217. package/src/semantics/account.ts +10 -0
  218. package/src/semantics/account_links.ts +20 -0
  219. package/src/semantics/accounts.ts +44 -0
  220. package/src/semantics/{apps-secrets.ts → apps.ts} +17 -33
  221. package/src/semantics/around.ts +17 -0
  222. package/src/semantics/balance.ts +6 -208
  223. package/src/semantics/balance_transactions.ts +18 -0
  224. package/src/semantics/billing_portal.ts +45 -0
  225. package/src/semantics/charges.ts +8 -212
  226. package/src/semantics/checkout.ts +25 -276
  227. package/src/semantics/clock.ts +19 -0
  228. package/src/semantics/coupons.ts +5 -68
  229. package/src/semantics/customers.ts +48 -414
  230. package/src/semantics/doors.ts +79 -0
  231. package/src/semantics/entitlements.ts +3 -94
  232. package/src/semantics/events.ts +37 -0
  233. package/src/semantics/index.ts +89 -0
  234. package/src/semantics/invoice_payments.ts +16 -0
  235. package/src/semantics/invoices.ts +112 -441
  236. package/src/semantics/issuing.ts +57 -573
  237. package/src/semantics/payment_intents.ts +76 -0
  238. package/src/semantics/payment_methods.ts +20 -0
  239. package/src/semantics/payouts.ts +29 -0
  240. package/src/semantics/prices.ts +41 -0
  241. package/src/semantics/products.ts +12 -146
  242. package/src/semantics/promotion_codes.ts +38 -0
  243. package/src/semantics/radar.ts +8 -79
  244. package/src/semantics/refunds.ts +4 -216
  245. package/src/semantics/shared.ts +2089 -135
  246. package/src/semantics/states.ts +662 -0
  247. package/src/semantics/subscriptions.ts +39 -542
  248. package/src/semantics/test_helpers.ts +119 -0
  249. package/src/semantics/transfers.ts +10 -132
  250. package/src/semantics/webhook_endpoints.ts +27 -0
  251. package/src/server.ts +7 -0
  252. package/client/dashboard-api.ts +0 -286
  253. package/client/stripe-mirror.css +0 -277
  254. package/client/stripe-mirror.tsx +0 -1559
  255. package/dist/client/dashboard-api.d.ts +0 -107
  256. package/dist/client/dashboard-api.js +0 -238
  257. package/dist/client/dashboard-api.ts +0 -286
  258. package/dist/client/stripe-mirror.bundle.js +0 -236
  259. package/dist/client/stripe-mirror.css +0 -277
  260. package/dist/client/stripe-mirror.d.ts +0 -134
  261. package/dist/client/stripe-mirror.js +0 -859
  262. package/dist/client/stripe-mirror.tsx +0 -1559
  263. package/dist/src/screens/connect-oauth.d.ts +0 -27
  264. package/dist/src/screens/connect-oauth.js +0 -414
  265. package/dist/src/screens/connect-settings.d.ts +0 -22
  266. package/dist/src/screens/connect-settings.js +0 -103
  267. package/dist/src/screens/consent-skin.d.ts +0 -4
  268. package/dist/src/screens/consent-skin.js +0 -18
  269. package/dist/src/screens/financial-connections.d.ts +0 -5
  270. package/dist/src/screens/financial-connections.js +0 -90
  271. package/dist/src/screens/identity.d.ts +0 -5
  272. package/dist/src/screens/identity.js +0 -86
  273. package/dist/src/screens/onboarding.d.ts +0 -13
  274. package/dist/src/screens/portal.d.ts +0 -5
  275. package/dist/src/screens/public-details.d.ts +0 -5
  276. package/dist/src/screens/public-details.js +0 -90
  277. package/dist/src/semantics/after-payment.d.ts +0 -22
  278. package/dist/src/semantics/after-payment.js +0 -99
  279. package/dist/src/semantics/apps-secrets.d.ts +0 -2
  280. package/dist/src/semantics/billing.d.ts +0 -2
  281. package/dist/src/semantics/billing.js +0 -220
  282. package/dist/src/semantics/connect.d.ts +0 -5
  283. package/dist/src/semantics/connect.js +0 -493
  284. package/dist/src/semantics/credit-notes.d.ts +0 -2
  285. package/dist/src/semantics/credit-notes.js +0 -172
  286. package/dist/src/semantics/disputes.d.ts +0 -2
  287. package/dist/src/semantics/disputes.js +0 -51
  288. package/dist/src/semantics/ephemeral-keys.d.ts +0 -2
  289. package/dist/src/semantics/ephemeral-keys.js +0 -34
  290. package/dist/src/semantics/files.d.ts +0 -2
  291. package/dist/src/semantics/files.js +0 -125
  292. package/dist/src/semantics/ledger.d.ts +0 -59
  293. package/dist/src/semantics/ledger.js +0 -200
  294. package/dist/src/semantics/payment-intents.d.ts +0 -18
  295. package/dist/src/semantics/payment-intents.js +0 -452
  296. package/dist/src/semantics/payment-links.d.ts +0 -2
  297. package/dist/src/semantics/payment-links.js +0 -133
  298. package/dist/src/semantics/payment-methods.d.ts +0 -20
  299. package/dist/src/semantics/payment-methods.js +0 -140
  300. package/dist/src/semantics/plans.d.ts +0 -5
  301. package/dist/src/semantics/plans.js +0 -121
  302. package/dist/src/semantics/platform.d.ts +0 -9
  303. package/dist/src/semantics/platform.js +0 -206
  304. package/dist/src/semantics/renewals.d.ts +0 -47
  305. package/dist/src/semantics/renewals.js +0 -281
  306. package/dist/src/semantics/setup-intents.d.ts +0 -2
  307. package/dist/src/semantics/setup-intents.js +0 -84
  308. package/dist/src/semantics/subscription-schedules.d.ts +0 -2
  309. package/dist/src/semantics/subscription-schedules.js +0 -119
  310. package/dist/src/semantics/tax.d.ts +0 -2
  311. package/dist/src/semantics/tax.js +0 -197
  312. package/dist/src/semantics/terminal.d.ts +0 -5
  313. package/dist/src/semantics/terminal.js +0 -182
  314. package/dist/src/semantics/test-clocks.d.ts +0 -6
  315. package/dist/src/semantics/test-clocks.js +0 -73
  316. package/dist/src/semantics/tokens.d.ts +0 -4
  317. package/dist/src/semantics/tokens.js +0 -44
  318. package/dist/src/semantics/treasury.d.ts +0 -2
  319. package/dist/src/semantics/treasury.js +0 -377
  320. package/dist/src/semantics/webhook-endpoints.d.ts +0 -3
  321. package/dist/src/semantics/webhook-endpoints.js +0 -85
  322. package/dist/src/stripe-budget.d.ts +0 -55
  323. package/dist/src/stripe-budget.js +0 -155
  324. package/dist/src/stripe-capabilities.d.ts +0 -3
  325. package/dist/src/stripe-capabilities.js +0 -5836
  326. package/dist/src/stripe-conformance.d.ts +0 -43
  327. package/dist/src/stripe-conformance.js +0 -105
  328. package/dist/src/stripe-connector.d.ts +0 -161
  329. package/dist/src/stripe-connector.js +0 -414
  330. package/dist/src/stripe-emit.d.ts +0 -2
  331. package/dist/src/stripe-emit.js +0 -145
  332. package/dist/src/stripe-events.d.ts +0 -93
  333. package/dist/src/stripe-events.js +0 -392
  334. package/dist/src/stripe-js.d.ts +0 -4
  335. package/dist/src/stripe-js.js +0 -70
  336. package/dist/src/stripe-mirror-ui.d.ts +0 -15
  337. package/dist/src/stripe-mirror-ui.js +0 -87
  338. package/dist/src/stripe-perform-harness.d.ts +0 -9
  339. package/dist/src/stripe-perform-harness.js +0 -26
  340. package/dist/src/stripe-server.d.ts +0 -33
  341. package/dist/src/stripe-server.js +0 -429
  342. package/dist/src/stripe-shared.d.ts +0 -109
  343. package/dist/src/stripe-shared.js +0 -276
  344. package/dist/src/stripe-ui-conformance.d.ts +0 -5
  345. package/dist/src/stripe-ui-conformance.js +0 -79
  346. package/dist/src/stripe-ui-structure.d.ts +0 -3
  347. package/dist/src/stripe-ui-structure.js +0 -168
  348. package/dist/test-fixtures/stripe-known-deviations.json +0 -110
  349. package/dist/test-fixtures/stripe-openapi-operations.SOURCE.md +0 -14
  350. package/dist/test-fixtures/stripe-openapi-operations.json +0 -4717
  351. package/dist/test-fixtures/stripe-schemas.SOURCE.md +0 -35
  352. package/dist/test-fixtures/stripe-schemas.json +0 -3813
  353. package/src/screens/connect-oauth.tsx +0 -400
  354. package/src/screens/connect-settings.tsx +0 -121
  355. package/src/screens/consent-skin.ts +0 -20
  356. package/src/screens/financial-connections.tsx +0 -101
  357. package/src/screens/identity.tsx +0 -96
  358. package/src/screens/public-details.tsx +0 -105
  359. package/src/semantics/after-payment.ts +0 -118
  360. package/src/semantics/billing.ts +0 -216
  361. package/src/semantics/connect.ts +0 -487
  362. package/src/semantics/credit-notes.ts +0 -168
  363. package/src/semantics/disputes.ts +0 -62
  364. package/src/semantics/ephemeral-keys.ts +0 -34
  365. package/src/semantics/files.ts +0 -143
  366. package/src/semantics/ledger.ts +0 -253
  367. package/src/semantics/payment-intents.ts +0 -463
  368. package/src/semantics/payment-links.ts +0 -148
  369. package/src/semantics/payment-methods.ts +0 -145
  370. package/src/semantics/plans.ts +0 -131
  371. package/src/semantics/platform.ts +0 -220
  372. package/src/semantics/renewals.ts +0 -279
  373. package/src/semantics/setup-intents.ts +0 -87
  374. package/src/semantics/subscription-schedules.ts +0 -129
  375. package/src/semantics/tax.ts +0 -220
  376. package/src/semantics/terminal.ts +0 -195
  377. package/src/semantics/test-clocks.ts +0 -77
  378. package/src/semantics/tokens.ts +0 -52
  379. package/src/semantics/treasury.ts +0 -383
  380. package/src/semantics/webhook-endpoints.ts +0 -87
  381. package/src/stripe-budget.ts +0 -181
  382. package/src/stripe-capabilities.ts +0 -5651
  383. package/src/stripe-conformance.ts +0 -124
  384. package/src/stripe-connector.ts +0 -462
  385. package/src/stripe-emit.ts +0 -157
  386. package/src/stripe-events.ts +0 -434
  387. package/src/stripe-js.ts +0 -70
  388. package/src/stripe-mirror-ui.ts +0 -90
  389. package/src/stripe-perform-harness.ts +0 -29
  390. package/src/stripe-server.ts +0 -393
  391. package/src/stripe-shared.ts +0 -297
  392. package/src/stripe-ui-conformance.ts +0 -88
  393. package/src/stripe-ui-structure.ts +0 -182
  394. package/test-fixtures/stripe-known-deviations.json +0 -110
  395. package/test-fixtures/stripe-openapi-operations.json +0 -4717
  396. package/test-fixtures/stripe-schemas.json +0 -3813
  397. /package/dist/src/{screens → engine}/industries.d.ts +0 -0
  398. /package/dist/src/{screens → engine}/industries.js +0 -0
  399. /package/dist/src/{semantics → engine}/test-cards.d.ts +0 -0
  400. /package/dist/src/{semantics → engine}/test-cards.js +0 -0
  401. /package/src/{screens → engine}/industries.ts +0 -0
  402. /package/src/{semantics → engine}/test-cards.ts +0 -0
@@ -1,377 +0,0 @@
1
- import { PLATFORM_ACCOUNT_ID, validateMoney } from "../stripe-twin.js";
2
- import { at, created, fail, list, newest, send, where } from "./shared.js";
3
- const FA = 'treasury.financial_account';
4
- const TX = 'treasury.transaction';
5
- const ENTRY = 'treasury.transaction_entry';
6
- const ENTRY_TYPES = new Set(['credit_reversal', 'debit_reversal', 'inbound_transfer', 'inbound_transfer_return', 'issuing_authorization_hold', 'issuing_authorization_release', 'outbound_payment', 'outbound_transfer', 'received_credit', 'received_debit']);
7
- const faMissing = (ctx, id, status = 404) => fail(ctx, `No such financial account: '${id}'`, status, 'resource_missing');
8
- const metadataOf = (ctx) => (ctx.params.metadata && typeof ctx.params.metadata === 'object' ? ctx.params.metadata : {});
9
- /** A financial account's features as the served spec's treasury.financial_account_features gives them: a toggle
10
- * (card_issuing, deposit_insurance, intra_stripe_flows) or a feature per network (financial_addresses.aba,
11
- * inbound_transfers.ach, outbound_payments.ach and .us_domestic_wire, outbound_transfers likewise), each
12
- * { requested, status, status_details }. What a request asks for is laid over what the account had. Where the
13
- * documentation stops and the twin decides: a requested feature is active at once (test mode), and one never requested
14
- * is left out (each is optional in the served spec). Answers the features and the active features' paths. */
15
- const NETWORKS = { financial_addresses: ['aba'], inbound_transfers: ['ach'], outbound_payments: ['ach', 'us_domestic_wire'], outbound_transfers: ['ach', 'us_domestic_wire'] };
16
- const TOGGLES = ['card_issuing', 'deposit_insurance', 'intra_stripe_flows'];
17
- function featuresOf(requested, had = {}) {
18
- const on = (v) => v === true || v === 'true';
19
- const setting = (asked) => ({ requested: asked, status: asked ? 'active' : 'restricted', status_details: [] });
20
- const features = { ...had };
21
- for (const t of TOGGLES) {
22
- const r = requested[t];
23
- if (r && typeof r === 'object' && r.requested !== undefined)
24
- features[t] = setting(on(r.requested));
25
- }
26
- for (const [f, nets] of Object.entries(NETWORKS)) {
27
- const r = requested[f];
28
- if (!r || typeof r !== 'object')
29
- continue;
30
- const current = features[f] ?? {};
31
- const next = { ...current };
32
- for (const n of nets) {
33
- const nr = r[n];
34
- if (nr && typeof nr === 'object' && nr.requested !== undefined)
35
- next[n] = setting(on(nr.requested));
36
- }
37
- features[f] = next;
38
- }
39
- const active = [];
40
- for (const t of TOGGLES)
41
- if (features[t]?.status === 'active')
42
- active.push(t);
43
- for (const [f, nets] of Object.entries(NETWORKS))
44
- for (const n of nets)
45
- if (features[f]?.[n]?.status === 'active')
46
- active.push(`${f}.${n}`);
47
- return { features, active };
48
- }
49
- /** The account's bank address once financial_addresses.aba is active: "The FinancialAccount gains a FinancialAddress
50
- * when the `financial_addresses.aba` feature is active", and "A FinancialAddress is not added until the
51
- * financial_addresses.aba feature has been activated" (docs.stripe.com/treasury/account-management/financial-accounts),
52
- * whose test example answers "bank_name": "Stripe Test Bank", "routing_number": "000000001" and the networks "ach",
53
- * "us_domestic_wire", "rtp"; "The full account_number is only returned if the request expands it" (the same page).
54
- * Where the documentation stops and the twin decides: the account number is ten digits drawn from the account's id,
55
- * answered by its last four (the full number is null: expanding it is not modelled), and the holder's name is the
56
- * platform account's business name, its dashboard name or, with neither, its id. */
57
- function abaAddress(ctx, faId) {
58
- let n = 0;
59
- for (const ch of faId)
60
- n = (n * 31 + ch.charCodeAt(0)) % 10_000_000_000;
61
- const number = String(n).padStart(10, '0');
62
- const platform = ctx.get('account', PLATFORM_ACCOUNT_ID);
63
- const name = (platform?.business_profile?.name ?? platform?.settings?.dashboard?.display_name ?? PLATFORM_ACCOUNT_ID);
64
- return { type: 'aba', supported_networks: ['ach', 'us_domestic_wire', 'rtp'], aba: { account_holder_name: name, account_number: null, account_number_last4: number.slice(-4), bank_name: 'Stripe Test Bank', routing_number: '000000001' } };
65
- }
66
- const addressesOf = (ctx, faId, active) => (active.includes('financial_addresses.aba') ? [abaAddress(ctx, faId)] : []);
67
- // an account opens with a zero balance in each supported currency and the requested features active
68
- const open = async (ctx) => {
69
- const p = ctx.params;
70
- const currencies = Array.isArray(p.supported_currencies) ? p.supported_currencies.map(String) : typeof p.supported_currencies === 'string' ? [p.supported_currencies] : [];
71
- if (currencies.length === 0)
72
- return fail(ctx, 'Missing required param: supported_currencies.', 400, 'parameter_missing');
73
- const requested = p.features && typeof p.features === 'object' ? p.features : {};
74
- const { features, active } = featuresOf(requested);
75
- const zero = Object.fromEntries(currencies.map((c) => [c, 0]));
76
- const id = ctx.mint(FA);
77
- return ctx.reply(await created(ctx, FA, { id }, {
78
- livemode: false, status: 'open', country: p.country ?? 'US',
79
- supported_currencies: currencies, active_features: active, pending_features: [], restricted_features: [],
80
- features, balance: { cash: zero, inbound_pending: zero, outbound_pending: zero },
81
- financial_addresses: addressesOf(ctx, id, active), platform_restrictions: null,
82
- status_details: { closed: null },
83
- metadata: metadataOf(ctx),
84
- }));
85
- };
86
- // reading the features answers them; updating them lays the request over them (featuresOf)
87
- const features = async (ctx) => {
88
- const id = at(ctx, 'financial_account');
89
- const f = ctx.get(FA, id);
90
- if (!f)
91
- return faMissing(ctx, id);
92
- if (ctx.call.request.method === 'GET')
93
- return ctx.reply({ object: 'treasury.financial_account_features', ...f.features });
94
- const next = featuresOf(ctx.params, f.features ?? {});
95
- const updated = await ctx.write(FA, id, { features: next.features, active_features: next.active, financial_addresses: addressesOf(ctx, id, next.active) }, 'financial_account.features_updated');
96
- return ctx.reply({ object: 'treasury.financial_account_features', ...updated.features });
97
- };
98
- // only metadata and platform restrictions change
99
- const updateAccount = async (ctx) => {
100
- const id = at(ctx, 'financial_account');
101
- if (!ctx.get(FA, id))
102
- return faMissing(ctx, id);
103
- const patch = {};
104
- if (ctx.params.metadata !== undefined)
105
- patch.metadata = ctx.params.metadata;
106
- if (ctx.params.platform_restrictions !== undefined)
107
- patch.platform_restrictions = ctx.params.platform_restrictions;
108
- return ctx.reply(await ctx.write(FA, id, patch, 'financial_account.updated'));
109
- };
110
- /** Post a flow's double entry: a ledger transaction with its net balance impact, and its one entry. */
111
- async function post(ctx, o) {
112
- const now = ctx.now();
113
- const txnId = ctx.mint(TX);
114
- await ctx.write(TX, txnId, {
115
- object: 'treasury.transaction', created: now, livemode: false,
116
- amount: o.amount, currency: o.currency, financial_account: o.financial_account,
117
- flow: o.flow, flow_type: o.flow_type, flow_details: null,
118
- status: o.status, balance_impact: o.balance_impact, description: o.description,
119
- entries: { object: 'list', has_more: false, url: `/v1/treasury/transaction_entries?transaction=${txnId}`, data: [] },
120
- status_transitions: { posted_at: o.status === 'posted' ? now : null, void_at: null },
121
- }, 'treasury_transaction.created');
122
- await ctx.write(ENTRY, ctx.mint(ENTRY), {
123
- object: 'treasury.transaction_entry', created: now, livemode: false,
124
- amount: o.amount, currency: o.currency, financial_account: o.financial_account,
125
- flow: o.flow, flow_type: o.flow_type,
126
- flow_details: o.flowDetailKey ? { type: o.flowDetailKey, [o.flowDetailKey]: o.flow } : null,
127
- transaction: txnId, effective_at: now,
128
- balance_impact: o.balance_impact,
129
- // what the entry records: its flow's kind where Stripe names one (docs.stripe.com/api/treasury/transaction_entries/object);
130
- // a vendor `type`, kept apart from the kernel's row type
131
- _stripe_type: ENTRY_TYPES.has(String(o.flow_type)) ? o.flow_type : 'other',
132
- }, 'treasury_transaction_entry.created');
133
- // the account's balance moves by the entry's impact: cash "Funds the user can spend right now", inbound_pending
134
- // "Funds not spendable yet", outbound_pending "held for pending outbound flows" (the served spec's balance)
135
- const account = ctx.get(FA, o.financial_account);
136
- if (account) {
137
- const bal = account.balance ?? { cash: {}, inbound_pending: {}, outbound_pending: {} };
138
- const moved = Object.fromEntries(['cash', 'inbound_pending', 'outbound_pending'].map((k) => [k, { ...(bal[k] ?? {}), [o.currency]: ((bal[k] ?? {})[o.currency] ?? 0) + (Number(o.balance_impact[k]) || 0) }]));
139
- await ctx.write(FA, o.financial_account, { balance: moved }, 'financial_account.balance_updated');
140
- }
141
- return txnId;
142
- }
143
- /** The request's funding account, or the refusal. */
144
- function fundingAccount(ctx) {
145
- const bad = validateMoney(ctx.params);
146
- if (bad)
147
- return send(ctx, bad);
148
- const fa = typeof ctx.params.financial_account === 'string' ? ctx.params.financial_account : '';
149
- if (!fa)
150
- return fail(ctx, 'Missing required param: financial_account.', 400, 'parameter_missing');
151
- return ctx.get(FA, fa) ? fa : faMissing(ctx, fa, 400);
152
- }
153
- const noTransitions = { canceled_at: null, failed_at: null, posted_at: null, returned_at: null };
154
- /** Where an outbound flow sends its money, as the served spec's payment method details give it: the bank account's
155
- * holder type, last four digits and routing number from what the request sent (a saved method's, or the test bank's
156
- * when none is given), and its billing details (required): the name and email sent, the address lines null where not
157
- * given. Where the documentation stops and the twin decides: a saved method's details are the test bank's. */
158
- function destinationDetails(ctx, dest) {
159
- const data = ctx.params.destination_payment_method_data && typeof ctx.params.destination_payment_method_data === 'object' ? ctx.params.destination_payment_method_data : {};
160
- const bank = data.us_bank_account && typeof data.us_bank_account === 'object' ? data.us_bank_account : {};
161
- const billing = data.billing_details && typeof data.billing_details === 'object' ? data.billing_details : {};
162
- const address = billing.address && typeof billing.address === 'object' ? billing.address : {};
163
- const number = typeof bank.account_number === 'string' ? bank.account_number.replace(/\D/g, '') : '';
164
- const billing_details = { name: billing.name ?? null, email: billing.email ?? null, address: Object.fromEntries(['city', 'country', 'line1', 'line2', 'postal_code', 'state'].map((k) => [k, address[k] ?? null])) };
165
- if (dest && data.type === undefined && dest.startsWith('fa_'))
166
- return { type: 'financial_account', financial_account: { id: dest, network: 'stripe' }, billing_details };
167
- return {
168
- type: 'us_bank_account', billing_details,
169
- us_bank_account: { last4: number ? number.slice(-4) : '6789', network: 'ach', routing_number: typeof bank.routing_number === 'string' ? bank.routing_number : '110000000', account_holder_type: typeof bank.account_holder_type === 'string' ? bank.account_holder_type : 'individual', account_type: typeof bank.account_type === 'string' ? bank.account_type : 'checking', bank_name: 'STRIPE TEST BANK', mandate: null },
170
- };
171
- }
172
- /** An outbound payment that names no destination: "You must provide either destination_payment_method or
173
- * destination_payment_method_data" (the served spec's outbound payment create). */
174
- function noDestination(ctx) {
175
- return fail(ctx, 'You must provide either `destination_payment_method` or `destination_payment_method_data`.', 400, 'parameter_missing');
176
- }
177
- const outboundPayment = async (ctx) => {
178
- const fa = fundingAccount(ctx);
179
- if (fa instanceof Response)
180
- return fa;
181
- const dest = typeof ctx.params.destination_payment_method === 'string' ? ctx.params.destination_payment_method : null;
182
- if (!dest && !(ctx.params.destination_payment_method_data && typeof ctx.params.destination_payment_method_data === 'object'))
183
- return noDestination(ctx);
184
- const amount = ctx.params.amount;
185
- const currency = String(ctx.params.currency);
186
- const id = ctx.mint('treasury.outbound_payment');
187
- const txn = await post(ctx, { financial_account: fa, amount: -amount, currency, flow: id, flow_type: 'outbound_payment', status: 'open', balance_impact: { cash: -amount, inbound_pending: 0, outbound_pending: amount }, description: 'OutboundPayment' });
188
- return ctx.reply(await created(ctx, 'treasury.outbound_payment', { id }, {
189
- amount, currency, financial_account: fa, livemode: false, status: 'processing', cancelable: true,
190
- destination_payment_method: dest,
191
- destination_payment_method_details: destinationDetails(ctx, dest),
192
- destination_payment_method_data: null, end_user_details: null, expected_arrival_date: Number(ctx.now()) + 2 * 86400,
193
- hosted_regulatory_receipt_url: null, returned_details: null, statement_descriptor: ctx.params.statement_descriptor ?? 'payment',
194
- description: typeof ctx.params.description === 'string' ? ctx.params.description : null, transaction: txn, status_transitions: noTransitions, metadata: metadataOf(ctx),
195
- }));
196
- };
197
- const outboundTransfer = async (ctx) => {
198
- const fa = fundingAccount(ctx);
199
- if (fa instanceof Response)
200
- return fa;
201
- const dest = typeof ctx.params.destination_payment_method === 'string' ? ctx.params.destination_payment_method : null;
202
- const amount = ctx.params.amount;
203
- const currency = String(ctx.params.currency);
204
- const id = ctx.mint('treasury.outbound_transfer');
205
- const txn = await post(ctx, { financial_account: fa, amount: -amount, currency, flow: id, flow_type: 'outbound_transfer', status: 'open', balance_impact: { cash: -amount, inbound_pending: 0, outbound_pending: amount }, description: 'OutboundTransfer' });
206
- return ctx.reply(await created(ctx, 'treasury.outbound_transfer', { id }, {
207
- amount, currency, financial_account: fa, livemode: false, status: 'processing', cancelable: true,
208
- destination_payment_method: dest, destination_payment_method_details: destinationDetails(ctx, dest),
209
- expected_arrival_date: Number(ctx.now()) + 2 * 86400, hosted_regulatory_receipt_url: null,
210
- returned_details: null, statement_descriptor: ctx.params.statement_descriptor ?? 'transfer',
211
- description: typeof ctx.params.description === 'string' ? ctx.params.description : null, transaction: txn, status_transitions: noTransitions, metadata: metadataOf(ctx),
212
- }));
213
- };
214
- /** The bank account an inbound transfer may pull from: "You must first set up the account-attached payment method for
215
- * inbound flows and verify the bank account using a SetupIntent", and invalid ones ("of unsupported types, containing
216
- * an unverified bank account, or not set up for inbound flows") "throw the same errors as in live mode"
217
- * (docs.stripe.com/treasury/moving-money/financial-accounts/into/inbound-transfers). A payment method is set up for
218
- * inbound flows by a SetupIntent whose flow_directions holds `inbound`, and verified when that SetupIntent succeeded
219
- * ("The bank account has been instantly verified or verification isn't necessary", its `succeeded` status,
220
- * docs.stripe.com/treasury/connect/legacy/v1/moving-money/working-with-bankaccount-objects).
221
- * Where the documentation stops and the twin decides: the page quotes no error, so the twin answers the documented code
222
- * for the class, payment_method_unexpected_state ("The provided payment method's state was incompatible with the
223
- * operation you were trying to perform", docs.stripe.com/error-codes), in its own words; an existing verified
224
- * BankAccount (`ba_`), which the page also allows, is not checked. Answers the payment method, or the refusal. */
225
- function inboundOrigin(ctx, origin) {
226
- if (origin.startsWith('ba_'))
227
- return undefined;
228
- const pm = ctx.get('payment_method', origin);
229
- if (!pm)
230
- return fail(ctx, `No such PaymentMethod: '${origin}'`, 400, 'resource_missing');
231
- if (pm.type !== 'us_bank_account')
232
- return fail(ctx, `The PaymentMethod '${origin}' is of type ${String(pm.type)}; an InboundTransfer pulls from a us_bank_account.`, 400, 'payment_method_unexpected_state');
233
- const setUp = ctx.rows('setup_intent').some((si) => si.payment_method === origin && si.status === 'succeeded' && Array.isArray(si.flow_directions) && si.flow_directions.map(String).includes('inbound'));
234
- if (!setUp)
235
- return fail(ctx, `The PaymentMethod '${origin}' has not been set up for inbound flows and verified with a SetupIntent.`, 400, 'payment_method_unexpected_state');
236
- return pm;
237
- }
238
- const inboundTransfer = async (ctx) => {
239
- const fa = fundingAccount(ctx);
240
- if (fa instanceof Response)
241
- return fa;
242
- const origin = typeof ctx.params.origin_payment_method === 'string' ? ctx.params.origin_payment_method : '';
243
- if (!origin)
244
- return fail(ctx, 'Missing required param: origin_payment_method.', 400, 'parameter_missing');
245
- const pm = inboundOrigin(ctx, origin);
246
- if (pm instanceof Response)
247
- return pm;
248
- const bank = (pm?.us_bank_account ?? {});
249
- const billing = (pm?.billing_details ?? {});
250
- // the debit mandate the account's verification made (docs.stripe.com/payments/setup-intents#mandates)
251
- const mandate = ctx.rows('setup_intent').find((si) => si.payment_method === origin && si.status === 'succeeded' && typeof si.mandate === 'string')?.mandate;
252
- const amount = ctx.params.amount;
253
- const currency = String(ctx.params.currency);
254
- const id = ctx.mint('treasury.inbound_transfer');
255
- // it starts processing, its funds pending inbound, until confirmed (succeedInbound)
256
- const txn = await post(ctx, { financial_account: fa, amount, currency, flow: id, flow_type: 'inbound_transfer', status: 'open', balance_impact: { cash: 0, inbound_pending: amount, outbound_pending: 0 }, description: 'InboundTransfer', flowDetailKey: 'inbound_transfer' });
257
- return ctx.reply(await created(ctx, 'treasury.inbound_transfer', { id }, {
258
- amount, currency, financial_account: fa, origin_payment_method: origin, livemode: false,
259
- status: 'processing', cancelable: true, returned: null,
260
- // the pulled account as its payment method holds it
261
- origin_payment_method_details: {
262
- type: 'us_bank_account',
263
- us_bank_account: { last4: bank.last4 ?? '6789', routing_number: bank.routing_number ?? '110000000', bank_name: bank.bank_name ?? 'STRIPE TEST BANK', account_holder_type: bank.account_holder_type ?? null, account_type: bank.account_type ?? null, fingerprint: bank.fingerprint ?? null, ...(mandate ? { mandate } : {}), network: 'ach' },
264
- billing_details: { address: billing.address ?? {}, email: billing.email ?? null, name: billing.name ?? null },
265
- },
266
- failure_details: null, hosted_regulatory_receipt_url: null,
267
- linked_flows: { received_debit: null }, statement_descriptor: ctx.params.statement_descriptor ?? 'transfer',
268
- description: typeof ctx.params.description === 'string' ? ctx.params.description : null, transaction: txn, status_transitions: { succeeded_at: null, failed_at: null, canceled_at: null },
269
- metadata: metadataOf(ctx),
270
- }));
271
- };
272
- // test mode's stand-ins for money another party sends to the account or pulls from it
273
- // (docs.stripe.com/treasury/moving-money/receiving-funds, docs.stripe.com/api/treasury/received_credits/test_mode_create)
274
- function received(kind) {
275
- return async (ctx) => {
276
- const fa = fundingAccount(ctx);
277
- if (fa instanceof Response)
278
- return fa;
279
- const network = typeof ctx.params.network === 'string' ? ctx.params.network : '';
280
- if (!['ach', 'us_domestic_wire', 'stripe'].includes(network))
281
- return fail(ctx, 'Missing required param: network.', 400, 'parameter_missing');
282
- const amount = ctx.params.amount;
283
- const currency = String(ctx.params.currency);
284
- const id = ctx.mint(`treasury.${kind}`);
285
- const signed = kind === 'received_credit' ? amount : -amount;
286
- const txn = await post(ctx, { financial_account: fa, amount: signed, currency, flow: id, flow_type: kind, status: 'posted', balance_impact: { cash: signed, inbound_pending: 0, outbound_pending: 0 }, description: kind === 'received_credit' ? 'ReceivedCredit' : 'ReceivedDebit', flowDetailKey: kind });
287
- return ctx.reply(await created(ctx, `treasury.${kind}`, { id }, {
288
- amount, currency, financial_account: fa, network, livemode: false, status: 'succeeded', failure_code: null,
289
- description: typeof ctx.params.description === 'string' ? ctx.params.description : kind === 'received_credit' ? 'Received credit' : 'Received debit',
290
- hosted_regulatory_receipt_url: null, transaction: txn, reversal_details: null,
291
- initiating_payment_method_details: { type: 'us_bank_account', billing_details: { address: {}, email: null, name: null }, us_bank_account: { bank_name: 'STRIPE TEST BANK', last4: '6789', routing_number: '110000000' } },
292
- linked_flows: kind === 'received_credit' ? { credit_reversal: null, issuing_authorization: null, issuing_transaction: null, source_flow: null, source_flow_type: null } : { debit_reversal: null, inbound_transfer: null, issuing_authorization: null, issuing_transaction: null, payout: null },
293
- }));
294
- };
295
- }
296
- /** Test mode's confirmation of a processing inbound transfer: it succeeds, its transaction posts and the pending funds
297
- * become cash ("The status changes to succeeded once the funds have been "confirmed" and a transaction is created and
298
- * posted", docs.stripe.com/api/treasury/inbound_transfers). */
299
- const succeedInbound = async (ctx) => {
300
- const id = at(ctx, 'id');
301
- const flow = ctx.get('treasury.inbound_transfer', id);
302
- if (!flow)
303
- return fail(ctx, `No such inbound transfer: '${id}'`, 404, 'resource_missing');
304
- const refused = ctx.legal('treasury.inbound_transfer', 'status', 'PostTestHelpersTreasuryInboundTransfersIdSucceed', flow.status, 'succeeded', id);
305
- if (refused)
306
- return ctx.refuse(refused);
307
- const txn = typeof flow.transaction === 'string' ? ctx.get(TX, flow.transaction) : undefined;
308
- const amount = Number(flow.amount) || 0;
309
- const cur = String(flow.currency ?? 'usd');
310
- if (txn && txn.status === 'open') {
311
- await ctx.write(TX, String(txn.id), { status: 'posted', balance_impact: { cash: amount, inbound_pending: 0, outbound_pending: 0 }, status_transitions: { ...txn.status_transitions, posted_at: ctx.now() } }, 'treasury_transaction.posted');
312
- const account = ctx.get(FA, String(txn.financial_account));
313
- if (account) {
314
- const bal = account.balance ?? { cash: {}, inbound_pending: {}, outbound_pending: {} };
315
- await ctx.write(FA, String(account.id), { balance: { ...bal, cash: { ...(bal.cash ?? {}), [cur]: ((bal.cash ?? {})[cur] ?? 0) + amount }, inbound_pending: { ...(bal.inbound_pending ?? {}), [cur]: ((bal.inbound_pending ?? {})[cur] ?? 0) - amount } } }, 'financial_account.balance_updated');
316
- }
317
- }
318
- return ctx.reply(await ctx.write('treasury.inbound_transfer', id, { status: 'succeeded', cancelable: false, status_transitions: { ...flow.status_transitions, succeeded_at: ctx.now() } }, 'inbound_transfer.succeeded'));
319
- };
320
- /** Cancel a flow still processing; an outbound one must also still be cancelable. */
321
- function cancel(resource, param, name, operationId, op, checkCancelable) {
322
- return async (ctx) => {
323
- const id = at(ctx, param);
324
- const flow = ctx.get(resource, id);
325
- if (!flow)
326
- return fail(ctx, `No such ${name}: '${id}'`, 404, 'resource_missing');
327
- // a processing flow that is no longer cancelable is refused as one no longer processing
328
- const refused = ctx.legal(resource, 'status', operationId, checkCancelable && flow.cancelable !== true ? 'not_cancelable' : flow.status, undefined, id);
329
- if (refused)
330
- return ctx.refuse(refused);
331
- // a canceled flow's open transaction is voided and what it held returns to the account (the reverse of its
332
- // balance impact). Where the documentation stops and the twin decides: a flow already posted is only marked canceled
333
- const txn = typeof flow.transaction === 'string' ? ctx.get(TX, flow.transaction) : undefined;
334
- if (txn && txn.status === 'open') {
335
- await ctx.write(TX, String(txn.id), { status: 'void', status_transitions: { ...txn.status_transitions, void_at: ctx.now() } }, 'treasury_transaction.voided');
336
- const account = ctx.get(FA, String(txn.financial_account));
337
- const impact = txn.balance_impact ?? {};
338
- const cur = String(txn.currency ?? 'usd');
339
- if (account) {
340
- const bal = account.balance ?? { cash: {}, inbound_pending: {}, outbound_pending: {} };
341
- const back = Object.fromEntries(['cash', 'inbound_pending', 'outbound_pending'].map((k) => [k, { ...(bal[k] ?? {}), [cur]: ((bal[k] ?? {})[cur] ?? 0) - (Number(impact[k]) || 0) }]));
342
- await ctx.write(FA, String(account.id), { balance: back }, 'financial_account.balance_updated');
343
- }
344
- }
345
- return ctx.reply(await ctx.write(resource, id, { status: 'canceled', cancelable: false, status_transitions: { ...flow.status_transitions, canceled_at: ctx.now() } }, op));
346
- };
347
- }
348
- // the ledger is always read for one account
349
- function ledger(resource, spec) {
350
- return async (ctx) => {
351
- if (typeof ctx.params.financial_account !== 'string' || !ctx.params.financial_account)
352
- return fail(ctx, 'Missing required param: financial_account.', 400, 'parameter_missing');
353
- return list(ctx, resource, where(ctx, newest(ctx, resource), spec));
354
- };
355
- }
356
- export const treasury = {
357
- PostTreasuryFinancialAccounts: open,
358
- GetTreasuryFinancialAccountsFinancialAccountFeatures: features,
359
- PostTreasuryFinancialAccountsFinancialAccountFeatures: features,
360
- PostTreasuryFinancialAccountsFinancialAccount: updateAccount,
361
- PostTreasuryOutboundPayments: outboundPayment,
362
- PostTreasuryOutboundPaymentsIdCancel: cancel('treasury.outbound_payment', 'id', 'outbound payment', 'PostTreasuryOutboundPaymentsIdCancel', 'outbound_payment.canceled', true),
363
- PostTreasuryOutboundTransfers: outboundTransfer,
364
- PostTreasuryOutboundTransfersOutboundTransferCancel: cancel('treasury.outbound_transfer', 'outbound_transfer', 'outbound transfer', 'PostTreasuryOutboundTransfersOutboundTransferCancel', 'outbound_transfer.canceled', true),
365
- PostTreasuryInboundTransfers: inboundTransfer,
366
- PostTestHelpersTreasuryInboundTransfersIdSucceed: succeedInbound,
367
- PostTestHelpersTreasuryReceivedCredits: received('received_credit'),
368
- PostTestHelpersTreasuryReceivedDebits: received('received_debit'),
369
- PostTreasuryInboundTransfersInboundTransferCancel: cancel('treasury.inbound_transfer', 'inbound_transfer', 'inbound transfer', 'PostTreasuryInboundTransfersInboundTransferCancel', 'inbound_transfer.canceled', false),
370
- GetTreasuryTransactions: ledger(TX, {
371
- financial_account: (r, v) => r.financial_account === v, status: (r, v) => r.status === v,
372
- flow: (r, v) => r.flow === v, flow_type: (r, v) => r.flow_type === v,
373
- }),
374
- GetTreasuryTransactionEntries: ledger(ENTRY, {
375
- financial_account: (r, v) => r.financial_account === v, flow: (r, v) => r.flow === v, transaction: (r, v) => r.transaction === v,
376
- }),
377
- };
@@ -1,3 +0,0 @@
1
- import { type Semantics } from '@volter/world-core';
2
- export declare function worldEndpointSecret(connect: boolean): string | undefined;
3
- export declare const webhookEndpoints: Record<string, Semantics>;
@@ -1,85 +0,0 @@
1
- // Webhook endpoint semantics: registering a URL and the events it subscribes to. Delivery reads
2
- // the endpoints from the tree, signing each POST with the endpoint's own secret; a disabled one
3
- // (the machine in ../manifest.ts) receives nothing. Endpoint list, retrieve and delete are the derived core's.
4
- //
5
- // The Events API lists and retrieves the stored events of the account a request acts for: an event of a connected
6
- // account carries it ("Each event for a connected account contains a top-level `account` property that identifies the
7
- // connected account. Because the connected account owns the object that triggered the event, you must make API
8
- // requests for that object as the connected account", docs.stripe.com/connect/webhooks; the event's `account`: "The
9
- // connected account that originates the event", spec/openapi.json.gz), so a request with the Stripe-Account header
10
- // sees that account's events and one without it the platform's, those with no `account`. Where the documentation
11
- // stops and the twin decides: a platform request does not see its connected accounts' events.
12
- import { worldEnvValue } from '@volter/world-core';
13
- import { asBool } from "../stripe-twin.js";
14
- import { actingAccount } from "./ledger.js";
15
- import { at, created, fail, inRange, list, newest, where } from "./shared.js";
16
- const WE = 'webhook_endpoint';
17
- // The signing secret is the World's where the World set one. Stripe mints an endpoint's secret and the app is given it
18
- // (the dashboard, `stripe listen`); in a World the app's env is the World's, made at boot, so the World's value is the
19
- // one the app verifies with, and an endpoint the app registers is signed with it: the twin's decision, since Stripe
20
- // lets no one choose a secret. A Connect endpoint (`connect`) takes a Connect name first. Only a value the World sets
21
- // counts (worldEnvValue), never one the caller's shell passes through; with none (a twin outside a World) the twin
22
- // mints, as Stripe does.
23
- const ACCOUNT_SECRET_ENV = ['STRIPE_WEBHOOK_SECRET', 'STRIPE_WEBHOOK_SIGNING_SECRET', 'STRIPE_ENDPOINT_SECRET', 'STRIPE_WEBHOOK_SECRET_KEY', 'NEXT_PRIVATE_STRIPE_WEBHOOK_SECRET'];
24
- const CONNECT_SECRET_ENV = ['STRIPE_CONNECT_WEBHOOK_SECRET', 'STRIPE_WEBHOOK_SECRET_CONNECT', 'STRIPE_CONNECT_WEBHOOK_SIGNING_SECRET'];
25
- export function worldEndpointSecret(connect) {
26
- for (const name of connect ? [...CONNECT_SECRET_ENV, ...ACCOUNT_SECRET_ENV] : ACCOUNT_SECRET_ENV) {
27
- const value = worldEnvValue(name);
28
- if (value)
29
- return value;
30
- }
31
- return undefined;
32
- }
33
- const create = async (ctx) => {
34
- const params = ctx.params;
35
- const url = typeof params.url === 'string' ? params.url : '';
36
- if (!url)
37
- return fail(ctx, 'Missing required param: url.', 400, 'parameter_missing');
38
- const enabledEvents = Array.isArray(params.enabled_events) ? params.enabled_events.map(String) : typeof params.enabled_events === 'string' ? [params.enabled_events] : undefined;
39
- if (!enabledEvents || enabledEvents.length === 0)
40
- return fail(ctx, 'Missing required param: enabled_events.', 400, 'parameter_missing');
41
- const id = ctx.mint(WE);
42
- return ctx.reply(await created(ctx, WE, { ...params, id }, {
43
- url, enabled_events: enabledEvents, status: 'enabled', livemode: false, metadata: {},
44
- api_version: '2024-06-20', application: null, description: typeof params.description === 'string' ? params.description : null,
45
- secret: worldEndpointSecret(asBool(params.connect)) ?? `whsec_twin_${id}`,
46
- }));
47
- };
48
- // `disabled` switches delivery off (status disabled) and back on; it is a parameter, not a field
49
- const update = async (ctx) => {
50
- const id = at(ctx, 'webhook_endpoint');
51
- const we = ctx.get(WE, id);
52
- if (!we)
53
- return ctx.notFound(WE, id);
54
- const { disabled, ...fields } = { ...ctx.params };
55
- if (Array.isArray(ctx.params.enabled_events))
56
- fields.enabled_events = ctx.params.enabled_events.map(String);
57
- if (disabled !== undefined)
58
- return switchDelivery(ctx, id, we, fields, asBool(disabled));
59
- return ctx.reply(await ctx.write(WE, id, fields, 'webhook_endpoint.update'));
60
- };
61
- /** `disabled` switches delivery off or back on (docs.stripe.com/api/webhook_endpoints/update#update_webhook_endpoint-disabled). */
62
- async function switchDelivery(ctx, id, we, fields, off) {
63
- const status = off ? 'disabled' : 'enabled';
64
- const refused = ctx.legal(WE, 'status', 'PostWebhookEndpointsWebhookEndpoint', we.status, status, id);
65
- if (refused)
66
- return ctx.refuse(refused);
67
- return ctx.reply(await ctx.write(WE, id, { ...fields, status }, 'webhook_endpoint.update'));
68
- }
69
- /** Whether a stored event is the acting account's (no `account`: the platform's). */
70
- const ownEvent = (ctx, e) => (typeof e.account === 'string' ? e.account : undefined) === actingAccount(ctx);
71
- const listEvents = async (ctx) => list(ctx, 'event', where(ctx, newest(ctx, 'event').filter((e) => ownEvent(ctx, e)), {
72
- type: (e, v) => e.type === v,
73
- types: (e, v) => (Array.isArray(v) ? v.map(String) : [String(v)]).includes(String(e.type)),
74
- created: (e, v) => inRange(e.created, v),
75
- }));
76
- const retrieveEvent = async (ctx) => {
77
- const e = ctx.get('event', at(ctx, 'id'));
78
- return e && ownEvent(ctx, e) ? ctx.reply(e) : ctx.notFound('event', at(ctx, 'id'));
79
- };
80
- export const webhookEndpoints = {
81
- GetEvents: listEvents,
82
- GetEventsId: retrieveEvent,
83
- PostWebhookEndpoints: create,
84
- PostWebhookEndpointsWebhookEndpoint: update,
85
- };
@@ -1,55 +0,0 @@
1
- import { RateBudget, type RateBudgetDeclaration, type RateBudgetOptions, type RateBudgetReservation, type RateBudgetSnapshot } from '@volter/world-core';
2
- /** Rolling window, in ms. Spend older than this is pruned. */
3
- export declare const STRIPE_BUDGET_WINDOW_MS = 60000;
4
- /**
5
- * Weighted units allowed inside one window. 120/60s = 120 reads a minute (2/second) — 2% of
6
- * Stripe's documented live-mode 100/second and 8% of the 25/second a sandbox key or any single
7
- * endpoint gets.
8
- */
9
- export declare const STRIPE_BUDGET_CEILING = 120;
10
- /** Seconds. A `Retry-After` above this means the key is throttled hard — fail loudly, don't sleep. */
11
- export declare const STRIPE_BUDGET_MAX_RETRY_AFTER_S = 300;
12
- /** Per-call cost, keyed by `"<METHOD> <path>"`. See the header for what is documented vs. judged. */
13
- export declare const STRIPE_CALL_WEIGHTS: {
14
- /** `POST /v1/payouts` — documented at 15 creates/second, and the most irreversible object here. */
15
- readonly payout: 5;
16
- /** Any other `POST`/`DELETE` — creates charges, refunds, subscriptions, receipt e-mail. */
17
- readonly write: 2;
18
- /** Reads: list/retrieve. */
19
- readonly other: 1;
20
- };
21
- /** THE PACK'S DECLARATION — pure data, the only Stripe-specific thing in the whole budget. */
22
- export declare const STRIPE_RATE_BUDGET: RateBudgetDeclaration;
23
- /**
24
- * Price one call. The key is `"<METHOD> <path>"` — Stripe's executor carries filters as separate
25
- * `params` rather than in the path, so there is no query string to split off here; a `?` is still
26
- * handled defensively in case a caller inlines one. An unclassified endpoint costs `defaultWeight`.
27
- */
28
- export declare function stripeCallWeight(method: string, path: string): number;
29
- /** Where Stripe's ledger lives. Key-keyed and cwd-independent by default (limits attach to the
30
- * account behind the secret key, so a cwd-scoped ledger would hand the same key a fresh allowance
31
- * in every checkout, worktree and CI matrix leg); pass `root` for world-scoped accounting.
32
- *
33
- * A live key and a test key are different strings, so they get different ledgers — which matches
34
- * Stripe, whose live and sandbox limits are separate (100/s vs 25/s). */
35
- export declare function stripeBudgetPath(opts?: {
36
- root?: string;
37
- token?: string;
38
- } | string): string;
39
- /** Construction options for Stripe's budget. The vendor is fixed; everything else may only TIGHTEN. */
40
- export type StripeBudgetOptions = Omit<RateBudgetOptions, 'vendor'>;
41
- /**
42
- * Stripe's budget — the shared kernel guard bound to this vendor's declaration. A real subclass,
43
- * not an alias, so `budget instanceof StripeBudget` in `liveStripeExecute` means "a budget that
44
- * accounts against STRIPE's ledger under STRIPE's ceiling": another vendor's `RateBudget` (with its
45
- * own, possibly larger, ceiling) is NOT assignable there.
46
- */
47
- export declare class StripeBudget extends RateBudget {
48
- constructor(opts?: StripeBudgetOptions);
49
- }
50
- /** The typed refusal. One error class shared with every other vendor's budget; `err.vendor` says
51
- * which one refused, and `err.kind` says why. */
52
- export { RateBudgetError as StripeBudgetError } from '@volter/world-core';
53
- export type { RateBudgetErrorKind as StripeBudgetErrorKind } from '@volter/world-core';
54
- export type StripeBudgetReservation = RateBudgetReservation;
55
- export type StripeBudgetSnapshot = RateBudgetSnapshot;