@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,493 +0,0 @@
1
- import { ACCOUNT_TYPES, accountCapabilities, accountRequirements, accountSettings, asBool, PLATFORM_ACCOUNT_ID } from "../stripe-twin.js";
2
- import { currentlyDue, kindOf } from "../screens/onboarding.js";
3
- import { at, created, externalList, fail, list, newest, path, syncExternals } from "./shared.js";
4
- import { OAUTH_CONNECTIONS } from "../stripe-shared.js";
5
- const accountMissing = (ctx, id, status = 404) => fail(ctx, `No such account: '${id}'`, status, 'resource_missing');
6
- /** The account, tombstones included where the hand-written routes looked past a deletion. */
7
- const accountRow = (ctx, id) => ctx.row('account', id, { withDeleted: true });
8
- // the platform's own account: stored once it is written, otherwise Stripe's default. It "controls itself" (controller
9
- // type `account`, docs.stripe.com/api/accounts/object), is fully onboarded with nothing due, and takes card payments
10
- // and transfers. Where the documentation stops and the twin decides: it was created as the World began (2026-01-01),
11
- // and its bank account, which its automatic payouts reach, is not modelled, so it lists none.
12
- const PLATFORM_CREATED = 1_767_225_600;
13
- /** The platform's own account as Stripe's default has it, before anything is written to it. */
14
- export const platformAccountDefault = () => ({
15
- object: 'account', id: PLATFORM_ACCOUNT_ID, type: 'standard', country: 'US', default_currency: 'usd', created: PLATFORM_CREATED,
16
- charges_enabled: true, payouts_enabled: true, details_submitted: true, email: null, metadata: {},
17
- capabilities: { card_payments: 'active', transfers: 'active' }, controller: { type: 'account' },
18
- requirements: { alternatives: [], current_deadline: null, currently_due: [], disabled_reason: null, errors: [], eventually_due: [], past_due: [], pending_verification: [] },
19
- future_requirements: { alternatives: [], current_deadline: null, currently_due: [], disabled_reason: null, errors: [], eventually_due: [], past_due: [], pending_verification: [] },
20
- external_accounts: externalList(PLATFORM_ACCOUNT_ID, []), tos_acceptance: { date: null, ip: null, user_agent: null }, business_profile: {},
21
- settings: accountSettings(undefined), livemode: false,
22
- });
23
- // GET /v1/account answers the account the request acts as: with the Stripe-Account header (or a connected account's OAuth
24
- // key, which acts as it: stripe-server.ts) that connected account, "Retrieves the details of an account"
25
- // (docs.stripe.com/api/accounts/retrieve; docs.stripe.com/connect/authentication), else the platform's own
26
- const platform = async (ctx) => {
27
- const acting = ctx.call.request.headers.get('stripe-account');
28
- const connected = acting && acting !== PLATFORM_ACCOUNT_ID ? ctx.get('account', acting) : undefined;
29
- // a Stripe-Account naming no account is refused as Stripe refuses a Stripe-Account the key cannot use (account_invalid,
30
- // docs.stripe.com/error-codes; stripe-server.ts revokedAccountRefused words it the same)
31
- if (acting && acting !== PLATFORM_ACCOUNT_ID && !connected)
32
- return fail(ctx, `The provided key does not have access to account '${acting}' (or that account does not exist). Application access may have been revoked.`, 403, 'account_invalid');
33
- return ctx.reply(connected ?? ctx.get('account', PLATFORM_ACCOUNT_ID) ?? platformAccountDefault());
34
- };
35
- /** A new Express account owes what its hosted onboarding will ask for (screens/onboarding.tsx; the US sets
36
- * docs.stripe.com/connect/required-verification-information lists), or, where the twin does not model the set, the
37
- * generic list. */
38
- function expressRequirements(params) {
39
- const kind = kindOf({ country: params.country ?? 'US', business_type: params.business_type ?? 'individual' });
40
- const base = accountRequirements();
41
- return kind ? { ...base, currently_due: currentlyDue(kind), eventually_due: currentlyDue(kind) } : base;
42
- }
43
- // the requested capabilities become Stripe's status map, and settings its canonical shape
44
- const create = async (ctx) => {
45
- const params = ctx.params;
46
- const type = typeof params.type === 'string' ? params.type : 'standard';
47
- if (!ACCOUNT_TYPES.has(type))
48
- return fail(ctx, 'Invalid account type: must be one of express, standard, or custom.', 400, 'parameter_invalid_string_enum');
49
- const { capabilities: _caps, settings: _settings, ...accountParams } = keptKyc(params);
50
- const id = ctx.mint('account');
51
- const made = await created(ctx, 'account', { ...accountParams, id, type }, {
52
- business_type: null, charges_enabled: false, payouts_enabled: false, details_submitted: false,
53
- capabilities: accountCapabilities(params), requirements: type === 'express' ? expressRequirements(params) : accountRequirements(),
54
- country: typeof params.country === 'string' ? params.country : 'US',
55
- default_currency: 'usd', email: params.email ?? null, metadata: {}, livemode: false,
56
- settings: accountSettings(params.settings), business_profile: {},
57
- controller: controllerOf(type), external_accounts: externalList(id, []),
58
- future_requirements: { alternatives: [], current_deadline: null, currently_due: [], disabled_reason: null, errors: [], eventually_due: [], past_due: [], pending_verification: [] },
59
- tos_acceptance: { date: null, ip: null, user_agent: null },
60
- });
61
- await review(ctx, String(made.id));
62
- return ctx.reply(ctx.get('account', String(made.id)));
63
- };
64
- /** The controller an account made with a `type` has: "Each of the three account types maps to values in the
65
- * `controller` hash", Standard to losses.payments `stripe`, fees.payer `account`, requirement_collection `stripe` and
66
- * a `full` dashboard, Express to `application`, `application_express`, `stripe` and `express`, Custom to
67
- * `application`, `application_custom`, `application` and `none`; each "type": "application", "is_controller": true
68
- * (docs.stripe.com/connect/migrate-to-controller-properties). */
69
- function controllerOf(type) {
70
- const [losses, payer, collection, dashboard] = type === 'express' ? ['application', 'application_express', 'stripe', 'express']
71
- : type === 'custom' ? ['application', 'application_custom', 'application', 'none'] : ['stripe', 'account', 'stripe', 'full'];
72
- return { type: 'application', is_controller: true, losses: { payments: losses }, fees: { payer }, requirement_collection: collection, stripe_dashboard: { type: dashboard } };
73
- }
74
- // connected accounts only: the platform's own is not one, and neither is an account whose OAuth connection was revoked,
75
- // which "can't be accessed by your platform in the Dashboard or through the API" (docs.stripe.com/connect/oauth-reference;
76
- // its connection row is OAUTH_CONNECTIONS, screens/connect-oauth.tsx)
77
- const listAccounts = async (ctx) => {
78
- const revoked = new Set(ctx.rowsRaw(OAUTH_CONNECTIONS).filter((c) => c.revoked === true).map((c) => c.id));
79
- return list(ctx, 'account', newest(ctx, 'account').filter((a) => a.id !== PLATFORM_ACCOUNT_ID && !revoked.has(a.id)));
80
- };
81
- /** What a Custom account still owes, from what the platform has given for it, as Stripe's requirements endpoint lists it
82
- * for a US account with no Stripe Dashboard and the full service agreement
83
- * (docs.stripe.com/_endpoint/get-requirements-for-setups, the data behind
84
- * docs.stripe.com/connect/required-verification-information). With transfers alone, a company owes business_profile.url,
85
- * company.name, an external account and tos_acceptance.date and .ip at once (capability_limit_amount -1: paused until
86
- * given) and company.tax_id before $3,000 of payouts (payout_limit_amount 300000); an individual owes the url, its
87
- * first and last name, the bank account and the terms at once, and its date of birth and ssn_last_4 before $3,000 of
88
- * payouts. Requesting card_payments adds business_profile.mcc and the entity's address at once (and an individual's
89
- * email and ssn_last_4). A company with card_payments owes, at once, business_profile.mcc, its address, that its owners
90
- * are provided, each owner's name and email, and its representative's name, email, address, title and ssn_last_4; and
91
- * in time its phone, its statement descriptor and its representative's date of birth and phone (the endpoint's answer
92
- * for US / dashboard none / full terms / company / card_payments and transfers, saved in scratch as
93
- * req-custom-company-cards-transfers.json: capability_limit_amount -1 for the first, none for the second). The
94
- * representative and the owners are the account's persons (relationship.representative, relationship.owner).
95
- * Where the documentation stops and the twin decides: what has no limit, or is owed before $3,000 of payouts, is
96
- * eventually_due and blocks nothing (the twin keeps no payout total against it); an owner field is met when every
97
- * person marked owner has it (none marked: met). */
98
- const at_path = (a, path) => path.split('.').reduce((v, k) => (v && typeof v === 'object' ? v[k] : undefined), a);
99
- const CARD_COMPANY_NOW = ['business_profile.mcc', 'company.address.line1', 'company.address.city', 'company.address.state', 'company.address.postal_code', 'company.owners_provided', 'owners.first_name', 'owners.last_name', 'owners.email', 'representative.first_name', 'representative.last_name', 'representative.email', 'representative.address.line1', 'representative.address.city', 'representative.address.state', 'representative.address.postal_code', 'representative.relationship.title', 'representative.ssn_last_4'];
100
- const CARD_COMPANY_LATER = ['company.phone', 'settings.payments.statement_descriptor', 'representative.dob.day', 'representative.dob.month', 'representative.dob.year', 'representative.phone'];
101
- const CARD_INDIVIDUAL_NOW = ['business_profile.mcc', 'individual.address.line1', 'individual.address.city', 'individual.address.state', 'individual.address.postal_code', 'individual.email', 'individual.ssn_last_4'];
102
- /** A field only card_payments asks for (the transfers capability's requirements leave it out). */
103
- const cardOnly = (field) => [...CARD_COMPANY_NOW, ...CARD_COMPANY_LATER, ...CARD_INDIVIDUAL_NOW].includes(field);
104
- const personHas = (p, field) => {
105
- if (field === 'ssn_last_4')
106
- return p.ssn_last_4_provided === true;
107
- const v = at_path(p, field);
108
- return v !== undefined && v !== null && v !== '';
109
- };
110
- const met = (a, bank, field, persons = []) => {
111
- if (field === 'external_account')
112
- return bank;
113
- if (field.startsWith('representative.')) {
114
- const rep = persons.find((p) => p.relationship?.representative === true);
115
- return !!rep && personHas(rep, field.slice('representative.'.length));
116
- }
117
- if (field.startsWith('owners.'))
118
- return persons.filter((p) => p.relationship?.owner === true).every((p) => personHas(p, field.slice('owners.'.length)));
119
- if (field === 'company.tax_id')
120
- return at_path(a, 'company.tax_id_provided') === true;
121
- if (field === 'individual.ssn_last_4')
122
- return at_path(a, 'individual.ssn_last_4_provided') === true;
123
- const v = at_path(a, field);
124
- return v !== undefined && v !== null && v !== '';
125
- };
126
- function customRequirements(a, bank, persons = []) {
127
- const company = a.business_type === 'company';
128
- const cards = Object.keys(a.capabilities ?? {}).includes('card_payments');
129
- const now = ['business_profile.url', ...(company ? ['company.name'] : ['individual.first_name', 'individual.last_name']), 'external_account', 'tos_acceptance.date', 'tos_acceptance.ip'];
130
- if (cards)
131
- now.push(...(company ? CARD_COMPANY_NOW : CARD_INDIVIDUAL_NOW));
132
- const later = [...(company ? ['company.tax_id'] : ['individual.dob.day', 'individual.dob.month', 'individual.dob.year', 'individual.ssn_last_4']), ...(cards && company ? CARD_COMPANY_LATER : [])].filter((f) => !now.includes(f));
133
- return { now: now.filter((f) => !met(a, bank, f, persons)), later: later.filter((f) => !met(a, bank, f, persons)) };
134
- }
135
- /** A request's company or individual as Stripe keeps it: a tax id or SSN given is kept only as provided (the Account
136
- * object answers company.tax_id_provided and individual.ssn_last_4_provided, never the numbers;
137
- * docs.stripe.com/api/accounts/object). */
138
- function keptKyc(params) {
139
- const out = { ...params };
140
- if (params.company && typeof params.company === 'object') {
141
- const { tax_id, ...company } = params.company;
142
- out.company = { ...company, ...(tax_id !== undefined && tax_id !== '' ? { tax_id_provided: true } : {}) };
143
- }
144
- if (params.individual && typeof params.individual === 'object') {
145
- const { ssn_last_4, id_number, ...individual } = params.individual;
146
- out.individual = { ...individual, ...(ssn_last_4 !== undefined && ssn_last_4 !== '' ? { ssn_last_4_provided: true } : {}), ...(id_number !== undefined && id_number !== '' ? { id_number_provided: true } : {}) };
147
- }
148
- return out;
149
- }
150
- /** Stripe's review of a Custom account once the platform gives it something: with nothing left due, its requested
151
- * capabilities become active and it can take charges and receive payouts; with something due again (its bank account
152
- * removed), they stop. Where the documentation stops and the twin decides: test-mode verification is immediate, and
153
- * it owes what customRequirements lists. An Express or Standard account is onboarded on Stripe's own pages. */
154
- async function review(ctx, id) {
155
- const account = ctx.get('account', id);
156
- if (account && account.type === 'custom')
157
- await reviewCustom(ctx, id, account);
158
- }
159
- /** The review of a Custom account (see review). */
160
- async function reviewCustom(ctx, id, account) {
161
- const bank = ctx.rows('external_account').some((e) => e.account === id);
162
- const persons = ctx.rows('person').filter((p) => p.account === id);
163
- const { now: due, later } = customRequirements(account, bank, persons);
164
- // one account, one review: "If a connected account has both card_payments and transfers, and the status of either one
165
- // is inactive, then both capabilities are disabled" (docs.stripe.com/connect/account-capabilities)
166
- const ready = due.length === 0;
167
- const capabilities = {};
168
- for (const [key, was] of Object.entries(account.capabilities ?? {})) {
169
- const to = ready ? 'active' : 'inactive';
170
- // Stripe's review moves each capability, as the machine declares it may
171
- if (was !== to)
172
- ctx.legal('capability', 'status', ctx.call.operation.id, String(was), to, key, 'vendor');
173
- capabilities[key] = to;
174
- }
175
- const requirements = { ...(account.requirements ?? {}), currently_due: due, eventually_due: [...due, ...later], past_due: [], disabled_reason: ready ? null : 'requirements.past_due', current_deadline: null };
176
- await ctx.write('account', id, { capabilities, requirements, charges_enabled: ready, payouts_enabled: ready, details_submitted: ready }, ready ? 'account.updated' : 'account.update');
177
- }
178
- // `type` cannot change; settings merge onto the existing ones
179
- const update = async (ctx) => {
180
- const id = at(ctx, 'account');
181
- const ex = ctx.get('account', id);
182
- if (!ex)
183
- return accountMissing(ctx, id);
184
- const { type: _drop, settings: rawSettings, ...rest } = keptKyc(ctx.params);
185
- if (rawSettings !== undefined)
186
- rest.settings = accountSettings(rawSettings, ex.settings);
187
- // a company or an individual given in part is laid over what the account holds
188
- for (const k of ['company', 'individual', 'business_profile', 'tos_acceptance'])
189
- if (rest[k] && typeof rest[k] === 'object' && ex[k] && typeof ex[k] === 'object')
190
- rest[k] = { ...ex[k], ...rest[k] };
191
- await ctx.write('account', id, rest, 'account.update');
192
- await review(ctx, id);
193
- return ctx.reply(ctx.get('account', id));
194
- };
195
- // a single-use Express dashboard link, not stored
196
- const loginLink = async (ctx) => {
197
- const id = at(ctx, 'account');
198
- if (!ctx.get('account', id))
199
- return accountMissing(ctx, id);
200
- return ctx.reply({ object: 'login_link', created: ctx.now(), url: `https://connect.twin.local/express/${id}` });
201
- };
202
- // ── persons on an account ──
203
- const personMissing = (ctx) => fail(ctx, `No such person: '${at(ctx, 'person')}'`, 404, 'resource_missing');
204
- const accountPerson = (ctx) => {
205
- const p = ctx.get('person', at(ctx, 'person'));
206
- return p && p.account === at(ctx, 'account') ? p : undefined;
207
- };
208
- /** A person's details as Stripe keeps them: an SSN or ID number given is kept only as provided (the Person object
209
- * answers ssn_last_4_provided and id_number_provided, never the numbers; docs.stripe.com/api/persons/object). */
210
- function keptPerson(params, was = {}) {
211
- const { ssn_last_4, id_number, ...rest } = params;
212
- const out = { ...rest, ...(ssn_last_4 !== undefined && ssn_last_4 !== '' ? { ssn_last_4_provided: true } : {}), ...(id_number !== undefined && id_number !== '' ? { id_number_provided: true } : {}) };
213
- // a relationship, address or date of birth given in part is laid over what the person holds
214
- for (const k of ['relationship', 'address', 'dob'])
215
- if (out[k] && typeof out[k] === 'object' && was[k] && typeof was[k] === 'object')
216
- out[k] = { ...was[k], ...out[k] };
217
- return out;
218
- }
219
- const RELATIONSHIP = { director: false, executive: false, owner: false, representative: false, percent_ownership: null, title: null };
220
- // a person given or changed is part of the account's review: its representative and owners are what card_payments asks for
221
- const createPerson = async (ctx) => {
222
- const account = at(ctx, 'account');
223
- if (!accountRow(ctx, account))
224
- return accountMissing(ctx, account);
225
- const kept = keptPerson(ctx.params, { relationship: RELATIONSHIP });
226
- const body = await created(ctx, 'person', { ...kept, account }, {
227
- relationship: RELATIONSHIP,
228
- requirements: { currently_due: [], eventually_due: [], past_due: [], pending_verification: [], errors: [], alternatives: [] },
229
- verification: { status: 'unverified', document: { back: null, details: null, details_code: null, front: null } },
230
- metadata: {}, ssn_last_4_provided: false, id_number_provided: false,
231
- });
232
- await review(ctx, account);
233
- return ctx.reply(body);
234
- };
235
- const person = async (ctx) => {
236
- const p = accountPerson(ctx);
237
- return p ? ctx.reply(p) : personMissing(ctx);
238
- };
239
- const updatePerson = async (ctx) => {
240
- const was = accountPerson(ctx);
241
- if (!was)
242
- return personMissing(ctx);
243
- const body = await ctx.write('person', at(ctx, 'person'), keptPerson(ctx.params, was), 'person.update');
244
- await review(ctx, at(ctx, 'account'));
245
- return ctx.reply(body);
246
- };
247
- const deletePerson = async (ctx) => {
248
- if (!accountPerson(ctx))
249
- return personMissing(ctx);
250
- const id = at(ctx, 'person');
251
- await ctx.write('person', id, { deleted: true }, 'person.delete');
252
- await review(ctx, at(ctx, 'account'));
253
- return ctx.reply({ id, object: 'person', deleted: true });
254
- };
255
- // ── capabilities: the account's capability map is the truth; requesting one leaves it pending ──
256
- /** A capability as its account stands: its status, and the account's requirements that capability asks for (transfers
257
- * leaves out what only card_payments asks for). Where the documentation stops and the twin decides: the account-wide
258
- * fields (the bank account, the terms) belong to every capability. */
259
- const capabilityBody = (acct, id, status, requested = true, requestedAt = null) => {
260
- const req = acct.requirements ?? {};
261
- const mine = (list) => (Array.isArray(list) ? list : []).filter((f) => id === 'card_payments' || !cardOnly(f));
262
- const due = mine(req.currently_due);
263
- return {
264
- id, object: 'capability', account: acct.id, status, requested, requested_at: requestedAt,
265
- requirements: { currently_due: due, eventually_due: mine(req.eventually_due), past_due: [], pending_verification: [], errors: [], alternatives: [], current_deadline: null, disabled_reason: due.length ? 'requirements.past_due' : null },
266
- };
267
- };
268
- const capabilities = async (ctx) => {
269
- const account = at(ctx, 'account');
270
- const acct = ctx.get('account', account);
271
- if (!acct)
272
- return accountMissing(ctx, account);
273
- const caps = acct.capabilities ?? {};
274
- return ctx.reply({ object: 'list', url: path(ctx), has_more: false, data: Object.entries(caps).map(([id, status]) => capabilityBody(acct, id, status)) });
275
- };
276
- const capability = async (ctx) => {
277
- const account = at(ctx, 'account');
278
- const acct = ctx.get('account', account);
279
- if (!acct)
280
- return accountMissing(ctx, account);
281
- const caps = acct.capabilities ?? {};
282
- const cap = at(ctx, 'capability');
283
- return cap in caps ? ctx.reply(capabilityBody(acct, cap, caps[cap])) : fail(ctx, `No such capability: '${cap}'`, 404, 'resource_missing');
284
- };
285
- const requestCapability = async (ctx) => {
286
- const account = at(ctx, 'account');
287
- const acct = ctx.get('account', account);
288
- if (!acct)
289
- return accountMissing(ctx, account);
290
- const caps = { ...(acct.capabilities ?? {}) };
291
- const cap = at(ctx, 'capability');
292
- const requested = ctx.params.requested === undefined ? true : asBool(ctx.params.requested);
293
- const to = requested ? 'pending' : 'inactive';
294
- const refused = ctx.legal('capability', 'status', 'PostAccountsAccountCapabilitiesCapability', String(caps[cap] ?? 'unrequested'), to, cap);
295
- if (refused)
296
- return ctx.refuse(refused);
297
- caps[cap] = to;
298
- await ctx.write('account', account, { capabilities: caps }, 'account.updated');
299
- // Stripe reviews the account against what the capability asks for (review)
300
- await review(ctx, account);
301
- const now = ctx.get('account', account);
302
- return ctx.reply(capabilityBody(now, cap, now.capabilities[cap], requested, requested ? ctx.now() : null));
303
- };
304
- // ── external accounts: a payout destination from a token or a bank_account hash ──
305
- const externalMissing = (ctx) => fail(ctx, `No such external account: '${at(ctx, 'id')}'`, 404, 'resource_missing');
306
- const accountExternal = (ctx) => {
307
- const e = ctx.get('external_account', at(ctx, 'id'));
308
- return e && e.account === at(ctx, 'account') ? e : undefined;
309
- };
310
- /** Whether the platform may create, update or delete an account's external accounts: "A platform can create, update, or
311
- * delete external accounts only for connected accounts without access to either the full Stripe or Express Dashboard
312
- * and where the platform is responsible for negative balances" (docs.stripe.com/connect/payouts-bank-accounts); it can
313
- * still view an Express account's ("A platform can view the external accounts of connected accounts that don’t have
314
- * access to the full Stripe Dashboard"). Where the documentation stops and the twin decides: the refusal. Stripe's
315
- * pages give no error code for it; the twin answers 403, which the errors page gives as "The API key doesn’t have
316
- * permissions to perform the request" (docs.stripe.com/api/errors), with the twin's own wording. The create page says
317
- * it too: "You can only specify connected accounts where account.controller.requirement_collection is `application`"
318
- * (docs.stripe.com/api/external_account_bank_accounts/create). */
319
- function refuseExternalWrite(ctx, account) {
320
- const row = accountRow(ctx, account);
321
- const controller = row?.controller ?? controllerOf(String(row?.type ?? 'standard'));
322
- const dashboard = String((controller.stripe_dashboard?.type) ?? '');
323
- const losses = String((controller.losses?.payments) ?? '');
324
- if (dashboard === 'none' && losses === 'application')
325
- return undefined;
326
- return ctx.refuse({ status: 403, message: `This application does not have the required permissions to manage the external accounts of account '${account}': they can only be managed through the account's ${dashboard === 'express' ? 'Express' : 'Stripe'} Dashboard.` });
327
- }
328
- const createExternal = async (ctx) => {
329
- const account = at(ctx, 'account');
330
- if (!accountRow(ctx, account))
331
- return accountMissing(ctx, account);
332
- const forbidden = refuseExternalWrite(ctx, account);
333
- if (forbidden)
334
- return forbidden;
335
- const ext = ctx.params.external_account ?? ctx.params.bank_account;
336
- if (ext === undefined)
337
- return fail(ctx, 'Missing required param: external_account.', 400, 'parameter_missing');
338
- const ba = typeof ext === 'object' ? ext : {};
339
- const acctNum = typeof ba.account_number === 'string' ? ba.account_number.replace(/\D/g, '') : '';
340
- const currency = String(ba.currency ?? 'usd');
341
- const sameCurrency = ctx.rows('external_account').filter((e) => e.account === account && String(e.currency ?? 'usd') === currency);
342
- const isDefault = sameCurrency.length === 0 || ctx.params.default_for_currency === true || ctx.params.default_for_currency === 'true';
343
- const made = await created(ctx, 'external_account', { account }, {
344
- account_holder_name: ba.account_holder_name ?? null,
345
- account_holder_type: ba.account_holder_type ?? null, bank_name: 'STRIPE TEST BANK',
346
- country: ba.country ?? 'US', currency,
347
- fingerprint: 'twin_ext_fp', last4: acctNum ? acctNum.slice(-4) : '6789',
348
- routing_number: ba.routing_number ?? '110000000', status: 'new', metadata: {},
349
- // "When set to true, or if this is the first external account added in this currency, this account becomes the
350
- // default external account for its currency" (docs.stripe.com/api/external_account_bank_accounts/create)
351
- default_for_currency: isDefault,
352
- ...(ctx.params.metadata && typeof ctx.params.metadata === 'object' ? { metadata: ctx.params.metadata } : {}),
353
- });
354
- if (isDefault)
355
- for (const other of sameCurrency)
356
- if (other.default_for_currency === true)
357
- await ctx.write('external_account', String(other.id), { default_for_currency: false }, 'external_account.update');
358
- await syncExternals(ctx, account);
359
- await review(ctx, account);
360
- return ctx.reply(made);
361
- };
362
- const externals = async (ctx) => {
363
- const account = at(ctx, 'account');
364
- if (!accountRow(ctx, account))
365
- return accountMissing(ctx, account);
366
- return list(ctx, 'external_account', newest(ctx, 'external_account').filter((e) => e.account === account));
367
- };
368
- const external = async (ctx) => {
369
- const e = accountExternal(ctx);
370
- return e ? ctx.reply(e) : externalMissing(ctx);
371
- };
372
- const deleteExternal = async (ctx) => {
373
- if (!accountExternal(ctx))
374
- return externalMissing(ctx);
375
- const forbidden = refuseExternalWrite(ctx, at(ctx, 'account'));
376
- if (forbidden)
377
- return forbidden;
378
- const id = at(ctx, 'id');
379
- await ctx.write('external_account', id, { deleted: true }, 'external_account.delete');
380
- await syncExternals(ctx, at(ctx, 'account'));
381
- await review(ctx, at(ctx, 'account'));
382
- return ctx.reply({ id, object: 'bank_account', deleted: true });
383
- };
384
- // ── hosted onboarding links and embedded-component sessions ──
385
- const accountLink = async (ctx) => {
386
- const account = typeof ctx.params.account === 'string' ? ctx.params.account : '';
387
- if (!account)
388
- return fail(ctx, 'Missing required param: account.', 400, 'parameter_missing');
389
- if (!ctx.get('account', account))
390
- return accountMissing(ctx, account, 400);
391
- const linkType = typeof ctx.params.type === 'string' ? ctx.params.type : '';
392
- if (linkType !== 'account_onboarding' && linkType !== 'account_update')
393
- return fail(ctx, 'Invalid account link type: must be account_onboarding or account_update.', 400, 'parameter_invalid_string_enum');
394
- // the owner is sent back to return_url when done, and to refresh_url for a new link once this one is used or expired
395
- for (const k of ['refresh_url', 'return_url'])
396
- if (typeof ctx.params[k] !== 'string' || !ctx.params[k])
397
- return fail(ctx, `Missing required param: ${k}.`, 400, 'parameter_missing');
398
- const now = Number(ctx.now());
399
- const id = ctx.mint('account_link');
400
- const link = { object: 'account_link', created: now, expires_at: now + 300, url: `https://connect.stripe.com/setup/${id}` };
401
- await ctx.write('account_link', id, { ...link, account, type: linkType, refresh_url: ctx.params.refresh_url, return_url: ctx.params.return_url, used: false }, 'account_link.create');
402
- return ctx.reply(link);
403
- };
404
- // a session is identified by its client_secret: the row is kept for traceability, the answer has no id
405
- /** Every embedded component an account session answers (the served spec requires all of them), each enabled only when
406
- * the request enables it, with its features: what the request gives, else the spec's stated default, "The default
407
- * value for this feature is `true`" (external_account_collection); disable_stripe_user_authentication "the opposite of
408
- * the `external_account_collection` value"; edit_payout_schedule and standard_payouts "Defaults to `true` when
409
- * `controller.losses.payments` is set to `stripe` for the account, otherwise `false`"; capture_payments, dispute_management
410
- * and refund_management "true by default"; destination_on_behalf_of_charge_management "false by default";
411
- * smart_disputes_management "Defaults to the value of `dispute_management`". Where the documentation stops and the twin
412
- * decides: instant_payouts (described as `enabled` "when Stripe is responsible for negative account balances", typed
413
- * boolean) is true exactly then, and the Issuing and financial-account features, which state no default, are false. */
414
- const SESSION_COMPONENTS = {
415
- account_management: ['external_account_collection', 'disable_stripe_user_authentication'],
416
- account_onboarding: ['external_account_collection', 'disable_stripe_user_authentication'],
417
- balance_report: [], documents: [], payout_details: [], payout_reconciliation_report: [], payouts_list: [], tax_registrations: [], tax_settings: [],
418
- balances: ['external_account_collection', 'disable_stripe_user_authentication', 'edit_payout_schedule', 'instant_payouts', 'standard_payouts'],
419
- payouts: ['external_account_collection', 'disable_stripe_user_authentication', 'edit_payout_schedule', 'instant_payouts', 'standard_payouts'],
420
- disputes_list: ['capture_payments', 'destination_on_behalf_of_charge_management', 'dispute_management', 'refund_management', 'smart_disputes_management'],
421
- payment_details: ['capture_payments', 'destination_on_behalf_of_charge_management', 'dispute_management', 'refund_management', 'smart_disputes_management'],
422
- payments: ['capture_payments', 'destination_on_behalf_of_charge_management', 'dispute_management', 'refund_management', 'smart_disputes_management'],
423
- payment_disputes: ['destination_on_behalf_of_charge_management', 'dispute_management', 'refund_management', 'smart_disputes_management'],
424
- financial_account: ['external_account_collection', 'disable_stripe_user_authentication', 'send_money', 'transfer_balance'],
425
- financial_account_transactions: ['card_spend_dispute_management'],
426
- instant_payouts_promotion: ['external_account_collection', 'disable_stripe_user_authentication', 'instant_payouts'],
427
- issuing_card: ['card_management', 'card_spend_dispute_management', 'cardholder_management', 'spend_control_management'],
428
- issuing_cards_list: ['card_management', 'card_spend_dispute_management', 'cardholder_management', 'disable_stripe_user_authentication', 'spend_control_management'],
429
- notification_banner: ['external_account_collection', 'disable_stripe_user_authentication'],
430
- payment_method_settings: ['disable_stripe_user_authentication'],
431
- };
432
- function sessionComponents(account, given) {
433
- const stripeLosses = (account.controller?.losses?.payments) === 'stripe';
434
- const out = {};
435
- for (const [name, featureNames] of Object.entries(SESSION_COMPONENTS)) {
436
- const c = given[name] && typeof given[name] === 'object' ? given[name] : {};
437
- const asked = c.features && typeof c.features === 'object' ? c.features : {};
438
- const f = {};
439
- const val = (k, fallback) => (asked[k] !== undefined ? asBool(asked[k]) : fallback);
440
- for (const k of featureNames) {
441
- if (k === 'external_account_collection')
442
- f[k] = val(k, true);
443
- else if (k === 'disable_stripe_user_authentication')
444
- f[k] = val(k, !val('external_account_collection', true));
445
- else if (k === 'edit_payout_schedule' || k === 'standard_payouts' || k === 'instant_payouts')
446
- f[k] = val(k, stripeLosses);
447
- else if (k === 'capture_payments' || k === 'dispute_management' || k === 'refund_management')
448
- f[k] = val(k, true);
449
- else if (k === 'smart_disputes_management')
450
- f[k] = val(k, val('dispute_management', true));
451
- else
452
- f[k] = val(k, false);
453
- }
454
- out[name] = { enabled: c.enabled !== undefined ? asBool(c.enabled) : false, features: f };
455
- }
456
- return out;
457
- }
458
- const accountSession = async (ctx) => {
459
- const account = typeof ctx.params.account === 'string' ? ctx.params.account : '';
460
- if (!account)
461
- return fail(ctx, 'Missing required param: account.', 400, 'parameter_missing');
462
- if (!ctx.get('account', account))
463
- return accountMissing(ctx, account, 400);
464
- const comps = ctx.params.components && typeof ctx.params.components === 'object' ? ctx.params.components : undefined;
465
- if (!comps || Object.keys(comps).length === 0)
466
- return fail(ctx, 'Missing required param: components.', 400, 'parameter_missing');
467
- const components = sessionComponents(ctx.get('account', account), comps);
468
- const now = Number(ctx.now());
469
- const seq = ctx.rowsRaw('account_session', { withDeleted: true }).length + 1;
470
- const secret = `_twin_acct_sess_${seq}_secret`;
471
- await created(ctx, 'account_session', { id: `accts_twin_${seq}`, account }, { livemode: false, client_secret: secret, expires_at: now + 3600, components });
472
- return ctx.reply({ object: 'account_session', account, client_secret: secret, expires_at: now + 3600, components, livemode: false });
473
- };
474
- export const connect = {
475
- GetAccount: platform,
476
- PostAccounts: create,
477
- GetAccounts: listAccounts,
478
- PostAccountsAccount: update,
479
- PostAccountsAccountLoginLinks: loginLink,
480
- PostAccountsAccountPersons: createPerson,
481
- GetAccountsAccountPersonsPerson: person,
482
- PostAccountsAccountPersonsPerson: updatePerson,
483
- DeleteAccountsAccountPersonsPerson: deletePerson,
484
- GetAccountsAccountCapabilities: capabilities,
485
- GetAccountsAccountCapabilitiesCapability: capability,
486
- PostAccountsAccountCapabilitiesCapability: requestCapability,
487
- PostAccountsAccountExternalAccounts: createExternal,
488
- GetAccountsAccountExternalAccounts: externals,
489
- GetAccountsAccountExternalAccountsId: external,
490
- DeleteAccountsAccountExternalAccountsId: deleteExternal,
491
- PostAccountLinks: accountLink,
492
- PostAccountSessions: accountSession,
493
- };
@@ -1,2 +0,0 @@
1
- import type { Semantics } from '@volter/world-core';
2
- export declare const creditNotes: Record<string, Semantics>;