@volter/twin-stripe 2.0.37 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (442) hide show
  1. package/README.md +82 -207
  2. package/dist/generated/pack-facts.json +94 -0
  3. package/dist/spec/SOURCE.md +14 -0
  4. package/dist/spec/fixtures3.json.gz +0 -0
  5. package/dist/spec/openapi.json.gz +0 -0
  6. package/dist/spec/patches.json +34 -0
  7. package/dist/spec/sources.json +378 -0
  8. package/dist/src/cli.js +12 -30
  9. package/dist/src/engine/after-payment.d.ts +9 -0
  10. package/dist/src/engine/after-payment.js +28 -0
  11. package/dist/src/engine/apps-secrets.d.ts +1 -0
  12. package/dist/src/engine/apps-secrets.js +3 -0
  13. package/dist/src/engine/balance.d.ts +5 -0
  14. package/dist/src/engine/balance.js +15 -0
  15. package/dist/src/engine/billing.d.ts +5 -0
  16. package/dist/src/engine/billing.js +6 -0
  17. package/dist/src/engine/charges.d.ts +6 -0
  18. package/dist/src/engine/charges.js +13 -0
  19. package/dist/src/engine/checkout.d.ts +24 -0
  20. package/dist/src/engine/checkout.js +30 -0
  21. package/dist/src/engine/common.d.ts +19 -0
  22. package/dist/src/engine/common.js +32 -0
  23. package/dist/src/{screens → engine}/connect-settings.d.ts +1 -7
  24. package/dist/src/engine/connect-settings.js +26 -0
  25. package/dist/src/engine/connect.d.ts +66 -0
  26. package/dist/src/engine/connect.js +189 -0
  27. package/dist/src/engine/coupons.d.ts +0 -0
  28. package/dist/src/engine/coupons.js +5 -0
  29. package/dist/src/engine/credit-notes.d.ts +1 -0
  30. package/dist/src/engine/credit-notes.js +5 -0
  31. package/dist/src/engine/customers.d.ts +12 -0
  32. package/dist/src/engine/customers.js +30 -0
  33. package/dist/src/engine/display.d.ts +14 -0
  34. package/dist/src/engine/display.js +16 -0
  35. package/dist/src/engine/disputes.d.ts +0 -0
  36. package/dist/src/engine/disputes.js +9 -0
  37. package/dist/src/engine/entitlements.d.ts +1 -0
  38. package/dist/src/engine/entitlements.js +4 -0
  39. package/dist/src/engine/ephemeral-keys.d.ts +0 -0
  40. package/dist/src/engine/ephemeral-keys.js +4 -0
  41. package/dist/src/engine/files.d.ts +18 -0
  42. package/dist/src/engine/files.js +33 -0
  43. package/dist/src/engine/front.d.ts +5 -0
  44. package/dist/src/engine/front.js +25 -0
  45. package/dist/src/engine/invoices.d.ts +24 -0
  46. package/dist/src/engine/invoices.js +57 -0
  47. package/dist/src/engine/issuing.d.ts +35 -0
  48. package/dist/src/engine/issuing.js +45 -0
  49. package/dist/src/engine/ledger.d.ts +9 -0
  50. package/dist/src/engine/ledger.js +9 -0
  51. package/dist/src/engine/oauth.d.ts +4 -0
  52. package/dist/src/engine/oauth.js +25 -0
  53. package/dist/src/engine/onboarding.d.ts +13 -0
  54. package/dist/src/engine/onboarding.js +42 -0
  55. package/dist/src/{stripe-params.d.ts → engine/params.d.ts} +20 -3
  56. package/dist/src/{stripe-params.js → engine/params.js} +7 -60
  57. package/dist/src/engine/payment-intents.d.ts +10 -0
  58. package/dist/src/engine/payment-intents.js +27 -0
  59. package/dist/src/engine/payment-links.d.ts +1 -0
  60. package/dist/src/engine/payment-links.js +5 -0
  61. package/dist/src/engine/payment-methods.d.ts +16 -0
  62. package/dist/src/engine/payment-methods.js +22 -0
  63. package/dist/src/engine/plans.d.ts +6 -0
  64. package/dist/src/engine/plans.js +26 -0
  65. package/dist/src/engine/platform.d.ts +39 -0
  66. package/dist/src/engine/platform.js +34 -0
  67. package/dist/src/engine/products.d.ts +0 -0
  68. package/dist/src/engine/products.js +4 -0
  69. package/dist/src/engine/radar.d.ts +2 -0
  70. package/dist/src/engine/radar.js +5 -0
  71. package/dist/src/engine/refunds.d.ts +1 -0
  72. package/dist/src/engine/refunds.js +28 -0
  73. package/dist/src/engine/renewals.d.ts +36 -0
  74. package/dist/src/engine/renewals.js +65 -0
  75. package/dist/src/engine/setup-intents.d.ts +1 -0
  76. package/dist/src/engine/setup-intents.js +4 -0
  77. package/dist/src/{stripe-twin.d.ts → engine/stripe.d.ts} +11 -39
  78. package/dist/src/{stripe-twin.js → engine/stripe.js} +25 -310
  79. package/dist/src/engine/subscription-schedules.d.ts +3 -0
  80. package/dist/src/engine/subscription-schedules.js +1 -0
  81. package/dist/src/engine/subscriptions.d.ts +12 -0
  82. package/dist/src/engine/subscriptions.js +31 -0
  83. package/dist/src/engine/tax.d.ts +7 -0
  84. package/dist/src/engine/tax.js +28 -0
  85. package/dist/src/engine/terminal.d.ts +4 -0
  86. package/dist/src/engine/terminal.js +20 -0
  87. package/dist/src/engine/test-clocks.d.ts +5 -0
  88. package/dist/src/engine/test-clocks.js +9 -0
  89. package/dist/src/engine/tokens.d.ts +7 -0
  90. package/dist/src/engine/tokens.js +20 -0
  91. package/dist/src/engine/transfers.d.ts +2 -0
  92. package/dist/src/engine/transfers.js +1 -0
  93. package/dist/src/engine/treasury.d.ts +23 -0
  94. package/dist/src/engine/treasury.js +45 -0
  95. package/dist/src/{stripe-version.js → engine/version.js} +4 -3
  96. package/dist/src/engine/webhook-endpoints.d.ts +1 -0
  97. package/dist/src/engine/webhook-endpoints.js +12 -0
  98. package/dist/src/engine/webhooks.d.ts +31 -0
  99. package/dist/src/engine/webhooks.js +68 -0
  100. package/dist/src/fetch.d.ts +2 -0
  101. package/dist/src/fetch.js +26 -0
  102. package/dist/src/generated/surface.gen.json +1 -1
  103. package/dist/src/generated/ui.gen.json +1 -1
  104. package/dist/src/index.d.ts +5 -14
  105. package/dist/src/index.js +8 -75
  106. package/dist/src/manifest.js +232 -758
  107. package/dist/src/screens/billing-portal.d.ts +3 -0
  108. package/dist/src/screens/{portal.js → billing-portal.js} +28 -54
  109. package/dist/src/screens/checkout.d.ts +2 -31
  110. package/dist/src/screens/checkout.js +32 -121
  111. package/dist/src/screens/connect-oauth.d.ts +3 -27
  112. package/dist/src/screens/connect-oauth.js +51 -132
  113. package/dist/src/screens/connect-onboarding.d.ts +3 -0
  114. package/dist/src/screens/{onboarding.js → connect-onboarding.js} +36 -102
  115. package/dist/src/screens/dashboard.d.ts +3 -0
  116. package/dist/src/screens/dashboard.js +117 -0
  117. package/dist/src/screens/shared.d.ts +27 -0
  118. package/dist/src/screens/shared.js +87 -0
  119. package/dist/src/screens/stripe-js.d.ts +3 -0
  120. package/dist/src/screens/stripe-js.js +135 -0
  121. package/dist/src/semantics/account_links.d.ts +2 -0
  122. package/dist/src/semantics/account_links.js +22 -0
  123. package/dist/src/semantics/accounts.d.ts +4 -0
  124. package/dist/src/semantics/accounts.js +38 -0
  125. package/dist/src/semantics/apps.d.ts +4 -0
  126. package/dist/src/semantics/{apps-secrets.js → apps.js} +14 -26
  127. package/dist/src/semantics/around.d.ts +2 -0
  128. package/dist/src/semantics/around.js +16 -0
  129. package/dist/src/semantics/balance.d.ts +2 -11
  130. package/dist/src/semantics/balance.js +3 -194
  131. package/dist/src/semantics/balance_transactions.d.ts +2 -0
  132. package/dist/src/semantics/balance_transactions.js +15 -0
  133. package/dist/src/semantics/billing_portal.d.ts +5 -0
  134. package/dist/src/semantics/billing_portal.js +42 -0
  135. package/dist/src/semantics/charges.d.ts +3 -28
  136. package/dist/src/semantics/charges.js +5 -202
  137. package/dist/src/semantics/checkout.d.ts +3 -20
  138. package/dist/src/semantics/checkout.js +8 -261
  139. package/dist/src/semantics/clock.d.ts +2 -0
  140. package/dist/src/semantics/clock.js +21 -0
  141. package/dist/src/semantics/coupons.d.ts +2 -6
  142. package/dist/src/semantics/coupons.js +2 -60
  143. package/dist/src/semantics/customers.d.ts +6 -6
  144. package/dist/src/semantics/customers.js +27 -387
  145. package/dist/src/semantics/disputes.d.ts +2 -2
  146. package/dist/src/semantics/disputes.js +3 -49
  147. package/dist/src/semantics/doors.d.ts +23 -0
  148. package/dist/src/semantics/doors.js +73 -0
  149. package/dist/src/semantics/entitlements.d.ts +2 -2
  150. package/dist/src/semantics/entitlements.js +5 -50
  151. package/dist/src/semantics/events.d.ts +12 -0
  152. package/dist/src/semantics/events.js +36 -0
  153. package/dist/src/semantics/index.d.ts +2 -0
  154. package/dist/src/semantics/index.js +107 -0
  155. package/dist/src/semantics/invoice_payments.d.ts +2 -0
  156. package/dist/src/semantics/invoice_payments.js +12 -0
  157. package/dist/src/semantics/invoiceitems.d.ts +3 -0
  158. package/dist/src/semantics/invoiceitems.js +59 -0
  159. package/dist/src/semantics/invoices.d.ts +16 -18
  160. package/dist/src/semantics/invoices.js +118 -444
  161. package/dist/src/semantics/payment_intents.d.ts +4 -0
  162. package/dist/src/semantics/payment_intents.js +79 -0
  163. package/dist/src/semantics/payment_methods.d.ts +5 -0
  164. package/dist/src/semantics/payment_methods.js +39 -0
  165. package/dist/src/semantics/payouts.d.ts +2 -0
  166. package/dist/src/semantics/payouts.js +21 -0
  167. package/dist/src/semantics/prices.d.ts +4 -0
  168. package/dist/src/semantics/prices.js +37 -0
  169. package/dist/src/semantics/products.d.ts +6 -2
  170. package/dist/src/semantics/products.js +15 -130
  171. package/dist/src/semantics/promotion_codes.d.ts +3 -0
  172. package/dist/src/semantics/promotion_codes.js +35 -0
  173. package/dist/src/semantics/radar.d.ts +2 -2
  174. package/dist/src/semantics/radar.js +5 -74
  175. package/dist/src/semantics/refunds.d.ts +3 -9
  176. package/dist/src/semantics/refunds.js +6 -192
  177. package/dist/src/semantics/setup_intents.d.ts +3 -0
  178. package/dist/src/semantics/{setup-intents.js → setup_intents.js} +10 -53
  179. package/dist/src/semantics/shared.d.ts +822 -47
  180. package/dist/src/semantics/shared.js +3044 -78
  181. package/dist/src/semantics/states.d.ts +531 -0
  182. package/dist/src/semantics/states.js +852 -0
  183. package/dist/src/semantics/subscription_items.d.ts +5 -0
  184. package/dist/src/semantics/subscription_items.js +55 -0
  185. package/dist/src/semantics/subscription_schedules.d.ts +4 -0
  186. package/dist/src/semantics/subscription_schedules.js +60 -0
  187. package/dist/src/semantics/subscriptions.d.ts +7 -11
  188. package/dist/src/semantics/subscriptions.js +44 -415
  189. package/dist/src/semantics/test_helpers.d.ts +6 -0
  190. package/dist/src/semantics/{test-clocks.js → test_helpers.js} +14 -40
  191. package/dist/src/semantics/transfers.d.ts +2 -2
  192. package/dist/src/semantics/transfers.js +6 -101
  193. package/dist/src/server.d.ts +7 -0
  194. package/dist/src/server.js +7 -0
  195. package/generated/pack-facts.json +94 -0
  196. package/package.json +10 -20
  197. package/spec/SOURCE.md +14 -0
  198. package/spec/fixtures3.json.gz +0 -0
  199. package/spec/openapi.json.gz +0 -0
  200. package/spec/patches.json +34 -0
  201. package/spec/sources.json +378 -0
  202. package/src/cli.ts +12 -26
  203. package/src/engine/after-payment.ts +31 -0
  204. package/src/engine/apps-secrets.ts +4 -0
  205. package/src/engine/balance.ts +33 -0
  206. package/src/engine/billing.ts +16 -0
  207. package/src/engine/charges.ts +19 -0
  208. package/src/engine/checkout.ts +40 -0
  209. package/src/engine/common.ts +47 -0
  210. package/src/engine/connect-settings.ts +23 -0
  211. package/src/engine/connect.ts +184 -0
  212. package/src/engine/coupons.ts +5 -0
  213. package/src/engine/credit-notes.ts +6 -0
  214. package/src/engine/customers.ts +35 -0
  215. package/src/engine/display.ts +19 -0
  216. package/src/engine/disputes.ts +9 -0
  217. package/src/engine/entitlements.ts +5 -0
  218. package/src/engine/ephemeral-keys.ts +3 -0
  219. package/src/engine/files.ts +41 -0
  220. package/src/engine/front.ts +31 -0
  221. package/src/engine/invoices.ts +71 -0
  222. package/src/engine/issuing.ts +61 -0
  223. package/src/engine/ledger.ts +50 -0
  224. package/src/engine/oauth.ts +19 -0
  225. package/src/engine/onboarding.ts +54 -0
  226. package/src/{stripe-params.ts → engine/params.ts} +8 -56
  227. package/src/engine/payment-intents.ts +33 -0
  228. package/src/engine/payment-links.ts +6 -0
  229. package/src/engine/payment-methods.ts +25 -0
  230. package/src/engine/plans.ts +42 -0
  231. package/src/engine/platform.ts +47 -0
  232. package/src/engine/products.ts +3 -0
  233. package/src/engine/radar.ts +6 -0
  234. package/src/engine/refunds.ts +29 -0
  235. package/src/engine/renewals.ts +73 -0
  236. package/src/engine/setup-intents.ts +5 -0
  237. package/src/{stripe-twin.ts → engine/stripe.ts} +28 -323
  238. package/src/engine/subscription-schedules.ts +10 -0
  239. package/src/engine/subscriptions.ts +40 -0
  240. package/src/engine/tax.ts +39 -0
  241. package/src/engine/terminal.ts +23 -0
  242. package/src/engine/test-clocks.ts +11 -0
  243. package/src/engine/tokens.ts +22 -0
  244. package/src/engine/transfers.ts +23 -0
  245. package/src/engine/treasury.ts +47 -0
  246. package/src/{stripe-version.ts → engine/version.ts} +4 -3
  247. package/src/engine/webhook-endpoints.ts +14 -0
  248. package/src/engine/webhooks.ts +72 -0
  249. package/src/fetch.ts +27 -0
  250. package/src/generated/surface.gen.json +1 -1
  251. package/src/generated/ui.gen.json +1 -1
  252. package/src/index.ts +8 -116
  253. package/src/manifest.ts +234 -786
  254. package/src/screens/{portal.tsx → billing-portal.tsx} +32 -37
  255. package/src/screens/checkout.tsx +33 -95
  256. package/src/screens/connect-oauth.tsx +64 -88
  257. package/src/screens/{onboarding.tsx → connect-onboarding.tsx} +38 -82
  258. package/src/screens/dashboard.tsx +198 -0
  259. package/src/screens/shared.tsx +84 -0
  260. package/src/screens/stripe-js.ts +170 -0
  261. package/src/semantics/account_links.ts +21 -0
  262. package/src/semantics/accounts.ts +43 -0
  263. package/src/semantics/{apps-secrets.ts → apps.ts} +17 -32
  264. package/src/semantics/around.ts +20 -0
  265. package/src/semantics/balance.ts +6 -207
  266. package/src/semantics/balance_transactions.ts +20 -0
  267. package/src/semantics/billing_portal.ts +51 -0
  268. package/src/semantics/charges.ts +12 -211
  269. package/src/semantics/checkout.ts +13 -268
  270. package/src/semantics/clock.ts +26 -0
  271. package/src/semantics/coupons.ts +5 -67
  272. package/src/semantics/customers.ts +29 -392
  273. package/src/semantics/disputes.ts +9 -59
  274. package/src/semantics/doors.ts +80 -0
  275. package/src/semantics/entitlements.ts +9 -56
  276. package/src/semantics/events.ts +44 -0
  277. package/src/semantics/index.ts +111 -0
  278. package/src/semantics/invoice_payments.ts +18 -0
  279. package/src/semantics/invoiceitems.ts +59 -0
  280. package/src/semantics/invoices.ts +109 -443
  281. package/src/semantics/payment_intents.ts +83 -0
  282. package/src/semantics/payment_methods.ts +43 -0
  283. package/src/semantics/payouts.ts +23 -0
  284. package/src/semantics/prices.ts +42 -0
  285. package/src/semantics/products.ts +18 -142
  286. package/src/semantics/promotion_codes.ts +39 -0
  287. package/src/semantics/radar.ts +8 -77
  288. package/src/semantics/refunds.ts +9 -212
  289. package/src/semantics/setup_intents.ts +45 -0
  290. package/src/semantics/shared.ts +3092 -106
  291. package/src/semantics/states.ts +883 -0
  292. package/src/semantics/subscription_items.ts +54 -0
  293. package/src/semantics/subscription_schedules.ts +66 -0
  294. package/src/semantics/subscriptions.ts +49 -432
  295. package/src/semantics/{test-clocks.ts → test_helpers.ts} +23 -47
  296. package/src/semantics/transfers.ts +11 -131
  297. package/src/server.ts +8 -0
  298. package/client/dashboard-api.ts +0 -286
  299. package/client/stripe-mirror.css +0 -277
  300. package/client/stripe-mirror.tsx +0 -1559
  301. package/dist/client/dashboard-api.d.ts +0 -107
  302. package/dist/client/dashboard-api.js +0 -238
  303. package/dist/client/dashboard-api.ts +0 -286
  304. package/dist/client/stripe-mirror.bundle.js +0 -236
  305. package/dist/client/stripe-mirror.css +0 -277
  306. package/dist/client/stripe-mirror.d.ts +0 -134
  307. package/dist/client/stripe-mirror.js +0 -859
  308. package/dist/client/stripe-mirror.tsx +0 -1559
  309. package/dist/src/screens/connect-settings.js +0 -103
  310. package/dist/src/screens/consent-skin.d.ts +0 -4
  311. package/dist/src/screens/consent-skin.js +0 -18
  312. package/dist/src/screens/financial-connections.d.ts +0 -5
  313. package/dist/src/screens/financial-connections.js +0 -90
  314. package/dist/src/screens/identity.d.ts +0 -5
  315. package/dist/src/screens/identity.js +0 -86
  316. package/dist/src/screens/onboarding.d.ts +0 -13
  317. package/dist/src/screens/portal.d.ts +0 -5
  318. package/dist/src/screens/public-details.d.ts +0 -5
  319. package/dist/src/screens/public-details.js +0 -90
  320. package/dist/src/semantics/after-payment.d.ts +0 -22
  321. package/dist/src/semantics/after-payment.js +0 -99
  322. package/dist/src/semantics/apps-secrets.d.ts +0 -2
  323. package/dist/src/semantics/billing.d.ts +0 -2
  324. package/dist/src/semantics/billing.js +0 -220
  325. package/dist/src/semantics/connect.d.ts +0 -5
  326. package/dist/src/semantics/connect.js +0 -493
  327. package/dist/src/semantics/credit-notes.d.ts +0 -2
  328. package/dist/src/semantics/credit-notes.js +0 -172
  329. package/dist/src/semantics/ephemeral-keys.d.ts +0 -2
  330. package/dist/src/semantics/ephemeral-keys.js +0 -34
  331. package/dist/src/semantics/files.d.ts +0 -2
  332. package/dist/src/semantics/files.js +0 -125
  333. package/dist/src/semantics/issuing.d.ts +0 -13
  334. package/dist/src/semantics/issuing.js +0 -575
  335. package/dist/src/semantics/ledger.d.ts +0 -59
  336. package/dist/src/semantics/ledger.js +0 -200
  337. package/dist/src/semantics/payment-intents.d.ts +0 -18
  338. package/dist/src/semantics/payment-intents.js +0 -452
  339. package/dist/src/semantics/payment-links.d.ts +0 -2
  340. package/dist/src/semantics/payment-links.js +0 -133
  341. package/dist/src/semantics/payment-methods.d.ts +0 -20
  342. package/dist/src/semantics/payment-methods.js +0 -140
  343. package/dist/src/semantics/plans.d.ts +0 -5
  344. package/dist/src/semantics/plans.js +0 -121
  345. package/dist/src/semantics/platform.d.ts +0 -9
  346. package/dist/src/semantics/platform.js +0 -206
  347. package/dist/src/semantics/renewals.d.ts +0 -47
  348. package/dist/src/semantics/renewals.js +0 -281
  349. package/dist/src/semantics/setup-intents.d.ts +0 -2
  350. package/dist/src/semantics/subscription-schedules.d.ts +0 -2
  351. package/dist/src/semantics/subscription-schedules.js +0 -119
  352. package/dist/src/semantics/tax.d.ts +0 -2
  353. package/dist/src/semantics/tax.js +0 -197
  354. package/dist/src/semantics/terminal.d.ts +0 -5
  355. package/dist/src/semantics/terminal.js +0 -182
  356. package/dist/src/semantics/test-clocks.d.ts +0 -6
  357. package/dist/src/semantics/tokens.d.ts +0 -4
  358. package/dist/src/semantics/tokens.js +0 -44
  359. package/dist/src/semantics/treasury.d.ts +0 -2
  360. package/dist/src/semantics/treasury.js +0 -377
  361. package/dist/src/semantics/webhook-endpoints.d.ts +0 -3
  362. package/dist/src/semantics/webhook-endpoints.js +0 -85
  363. package/dist/src/stripe-budget.d.ts +0 -55
  364. package/dist/src/stripe-budget.js +0 -155
  365. package/dist/src/stripe-capabilities.d.ts +0 -3
  366. package/dist/src/stripe-capabilities.js +0 -5836
  367. package/dist/src/stripe-conformance.d.ts +0 -43
  368. package/dist/src/stripe-conformance.js +0 -105
  369. package/dist/src/stripe-connector.d.ts +0 -161
  370. package/dist/src/stripe-connector.js +0 -414
  371. package/dist/src/stripe-emit.d.ts +0 -2
  372. package/dist/src/stripe-emit.js +0 -145
  373. package/dist/src/stripe-events.d.ts +0 -93
  374. package/dist/src/stripe-events.js +0 -392
  375. package/dist/src/stripe-js.d.ts +0 -4
  376. package/dist/src/stripe-js.js +0 -70
  377. package/dist/src/stripe-mirror-ui.d.ts +0 -15
  378. package/dist/src/stripe-mirror-ui.js +0 -87
  379. package/dist/src/stripe-perform-harness.d.ts +0 -9
  380. package/dist/src/stripe-perform-harness.js +0 -26
  381. package/dist/src/stripe-server.d.ts +0 -33
  382. package/dist/src/stripe-server.js +0 -429
  383. package/dist/src/stripe-shared.d.ts +0 -109
  384. package/dist/src/stripe-shared.js +0 -276
  385. package/dist/src/stripe-ui-conformance.d.ts +0 -5
  386. package/dist/src/stripe-ui-conformance.js +0 -79
  387. package/dist/src/stripe-ui-structure.d.ts +0 -3
  388. package/dist/src/stripe-ui-structure.js +0 -168
  389. package/dist/test-fixtures/stripe-known-deviations.json +0 -110
  390. package/dist/test-fixtures/stripe-openapi-operations.SOURCE.md +0 -14
  391. package/dist/test-fixtures/stripe-openapi-operations.json +0 -4717
  392. package/dist/test-fixtures/stripe-schemas.SOURCE.md +0 -35
  393. package/dist/test-fixtures/stripe-schemas.json +0 -3813
  394. package/src/screens/connect-settings.tsx +0 -121
  395. package/src/screens/consent-skin.ts +0 -20
  396. package/src/screens/financial-connections.tsx +0 -101
  397. package/src/screens/identity.tsx +0 -96
  398. package/src/screens/public-details.tsx +0 -105
  399. package/src/semantics/after-payment.ts +0 -118
  400. package/src/semantics/billing.ts +0 -216
  401. package/src/semantics/connect.ts +0 -487
  402. package/src/semantics/credit-notes.ts +0 -168
  403. package/src/semantics/ephemeral-keys.ts +0 -34
  404. package/src/semantics/files.ts +0 -143
  405. package/src/semantics/issuing.ts +0 -590
  406. package/src/semantics/ledger.ts +0 -253
  407. package/src/semantics/payment-intents.ts +0 -463
  408. package/src/semantics/payment-links.ts +0 -148
  409. package/src/semantics/payment-methods.ts +0 -145
  410. package/src/semantics/plans.ts +0 -131
  411. package/src/semantics/platform.ts +0 -220
  412. package/src/semantics/renewals.ts +0 -279
  413. package/src/semantics/setup-intents.ts +0 -87
  414. package/src/semantics/subscription-schedules.ts +0 -129
  415. package/src/semantics/tax.ts +0 -220
  416. package/src/semantics/terminal.ts +0 -195
  417. package/src/semantics/tokens.ts +0 -52
  418. package/src/semantics/treasury.ts +0 -383
  419. package/src/semantics/webhook-endpoints.ts +0 -87
  420. package/src/stripe-budget.ts +0 -181
  421. package/src/stripe-capabilities.ts +0 -5651
  422. package/src/stripe-conformance.ts +0 -124
  423. package/src/stripe-connector.ts +0 -462
  424. package/src/stripe-emit.ts +0 -157
  425. package/src/stripe-events.ts +0 -434
  426. package/src/stripe-js.ts +0 -70
  427. package/src/stripe-mirror-ui.ts +0 -90
  428. package/src/stripe-perform-harness.ts +0 -29
  429. package/src/stripe-server.ts +0 -393
  430. package/src/stripe-shared.ts +0 -297
  431. package/src/stripe-ui-conformance.ts +0 -88
  432. package/src/stripe-ui-structure.ts +0 -182
  433. package/test-fixtures/stripe-known-deviations.json +0 -110
  434. package/test-fixtures/stripe-openapi-operations.json +0 -4717
  435. package/test-fixtures/stripe-schemas.json +0 -3813
  436. /package/dist/src/{screens → engine}/industries.d.ts +0 -0
  437. /package/dist/src/{screens → engine}/industries.js +0 -0
  438. /package/dist/src/{semantics → engine}/test-cards.d.ts +0 -0
  439. /package/dist/src/{semantics → engine}/test-cards.js +0 -0
  440. /package/dist/src/{stripe-version.d.ts → engine/version.d.ts} +0 -0
  441. /package/src/{screens → engine}/industries.ts +0 -0
  442. /package/src/{semantics → engine}/test-cards.ts +0 -0
@@ -1,121 +0,0 @@
1
- // THE DASHBOARD'S CONNECT OAUTH SETTINGS — a workspace page (docs/contributing/architecture.md, "Screens") of the
2
- // Dashboard (manifest screen `dashboard`), at dashboard.stripe.com/settings/connect/onboarding-options/oauth, where a
3
- // platform starts an OAuth integration: "Enable onboarding accounts with OAuth", "Copy your client_id, a unique
4
- // identifier for your platform that's generated by Stripe", and "Set your redirect_uri ... You must specify all redirect
5
- // URLs in your platform settings. If you don't include the redirect_uri parameter in your request, Stripe defaults to
6
- // using the first address you've configured" (docs.stripe.com/connect/oauth-standard-accounts). The test client_id
7
- // "allows you to: Set your redirect_uri to a non-HTTPS URL; Set your redirect_uri to localhost"
8
- // (docs.stripe.com/connect/testing#using-oauth). Stripe's API has no call that reads or changes these settings (GET
9
- // /v1/account does not carry the client_id), so this page is the only way to them, and connect.stripe.com/oauth/authorize
10
- // (./connect-oauth.tsx) reads what it saves. Authored from plain markup under Stripe's type; nothing of Stripe's page is
11
- // copied.
12
- //
13
- // Where the documentation stops and the twin decides: the World has one platform, and its test client_id is
14
- // `ca_twin_self` (PLATFORM_CLIENT_ID; the platform account is acct_twin_self), the same in every World, shown on the
15
- // page in an element a runner reads (data-testid="connect-client-id"). OAuth starts disabled. The page is served at
16
- // the docs' address, at /test/… (the docs' test-mode link) and at /settings/connect (the address Cal.com's setup
17
- // guide gives). The redirect URIs are one form field, one per line (or comma-separated, as the reference describes
18
- // them), saved whole: each an absolute http or https URL without a fragment; http and localhost are allowed, as the
19
- // test client_id allows them. No sign-in guards the page, as none guards the Dashboard mirror. The form posts to the
20
- // page's own address and the save redirects to it.
21
- import { semanticsContext, type SemanticsContext } from '@volter/world-core';
22
- import { flowPage } from '@volter/world-ui';
23
- import surface from '../generated/surface.gen.json' with { type: 'json' };
24
- import { manifest } from '../manifest.ts';
25
- import { formOf } from './consent-skin.ts';
26
-
27
- /** The platform's test client_id: the World's one platform (acct_twin_self) is the application it names. */
28
- export const PLATFORM_CLIENT_ID = 'ca_twin_self';
29
- export const SETTINGS_URL = 'https://dashboard.stripe.com/settings/connect/onboarding-options/oauth';
30
- /** The page's addresses: the docs' own, its test-mode link, and Connect's settings root. */
31
- export const CONNECT_SETTINGS_PATH = /^\/(test\/)?settings\/connect(\/onboarding-options\/oauth)?\/?$/;
32
- const SETTINGS = '_connect_oauth_settings';
33
- const OPERATION = (surface.operations as Array<{ id: string; method: string; path: string; class: string }>).find((o) => o.id === 'PostAccountsAccount')!;
34
-
35
- export type ConnectOAuthSettings = { oauth_enabled: boolean; redirect_uris: string[] };
36
-
37
- /** What the platform saved, or the settings a new platform starts with (OAuth off, no redirect URI). */
38
- export function connectOAuthSettings(ctx: SemanticsContext): ConnectOAuthSettings {
39
- const row = ctx.rowsRaw(SETTINGS).find((r) => r.id === PLATFORM_CLIENT_ID);
40
- return { oauth_enabled: row?.oauth_enabled === true, redirect_uris: Array.isArray(row?.redirect_uris) ? (row!.redirect_uris as string[]) : [] };
41
- }
42
-
43
- /** The redirect URIs a form's field names, or the first one refused and why. */
44
- export function redirectUris(field: string): { uris: string[] } | { refused: string } {
45
- const uris = [...new Set(field.split(/[\n,]/).map((s) => s.trim()).filter(Boolean))];
46
- for (const uri of uris) {
47
- let url: URL;
48
- try { url = new URL(uri); } catch { return { refused: `${uri} is not a valid URL.` }; }
49
- if (url.protocol !== 'https:' && url.protocol !== 'http:') return { refused: `${uri} must use http or https.` };
50
- if (uri.includes('#')) return { refused: `${uri} must not contain a fragment.` };
51
- }
52
- return { uris };
53
- }
54
-
55
- const CSS = `
56
- * { box-sizing: border-box; }
57
- body { margin: 0; background: #f6f8fa; color: #1a1f36; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Ubuntu, sans-serif; font-size: 14px; }
58
- .co { max-width: 680px; margin: 48px auto; padding: 0 16px; }
59
- .co h1 { font-size: 28px; margin: 16px 0 4px; }
60
- .co-lead { color: #697386; margin: 0 0 24px; }
61
- .co-card { background: #ffffff; border: 1px solid #e3e8ee; border-radius: 8px; padding: 24px; margin-bottom: 16px; }
62
- .co-card h2 { font-size: 16px; margin: 0 0 12px; }
63
- .co-card label { display: block; font-weight: 600; margin-bottom: 6px; }
64
- .co-card small { display: block; color: #697386; margin-bottom: 8px; }
65
- .co-card textarea { width: 100%; min-height: 96px; padding: 8px 10px; border: 1px solid #c1c9d2; border-radius: 6px; font: 13px ui-monospace, Menlo, monospace; }
66
- .co-id { font: 14px ui-monospace, Menlo, monospace; background: #f6f8fa; border: 1px solid #e3e8ee; border-radius: 6px; padding: 6px 10px; display: inline-block; }
67
- .co-toggle { display: flex; gap: 8px; align-items: center; font-weight: 600; }
68
- .co-actions { display: flex; justify-content: flex-end; }
69
- .co-actions button { background: #635bff; color: #ffffff; border: 0; border-radius: 6px; padding: 8px 16px; font: inherit; font-weight: 600; cursor: pointer; }
70
- .co-notice { padding: 10px 12px; border-radius: 6px; margin-bottom: 16px; }
71
- .co-error { background: #fff0f3; color: #df1b41; }
72
- .co-saved { background: #e7f8ef; color: #0e6245; }
73
- .co-uris { margin: 0; padding-left: 18px; }
74
- `;
75
-
76
- function page(s: ConnectOAuthSettings, opts: { value?: string; enabled?: boolean; error?: string; saved?: boolean } = {}): Response {
77
- const enabled = opts.enabled ?? s.oauth_enabled;
78
- return flowPage({
79
- title: 'OAuth – Connect settings – Stripe',
80
- css: [CSS],
81
- ...(opts.error ? { status: 400 } : {}),
82
- body: (
83
- <main className="co">
84
- <h1>OAuth</h1>
85
- <p className="co-lead">Onboard Standard accounts by sending them to Stripe's OAuth flow. Test mode.</p>
86
- {opts.error ? <p className="co-notice co-error" role="alert">{opts.error}</p> : null}
87
- {opts.saved ? <p className="co-notice co-saved" role="status">Your OAuth settings were saved.</p> : null}
88
- <section className="co-card">
89
- <h2>Test mode client ID</h2>
90
- <small>The client_id your platform sends to connect.stripe.com/oauth/authorize.</small>
91
- <code className="co-id" data-testid="connect-client-id">{PLATFORM_CLIENT_ID}</code>
92
- <p data-testid="connect-oauth-status">{s.oauth_enabled ? 'OAuth is enabled.' : 'OAuth is disabled.'}</p>
93
- {s.redirect_uris.length ? <ul className="co-uris">{s.redirect_uris.map((u) => <li key={u} data-testid="connect-redirect-uri">{u}</li>)}</ul> : <p>No redirect URIs.</p>}
94
- </section>
95
- <form className="co-card" method="post">
96
- <label className="co-toggle" htmlFor="oauth_enabled"><input type="checkbox" id="oauth_enabled" name="oauth_enabled" value="on" defaultChecked={enabled} /> Enable OAuth for Standard accounts</label>
97
- <label htmlFor="redirect_uris">Redirect URIs</label>
98
- <small>One per line. The first is used when a request names none. http and localhost are allowed in test mode.</small>
99
- <textarea id="redirect_uris" name="redirect_uris" defaultValue={opts.value ?? s.redirect_uris.join('\n')} />
100
- <div className="co-actions"><button type="submit">Save</button></div>
101
- </form>
102
- </main>
103
- ),
104
- });
105
- }
106
-
107
- export function stripeConnectSettingsFlow(scope: { root?: string; clock?: () => string }): (request: Request) => Promise<Response | undefined> {
108
- return async (request) => {
109
- const url = new URL(request.url);
110
- if (!CONNECT_SETTINGS_PATH.test(url.pathname) || (request.method !== 'GET' && request.method !== 'POST')) return undefined;
111
- const form = request.method === 'POST' ? await formOf(request.clone()) : {};
112
- const ctx = await semanticsContext(manifest, request, OPERATION, scope);
113
- const held = connectOAuthSettings(ctx);
114
- if (request.method === 'GET') return page(held, { saved: url.searchParams.has('saved') });
115
- const enabled = form.oauth_enabled === 'on' || form.oauth_enabled === 'true';
116
- const parsed = redirectUris(form.redirect_uris ?? '');
117
- if ('refused' in parsed) return page(held, { value: form.redirect_uris ?? '', enabled, error: parsed.refused });
118
- await ctx.record(SETTINGS, { oauth_enabled: enabled, redirect_uris: parsed.uris }, PLATFORM_CLIENT_ID);
119
- return new Response(null, { status: 303, headers: { location: '?saved=1' } });
120
- };
121
- }
@@ -1,20 +0,0 @@
1
- // Stripe's skin over @volter/world-ui's consent piece, for the hosted flows where a person agrees to something
2
- // (connected-account onboarding, identity verification, linking a bank): Stripe's type and its purple action.
3
- export const STRIPE_CONSENT_SKIN = `
4
- body { background: #f6f9fc; color: #1a1f36; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Ubuntu, sans-serif; }
5
- .consent-badge { background: #ffffff; border: 1px solid #e3e8ee; color: #1a1f36; }
6
- .consent-vendor { background: #635bff; border-color: #635bff; }
7
- .consent-link { border-color: #c1c9d2; }
8
- .consent-box { background: #ffffff; border-color: #e3e8ee; }
9
- .consent-who small, .consent-permission summary small, .consent-note { color: #697386; }
10
- .consent-actions { border-color: #e3e8ee; }
11
- .consent-deny { background: #ffffff; border-color: #c1c9d2; color: #1a1f36; }
12
- .consent-allow { background: #635bff; border-color: #635bff; color: #ffffff; }
13
- `;
14
-
15
- /** The form fields a page's POST carries, as a browser posts them. */
16
- export async function formOf(request: Request): Promise<Record<string, string>> {
17
- return Object.fromEntries(new URLSearchParams(await request.text()));
18
- }
19
-
20
- export const seeOther = (location: string): Response => new Response(null, { status: 302, headers: { location } });
@@ -1,101 +0,0 @@
1
- // STRIPE FINANCIAL CONNECTIONS — a hosted flow (docs/contributing/architecture.md, "Screens"): an application
2
- // creates a Financial Connections Session for an account holder and the permissions it wants, and hands its
3
- // client_secret to Stripe.js, whose authentication flow lets the holder pick their bank and the accounts to share;
4
- // the linked accounts are then on the session and readable through the Accounts API, with balances and
5
- // transactions when the permissions asked for them (docs.stripe.com/financial-connections/fundamentals,
6
- // docs.stripe.com/financial-connections/other-data-powered-products). In test mode the bank is Stripe's test
7
- // institution (docs.stripe.com/financial-connections/testing). Linking is the holder's move, not an API call.
8
- // Authored from @volter/world-ui's consent piece under Stripe's skin; nothing of Stripe's page is copied.
9
- //
10
- // The flow is opened with the session's client_secret, never its id: the session's own documentation says "The
11
- // session's client_secret can be used to launch the flow using Stripe.js", and stripe.collectFinancialConnectionsAccounts
12
- // takes `clientSecret`, "The client_secret of the Financial Connections Session"
13
- // (docs.stripe.com/js/financial_connections/collect_financial_connections_accounts).
14
- // Where the documentation stops and the twin decides: the page is served at
15
- // js.stripe.com/v3/financial-connections/{client_secret}, the twin's address for the "on-page modal UI" Stripe.js
16
- // loads (the twin's stripe.js navigates there, ../stripe-js.ts); an id or an unknown secret finds no flow;
17
- // the test institution holds a checking account (•••• 6789) and a savings account (•••• 4321); a linked account's
18
- // balance and its three transactions are the twin's test data.
19
- import { semanticsContext, type SemanticsContext } from '@volter/world-core';
20
- import { Consent, CONSENT_CSS, flowPage } from '@volter/world-ui';
21
- import surface from '../generated/surface.gen.json' with { type: 'json' };
22
- import { manifest } from '../manifest.ts';
23
- import { created, type Row } from '../semantics/shared.ts';
24
- import { formOf, seeOther, STRIPE_CONSENT_SKIN } from './consent-skin.ts';
25
-
26
- const FCS = 'financial_connections.session';
27
- const FCA = 'financial_connections.account';
28
- const FCT = 'financial_connections.transaction';
29
- const OPERATION = (surface.operations as Array<{ id: string; method: string; path: string; class: string }>).find((o) => o.id === 'GetFinancialConnectionsSessionsSession')!;
30
- const css = [CONSENT_CSS, STRIPE_CONSENT_SKIN];
31
-
32
- const TEST_ACCOUNTS = [
33
- { last4: '6789', subcategory: 'checking', display_name: 'Checking', balance: 125_000 },
34
- { last4: '4321', subcategory: 'savings', display_name: 'Savings', balance: 980_000 },
35
- ];
36
-
37
- const message = (status: number, text: string): Response => flowPage({ title: 'Link your account', status, css, body: <main className="consent"><h1 className="consent-heading">{text}</h1></main> });
38
- const permissionsOf = (session: Row): string[] => (Array.isArray(session.permissions) ? session.permissions.map(String) : []);
39
-
40
- function page(secret: string, session: Row): Response {
41
- const says: Record<string, string> = { balances: 'Account balances', ownership: 'Account ownership details', payment_method: 'Account and routing numbers', transactions: 'Transactions' };
42
- return flowPage({
43
- title: 'Link your account',
44
- css,
45
- body: (
46
- <Consent
47
- heading="Link your account"
48
- app={{ name: 'Test Institution' }}
49
- request={`Test mode · ${TEST_ACCOUNTS.map((a) => `${a.display_name} •••• ${a.last4}`).join(', ')}`}
50
- permissions={permissionsOf(session).map((p) => ({ title: says[p] ?? p, detail: 'Shared with the business through Stripe' }))}
51
- action={`/v3/financial-connections/${secret}`}
52
- fields={{}}
53
- deny={{ name: 'answer', value: 'cancel', label: 'Cancel' }}
54
- allow={{ name: 'answer', value: 'link', label: 'Link accounts' }}
55
- note="Stripe will share the data above with the business."
56
- />
57
- ),
58
- });
59
- }
60
-
61
- /** The holder links the test institution's accounts to the session. */
62
- async function link(ctx: SemanticsContext, id: string, session: Row): Promise<void> {
63
- const permissions = permissionsOf(session);
64
- const now = Number(ctx.now());
65
- for (const a of TEST_ACCOUNTS) {
66
- const account = await created(ctx, FCA, { session: id }, {
67
- livemode: false, status: 'active', account_holder: session.account_holder ?? null, institution_name: 'StripeBank', display_name: a.display_name,
68
- last4: a.last4, category: 'cash', subcategory: a.subcategory, supported_payment_method_types: ['us_bank_account', 'link'], permissions,
69
- balance: permissions.includes('balances') ? { as_of: now, type: 'cash', cash: { available: { usd: a.balance } }, current: { usd: a.balance } } : null,
70
- balance_refresh: permissions.includes('balances') ? { status: 'succeeded', last_attempted_at: now, next_refresh_available_at: null } : null,
71
- transaction_refresh: permissions.includes('transactions') ? { id: `fctxnref_${a.last4}`, status: 'succeeded', last_attempted_at: now, next_refresh_available_at: null } : null,
72
- ownership: null, ownership_refresh: null, subscriptions: [],
73
- });
74
- if (!permissions.includes('transactions')) continue;
75
- for (const [i, t] of [{ amount: -4_250, description: 'COFFEE ROASTERS' }, { amount: -12_000, description: 'CITY UTILITIES' }, { amount: 250_000, description: 'PAYROLL DEPOSIT' }].entries()) {
76
- await created(ctx, FCT, { account: account.id }, {
77
- livemode: false, amount: t.amount, currency: 'usd', description: t.description, status: 'posted',
78
- status_transitions: { posted_at: now - (3 - i) * 86_400, void_at: null }, transacted_at: now - (3 - i) * 86_400, transaction_refresh: `fctxnref_${a.last4}`, updated: now,
79
- });
80
- }
81
- }
82
- }
83
-
84
- /** The authentication flow Stripe.js opens, or undefined for any other request. */
85
- export function stripeFinancialConnectionsFlow(scope: { root?: string; clock?: () => string }): (request: Request) => Promise<Response | undefined> {
86
- return async (request) => {
87
- const m = /^\/v3\/financial-connections\/([A-Za-z0-9_]+)\/?$/.exec(new URL(request.url).pathname);
88
- if (!m || (request.method !== 'GET' && request.method !== 'POST')) return undefined;
89
- const secret = m[1]!;
90
- const form = request.method === 'POST' ? await formOf(request.clone()) : {};
91
- const ctx = await semanticsContext(manifest, request, OPERATION, scope);
92
- const session = ctx.rows(FCS).find((s) => s.client_secret === secret);
93
- if (!session) return message(404, 'This link has expired.');
94
- const id = String(session.id);
95
- if (ctx.rows(FCA).some((a) => a.session === id)) return message(200, 'Your accounts are linked.');
96
- if (request.method === 'GET') return page(secret, session);
97
- if (form.answer === 'link') await link(ctx, id, session);
98
- const back = typeof session.return_url === 'string' && session.return_url ? session.return_url : undefined;
99
- return back ? seeOther(back) : message(200, form.answer === 'link' ? 'Your accounts are linked.' : 'No accounts were linked.');
100
- };
101
- }
@@ -1,96 +0,0 @@
1
- // STRIPE IDENTITY — a hosted flow (docs/contributing/architecture.md, "Screens"): an application creates a
2
- // VerificationSession and sends the person to its `url` at verify.stripe.com/start/{session}; they submit their
3
- // ID there, the session is processing and then verified, with a VerificationReport of what was checked, or it
4
- // asks for input again with the reason in last_error; the person returns to return_url
5
- // (docs.stripe.com/identity/how-sessions-work, docs.stripe.com/identity/verification-sessions). In test mode the
6
- // page offers the outcome instead of a camera (the twin's decision: docs.stripe.com/identity/testing, once cited
7
- // for it, no longer answers). Submitting is the person's move
8
- // (the session machine's external actor) and the check Stripe's (its vendor moves). Authored from
9
- // @volter/world-ui's consent piece under Stripe's skin; nothing of Stripe's page is copied.
10
- //
11
- // Where the documentation stops and the twin decides: test mode's person is Jenny Rosen with a driving licence,
12
- // the name Stripe's test reports carry; a failed check is document_unverified_other.
13
- import { semanticsContext, type SemanticsContext } from '@volter/world-core';
14
- import { Consent, CONSENT_CSS, flowPage } from '@volter/world-ui';
15
- import surface from '../generated/surface.gen.json' with { type: 'json' };
16
- import { manifest } from '../manifest.ts';
17
- import { created, type Row } from '../semantics/shared.ts';
18
- import { formOf, seeOther, STRIPE_CONSENT_SKIN } from './consent-skin.ts';
19
-
20
- const VS = 'identity.verification_session';
21
- const OPERATION = (surface.operations as Array<{ id: string; method: string; path: string; class: string }>).find((o) => o.id === 'GetIdentityVerificationSessionsSession')!;
22
- const css = [CONSENT_CSS, STRIPE_CONSENT_SKIN];
23
-
24
- const message = (status: number, text: string): Response => flowPage({ title: 'Stripe Identity', status, css, body: <main className="consent"><h1 className="consent-heading">{text}</h1></main> });
25
-
26
- function page(id: string, session: Row): Response {
27
- const kind = session.type === 'id_number' ? 'ID number' : 'Government-issued photo ID';
28
- return flowPage({
29
- title: 'Verify your identity',
30
- css,
31
- body: (
32
- <Consent
33
- heading="Verify your identity"
34
- app={{ name: 'Stripe Identity' }}
35
- request="Test mode: choose how the verification ends"
36
- permissions={[
37
- { title: kind, detail: 'Test data: Jenny Rosen, driving licence' },
38
- ...(((session.options as Row | undefined)?.document as Row | undefined)?.require_matching_selfie === true ? [{ title: 'Selfie', detail: 'Matched to the ID photo' }] : []),
39
- ]}
40
- action={`/start/${id}`}
41
- fields={{}}
42
- deny={{ name: 'outcome', value: 'unverified', label: 'Fail verification' }}
43
- allow={{ name: 'outcome', value: 'verified', label: 'Verify' }}
44
- note="Stripe uses this data only to verify your identity."
45
- />
46
- ),
47
- });
48
- }
49
-
50
- /** The person submits; Stripe checks and writes the report, and the session is verified or asks again. */
51
- async function submit(ctx: SemanticsContext, id: string, session: Row, verified: boolean): Promise<void> {
52
- if (ctx.legal(VS, 'status', OPERATION.id, String(session.status), 'processing', id, 'external')) return;
53
- // Stripe's check decides the processing session at once: the second move of the one write below
54
- ctx.legal(VS, 'status', OPERATION.id, 'processing', verified ? 'verified' : 'requires_input', id, 'vendor');
55
- const type = session.type === 'id_number' ? 'id_number' : 'document';
56
- const error = verified ? null : { code: 'document_unverified_other', reason: 'The document could not be verified.' };
57
- // a document check holds its images: files "Array of File ids containing images for this document" (the served
58
- // spec's document report). Where the documentation stops and the twin decides: the licence's front and back, two
59
- // identity_document files, as the published report's two
60
- const images: string[] = [];
61
- if (type === 'document') for (const side of ['front', 'back']) {
62
- const f = await created(ctx, 'file', { purpose: 'identity_document' }, { filename: `driving_license_${side}.jpg`, size: 0, type: 'jpg', title: null, expires_at: null, url: null, links: { object: 'list', data: [], has_more: false, url: '' } });
63
- images.push(String(f.id));
64
- }
65
- // the report records the options the session was checked with (the session's own, as its object answers them)
66
- const sessionOptions = (session.options as Row | undefined) ?? {};
67
- const report = await created(ctx, 'identity.verification_report', { verification_session: id, type }, {
68
- livemode: false, client_reference_id: session.client_reference_id ?? null,
69
- document: type === 'document' ? { status: verified ? 'verified' : 'unverified', type: 'driving_license', first_name: 'Jenny', last_name: 'Rosen', address: null, dob: null, error, files: images } : null,
70
- id_number: type === 'id_number' ? { status: verified ? 'verified' : 'unverified', id_number_type: 'us_ssn', first_name: 'Jenny', last_name: 'Rosen', dob: null, error } : null,
71
- selfie: null, email: null, phone: null,
72
- options: type === 'document' ? { document: (sessionOptions.document as Row | undefined) ?? {} } : { id_number: (sessionOptions.id_number as Row | undefined) ?? {} },
73
- });
74
- // the url "can only be used once" (the served spec): spent by the submission, as the verification sessions page's
75
- // examples answer a verified and a requires_input session with url null
76
- await ctx.write(VS, id, verified
77
- ? { status: 'verified', last_verification_report: report.id, last_error: null, url: null, client_secret: null, verified_outputs: { first_name: 'Jenny', last_name: 'Rosen' } }
78
- : { status: 'requires_input', last_verification_report: report.id, last_error: error, url: null }, verified ? 'verification_session.verified' : 'verification_session.requires_input');
79
- }
80
-
81
- /** verify.stripe.com's pages, or undefined for any other request. */
82
- export function stripeIdentityFlow(scope: { root?: string; clock?: () => string }): (request: Request) => Promise<Response | undefined> {
83
- return async (request) => {
84
- const m = /^\/start\/(vs_[A-Za-z0-9_]+)\/?$/.exec(new URL(request.url).pathname);
85
- if (!m || (request.method !== 'GET' && request.method !== 'POST')) return undefined;
86
- const id = m[1]!;
87
- const form = request.method === 'POST' ? await formOf(request.clone()) : {};
88
- const ctx = await semanticsContext(manifest, request, OPERATION, scope);
89
- const session = ctx.get(VS, id);
90
- if (!session) return message(404, 'This verification link is invalid.');
91
- if (session.status !== 'requires_input') return message(200, session.status === 'verified' ? 'You are verified.' : 'This verification has ended.');
92
- if (request.method === 'GET') return page(id, session);
93
- await submit(ctx, id, session, form.outcome === 'verified');
94
- return typeof session.return_url === 'string' && session.return_url ? seeOther(session.return_url) : message(200, form.outcome === 'verified' ? 'You are verified.' : 'We could not verify your identity.');
95
- };
96
- }
@@ -1,105 +0,0 @@
1
- // THE DASHBOARD'S PUBLIC DETAILS — a workspace page (docs/contributing/architecture.md, "Screens") of the Dashboard
2
- // (manifest screen `dashboard`), at dashboard.stripe.com/settings/public: Settings → Business → Public details, where
3
- // the operator sets what their customers see ("Public Details → Business Settings",
4
- // support.stripe.com/questions/update-account-name-shown-in-the-dashboard). Its business name is the account's
5
- // `business_profile.name`, "The customer-facing business name" (docs.stripe.com/api/accounts/object), and it is the
6
- // name Checkout shows: "You can change a Checkout page's name by modifying the Business name field"
7
- // (docs.stripe.com/payments/checkout/customization/appearance). Stripe's API has no call that changes the platform's
8
- // own account (POST /v1/accounts/{account} updates a connected one), so this page is the only way to the act, and
9
- // saving it writes the platform account's stored record (semantics/connect.ts `platform`), which GET /v1/account,
10
- // Checkout and the customer portal then read. The Dashboard's account name (`settings.dashboard.display_name`,
11
- // Settings → Account) is a separate, internal setting, "for internal use only" (the same support article), and this
12
- // page does not touch it. Authored from plain markup under Stripe's type; nothing of Stripe's page is copied.
13
- //
14
- // Where the documentation stops and the twin decides: the page holds the business name only (the real page's
15
- // support details, website and statement descriptor are not modelled here); the name is required and at most 5000
16
- // characters (the spec's bound on business_profile.name), which the browser holds the field to and the page checks
17
- // again for a client that is not a browser; no sign-in guards the page, as none guards the Dashboard mirror. The page
18
- // is matched by its path on whatever host reaches the twin (the World routes only dashboard.stripe.com's
19
- // /settings/public here; the local mirror serves it on its own origin), and the form posts to the page's own address
20
- // and the save redirects to its own path, so it also works under the hosted mirror's path prefix. Saving is an update of an account that exists (the first save included, though
21
- // the twin stores the platform's record only then), so every save is sent as account.updated.
22
- import { semanticsContext, type SemanticsContext } from '@volter/world-core';
23
- import { flowPage } from '@volter/world-ui';
24
- import surface from '../generated/surface.gen.json' with { type: 'json' };
25
- import { manifest } from '../manifest.ts';
26
- import { platformAccountDefault } from '../semantics/connect.ts';
27
- import { created, type Row } from '../semantics/shared.ts';
28
- import { publicBusinessName } from '../stripe-shared.ts';
29
- import { PLATFORM_ACCOUNT_ID } from '../stripe-twin.ts';
30
- import { formOf } from './consent-skin.ts';
31
-
32
- export const PUBLIC_DETAILS_PATH = '/settings/public';
33
- const MAX_NAME = 5000;
34
- const OPERATION = (surface.operations as Array<{ id: string; method: string; path: string; class: string }>).find((o) => o.id === 'PostAccountsAccount')!;
35
-
36
- const CSS = `
37
- * { box-sizing: border-box; }
38
- body { margin: 0; background: #f6f8fa; color: #1a1f36; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Ubuntu, sans-serif; font-size: 14px; }
39
- .pd { max-width: 640px; margin: 48px auto; padding: 0 16px; }
40
- .pd h1 { font-size: 28px; margin: 16px 0 4px; }
41
- .pd-lead { color: #697386; margin: 0 0 24px; }
42
- .pd-card { background: #ffffff; border: 1px solid #e3e8ee; border-radius: 8px; padding: 24px; }
43
- .pd-card label { display: block; font-weight: 600; margin-bottom: 6px; }
44
- .pd-card small { display: block; color: #697386; margin-bottom: 8px; }
45
- .pd-card input { width: 100%; padding: 8px 10px; border: 1px solid #c1c9d2; border-radius: 6px; font: inherit; }
46
- .pd-actions { margin-top: 20px; display: flex; justify-content: flex-end; }
47
- .pd-actions button { background: #635bff; color: #ffffff; border: 0; border-radius: 6px; padding: 8px 16px; font: inherit; font-weight: 600; cursor: pointer; }
48
- .pd-notice { padding: 10px 12px; border-radius: 6px; margin-bottom: 16px; }
49
- .pd-error { background: #fff0f3; color: #df1b41; }
50
- .pd-saved { background: #e7f8ef; color: #0e6245; }
51
- `;
52
-
53
- function page(account: Row | undefined, opts: { value?: string; error?: string; saved?: boolean } = {}): Response {
54
- const named = (account?.business_profile as Row | undefined)?.name;
55
- const value = opts.value ?? (typeof named === 'string' ? named : '');
56
- return flowPage({
57
- title: 'Public details – Stripe',
58
- css: [CSS],
59
- ...(opts.error ? { status: 400 } : {}),
60
- body: (
61
- <main className="pd">
62
- <h1>Public details</h1>
63
- <p className="pd-lead">What your customers see on Checkout, the customer portal, receipts and invoices. Currently shown: <strong data-testid="public-business-name">{publicBusinessName(account)}</strong></p>
64
- {opts.error ? <p className="pd-notice pd-error" role="alert">{opts.error}</p> : null}
65
- {opts.saved ? <p className="pd-notice pd-saved" role="status">Your public details were saved.</p> : null}
66
- <form className="pd-card" method="post">
67
- <label htmlFor="business_name">Business name</label>
68
- <small>The name customers see when they pay you.</small>
69
- <input id="business_name" name="business_name" autoComplete="organization" defaultValue={value} required maxLength={MAX_NAME} />
70
- <div className="pd-actions"><button type="submit">Save</button></div>
71
- </form>
72
- </main>
73
- ),
74
- });
75
- }
76
-
77
- /** Save the business name on the platform's own account: the stored record, made from Stripe's default the first
78
- * time anything is saved, and otherwise changed in place (its other public details kept). */
79
- async function save(ctx: SemanticsContext, name: string): Promise<void> {
80
- const held = ctx.get('account', PLATFORM_ACCOUNT_ID);
81
- const profile = { business_profile: { ...(((held ?? platformAccountDefault()).business_profile as Row | undefined) ?? {}), name } };
82
- await (held ? ctx.write('account', PLATFORM_ACCOUNT_ID, profile, 'account.update') : created(ctx, 'account', { ...platformAccountDefault(), ...profile }, {}, { operation: 'account.update' }));
83
- }
84
-
85
- /** What the page says of a name no browser sends (the field is required and bounded), for a client that sends it. */
86
- function nameRefused(name: string): string | undefined {
87
- return !name ? 'Enter your business name.' : name.length > MAX_NAME ? `Your business name must be at most ${MAX_NAME} characters.` : undefined;
88
- }
89
-
90
- export function stripePublicDetailsFlow(scope: { root?: string; clock?: () => string }): (request: Request) => Promise<Response | undefined> {
91
- return async (request) => {
92
- const url = new URL(request.url);
93
- if (url.pathname.replace(/\/+$/, '') !== PUBLIC_DETAILS_PATH || (request.method !== 'GET' && request.method !== 'POST')) return undefined;
94
- // the form is read before the context, which reads the request's body itself
95
- const form = request.method === 'POST' ? await formOf(request.clone()) : {};
96
- const ctx = await semanticsContext(manifest, request, OPERATION, scope);
97
- if (request.method === 'GET') return page(ctx.get('account', PLATFORM_ACCOUNT_ID), { saved: url.searchParams.has('saved') });
98
- const name = (form.business_name ?? '').trim();
99
- const refused = nameRefused(name);
100
- if (refused) return page(ctx.get('account', PLATFORM_ACCOUNT_ID), { value: form.business_name ?? '', error: refused });
101
- await save(ctx, name);
102
- // a query-only reference: the page's own path, wherever it is mounted and with or without its trailing slash
103
- return new Response(null, { status: 303, headers: { location: '?saved=1' } });
104
- };
105
- }
@@ -1,118 +0,0 @@
1
- // What Stripe does itself once a payment succeeds, which no API call asks for:
2
- // - a test card that is disputed opens a dispute on its charge (docs.stripe.com/testing#disputes: 4000000000000259
3
- // "charge succeeds, then disputed as fraudulent", 4000000000002685 disputed as product not received,
4
- // 4000000000001976 an inquiry), and Stripe debits the disputed
5
- // amount and its dispute fee from the balance (docs.stripe.com/disputes/how-disputes-work);
6
- // - a test card Radar scores as elevated risk opens a review of its charge (docs.stripe.com/testing#fraud-prevention:
7
- // 4000000000009235, "elevated risk", which Radar places in review; docs.stripe.com/radar/reviews);
8
- // - a charge a platform makes with `application_fee_amount` earns the platform an application fee, from the connected
9
- // account it pays (a destination charge's `transfer_data.destination`, or the account a direct charge is made on;
10
- // docs.stripe.com/connect/destination-charges, docs.stripe.com/connect/direct-charges);
11
- // - a bank account verified by micro-deposits for a payment or a setup carries a mandate, the customer's acceptance
12
- // of debits (docs.stripe.com/payments/ach-direct-debit/accept-a-payment, docs.stripe.com/api/mandates).
13
- //
14
- // Where the documentation stops and the twin decides: evidence is due seven days after a dispute opens (Stripe's
15
- // deadline depends on the card network); the dispute fee is 1500 cents in any currency (Stripe's US fee is $15); an
16
- // elevated-risk review's risk score is 67 (Radar's elevated band); the application is `ca_twin`.
17
- import type { SemanticsContext } from '@volter/world-core';
18
- import { disputeEvidence } from '../stripe-twin.ts';
19
- import { actingAccount, settleApplicationFee, settleDispute, settleTransfer } from './ledger.ts';
20
- import { BYPASS_PENDING_CARDS } from './test-cards.ts';
21
- import { created, type Row } from './shared.ts';
22
-
23
- type Outcome = 'dispute' | 'dispute_not_received' | 'inquiry' | 'review' | 'available';
24
- const DAY = 86_400;
25
-
26
- /** The test cards whose success Stripe follows with its own act, by number and by their documented test names. */
27
- export const AFTER_SUCCESS_CARDS: Record<string, { brand: string; number: string; outcome: Outcome }> = {
28
- pm_card_createDispute: { brand: 'visa', number: '4000000000000259', outcome: 'dispute' },
29
- pm_card_createDisputeProductNotReceived: { brand: 'visa', number: '4000000000002685', outcome: 'dispute_not_received' },
30
- pm_card_createDisputeInquiry: { brand: 'visa', number: '4000000000001976', outcome: 'inquiry' },
31
- pm_card_riskLevelElevated: { brand: 'visa', number: '4000000000009235', outcome: 'review' },
32
- // its funds go straight to the available balance (ledger.ts reads it; no act follows here)
33
- ...Object.fromEntries(Object.entries(BYPASS_PENDING_CARDS).map(([name, c]) => [name, { ...c, outcome: 'available' as const }])),
34
- };
35
- const BY_NUMBER: Record<string, Outcome> = Object.fromEntries(Object.values(AFTER_SUCCESS_CARDS).map((c) => [c.number, c.outcome]));
36
-
37
- /** What Stripe does after a card succeeds: from a raw number, a test name (pm_card_* or tok_*), or a stored
38
- * PaymentMethod that recorded it when it was made. */
39
- export function afterSuccessOf(ctx: SemanticsContext, ref: unknown): Outcome | undefined {
40
- // a card given as a token (card[token], payment_method_data[card][token]) is the card the token names
41
- if (ref && typeof ref === 'object' && typeof (ref as Row).token === 'string') return afterSuccessOf(ctx, (ref as Row).token);
42
- if (ref && typeof ref === 'object') return BY_NUMBER[String((ref as Row).number ?? '').replace(/\D/g, '')];
43
- if (typeof ref !== 'string' || !ref) return undefined;
44
- const stored = ctx.row('payment_method', ref);
45
- if (stored) return (stored._afterSuccess as Outcome | undefined) ?? undefined;
46
- return AFTER_SUCCESS_CARDS[ref.replace(/^tok_/, 'pm_card_')]?.outcome ?? BY_NUMBER[ref.replace(/\D/g, '')];
47
- }
48
-
49
- /** Stripe's acts on a charge that just succeeded: a dispute or a review its card brings, and the platform's fee. */
50
- export async function afterCharge(ctx: SemanticsContext, chargeId: string, charge: { amount: number; currency: string; payment_intent?: string | undefined; application_fee_amount?: unknown; destination?: unknown }, ref: unknown): Promise<void> {
51
- const outcome = afterSuccessOf(ctx, ref);
52
- const pi = charge.payment_intent ? { payment_intent: charge.payment_intent } : { payment_intent: null };
53
- const now = Number(ctx.now());
54
- if (outcome === 'dispute' || outcome === 'dispute_not_received' || outcome === 'inquiry') {
55
- const dispute = await created(ctx, 'dispute', { charge: chargeId, ...pi, amount: charge.amount, currency: charge.currency }, {
56
- reason: outcome === 'dispute_not_received' ? 'product_not_received' : 'fraudulent', status: outcome === 'inquiry' ? 'warning_needs_response' : 'needs_response', is_charge_refundable: false,
57
- evidence: disputeEvidence(), evidence_details: { due_by: now + 7 * DAY, has_evidence: false, past_due: false, submission_count: 0, enhanced_eligibility: {} },
58
- balance_transactions: [], livemode: false, metadata: {}, enhanced_eligibility_types: [],
59
- });
60
- // an inquiry moves no money; a dispute takes the amount and its fee until it is decided
61
- if (outcome !== 'inquiry') {
62
- const bt = await settleDispute(ctx, String(dispute.id), charge.amount, charge.currency);
63
- await ctx.write('dispute', String(dispute.id), { balance_transactions: [ctx.get('balance_transaction', bt) ?? bt] }, 'dispute.funds_withdrawn');
64
- }
65
- await ctx.write('charge', chargeId, { disputed: true }, 'charge.dispute.created');
66
- }
67
- if (outcome === 'review') await openReview(ctx, chargeId, pi);
68
- const feeAmount = Math.trunc(Number(charge.application_fee_amount) || 0);
69
- const destination = typeof charge.destination === 'string' && charge.destination ? charge.destination : undefined;
70
- const direct = actingAccount(ctx);
71
- const account = destination ?? direct;
72
- // a destination charge transfers what it collected, less the platform's fee, available when the charge's funds are
73
- if (destination) {
74
- const amount = charge.amount - feeAmount;
75
- const chargeBt = ctx.get('charge', chargeId)?.balance_transaction;
76
- const availableOn = Number(ctx.get('balance_transaction', String(chargeBt))?.available_on ?? ctx.now());
77
- const tr = await created(ctx, 'transfer', { amount, currency: charge.currency, destination }, {
78
- amount_reversed: 0, balance_transaction: null, livemode: false, metadata: {}, reversed: false, source_type: 'card', source_transaction: chargeId,
79
- reversals: { object: 'list', data: [], has_more: false, total_count: 0, url: '' },
80
- });
81
- const bt = await settleTransfer(ctx, String(tr.id), amount, charge.currency, destination, availableOn);
82
- await ctx.write('transfer', String(tr.id), { balance_transaction: bt, destination_payment: `py_${String(tr.id).replace(/^tr_/, '')}`, reversals: { object: 'list', data: [], has_more: false, total_count: 0, url: `/v1/transfers/${String(tr.id)}/reversals` } }, 'transfer.created');
83
- await ctx.write('charge', chargeId, { transfer: tr.id }, 'charge.updated');
84
- }
85
- if (feeAmount > 0 && account) {
86
- const fee = await created(ctx, 'application_fee', { account, amount: feeAmount, charge: chargeId, currency: charge.currency }, {
87
- amount_refunded: 0, application: 'ca_twin', balance_transaction: null, originating_transaction: null, refunded: false, livemode: false,
88
- });
89
- // a direct charge's fee moves from the connected account to the platform (a destination charge kept it back)
90
- const bt = !destination && direct ? await settleApplicationFee(ctx, String(fee.id), feeAmount, charge.currency, direct) : null;
91
- await ctx.write('application_fee', String(fee.id), { balance_transaction: bt, refunds: { object: 'list', data: [], has_more: false, total_count: 0, url: `/v1/application_fees/${String(fee.id)}/refunds` } }, 'application_fee.created');
92
- await ctx.write('charge', chargeId, { application_fee: fee.id, application_fee_amount: feeAmount }, 'charge.updated');
93
- }
94
- }
95
-
96
- /** Radar places an elevated-risk card's charge in review (docs.stripe.com/radar/reviews). */
97
- async function openReview(ctx: SemanticsContext, chargeId: string, pi: { payment_intent: string | null }): Promise<void> {
98
- const review = await created(ctx, 'review', { charge: chargeId, ...pi }, {
99
- open: true, opened_reason: 'rule', reason: 'rule', closed_reason: null, billing_zip: null, ip_address: null, ip_address_location: null, session: null, livemode: false,
100
- });
101
- const existing = (ctx.get('charge', chargeId)?.outcome as Row | undefined) ?? {};
102
- await ctx.write('charge', chargeId, {
103
- review: review.id,
104
- outcome: { ...existing, type: 'manual_review', risk_level: 'elevated', risk_score: 67, seller_message: 'Stripe evaluated this payment as having elevated risk, and placed it in review.' },
105
- }, 'review.opened');
106
- }
107
-
108
- /** The mandate a verified bank account carries for a payment (single use) or a setup (multi use). */
109
- export async function mintMandate(ctx: SemanticsContext, paymentMethod: unknown, use: 'single_use' | 'multi_use', amount?: number, currency?: string): Promise<string> {
110
- const now = Number(ctx.now());
111
- const mandate = await created(ctx, 'mandate', { payment_method: typeof paymentMethod === 'string' ? paymentMethod : null }, {
112
- status: 'active', type: use, livemode: false,
113
- customer_acceptance: { type: 'online', accepted_at: now, online: { ip_address: '127.0.0.1', user_agent: 'twin' } },
114
- payment_method_details: { type: 'us_bank_account', us_bank_account: { collection_method: 'paper' } },
115
- ...(use === 'single_use' ? { single_use: { amount: amount ?? 0, currency: currency ?? 'usd' } } : { multi_use: {} }),
116
- }, { timeField: '_created' });
117
- return String(mandate.id);
118
- }