@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,392 +0,0 @@
1
- import { nodeBuiltin, worldNow, deliveryTraceHeaders } from '@volter/world-core';
2
- import { appDestination, appFetch } from '@volter/world-core/app-route';
3
- import { worldEgressRefusal } from '@volter/world-core/network-policy';
4
- import vendorEvents from './generated/events.gen.json' with { type: 'json' };
5
- import { render } from "./stripe-version.js";
6
- function nodeCrypto() {
7
- // eslint-disable-next-line @typescript-eslint/no-require-imports
8
- return nodeBuiltin('node:crypto');
9
- }
10
- /** HMAC-SHA256(secret, `${timestamp}.${payload}`) as lowercase hex — Stripe's v1 signature. */
11
- export function computeStripeSignature(payload, secret, timestamp) {
12
- return nodeCrypto().createHmac('sha256', secret).update(`${timestamp}.${payload}`, 'utf8').digest('hex');
13
- }
14
- /** Build a `Stripe-Signature` header value for `payload` (mirrors generateTestHeaderString). */
15
- export function generateTestHeaderString(opts) {
16
- // signed at the World's time, as its application reads the time (a moved World clock; the app keeps it too)
17
- const timestamp = opts.timestamp ?? Math.floor(Date.parse(worldNow()) / 1000);
18
- const scheme = opts.scheme ?? 'v1';
19
- const signature = computeStripeSignature(opts.payload, opts.secret, timestamp);
20
- return `t=${timestamp},${scheme}=${signature}`;
21
- }
22
- /** Parse a `Stripe-Signature` header into its timestamp + the list of v1 signatures. */
23
- function parseSignatureHeader(header) {
24
- let timestamp = -1;
25
- const signatures = [];
26
- for (const part of header.split(',')) {
27
- const eq = part.indexOf('=');
28
- if (eq === -1)
29
- continue;
30
- const key = part.slice(0, eq).trim();
31
- const value = part.slice(eq + 1).trim();
32
- if (key === 't')
33
- timestamp = Number(value);
34
- else if (key === 'v1')
35
- signatures.push(value);
36
- }
37
- return { timestamp, signatures };
38
- }
39
- export class StripeSignatureVerificationError extends Error {
40
- constructor(message) {
41
- super(message);
42
- this.name = 'StripeSignatureVerificationError';
43
- }
44
- }
45
- /**
46
- * Verify a webhook payload + signature header against the signing secret and return the
47
- * parsed event (mirrors `stripe.webhooks.constructEvent`). Throws a
48
- * StripeSignatureVerificationError on a malformed/missing header, a signature that does
49
- * not match, or (when `tolerance` is given) a timestamp outside the allowed window.
50
- */
51
- export function constructEvent(payload, header, secret, opts = {}) {
52
- if (!header)
53
- throw new StripeSignatureVerificationError('No signatures found matching the expected signature for payload.');
54
- const { timestamp, signatures } = parseSignatureHeader(header);
55
- if (timestamp < 0 || signatures.length === 0) {
56
- throw new StripeSignatureVerificationError('Unable to extract timestamp and signatures from header');
57
- }
58
- const expected = computeStripeSignature(payload, secret, timestamp);
59
- const expectedBuf = Buffer.from(expected, 'utf8');
60
- const matched = signatures.some((s) => {
61
- const sBuf = Buffer.from(s, 'utf8');
62
- return sBuf.length === expectedBuf.length && nodeCrypto().timingSafeEqual(sBuf, expectedBuf);
63
- });
64
- if (!matched) {
65
- throw new StripeSignatureVerificationError('No signatures found matching the expected signature for payload.');
66
- }
67
- if (opts.tolerance !== undefined) {
68
- const now = opts.now ?? Math.floor(Date.parse(worldNow()) / 1000);
69
- if (now - timestamp > opts.tolerance) {
70
- throw new StripeSignatureVerificationError('Timestamp outside the tolerance zone');
71
- }
72
- }
73
- return JSON.parse(payload);
74
- }
75
- const registry = [];
76
- // URLs a HOST registered directly (registerStripeWebhook), with the secret to sign with and the
77
- // enabled_events to filter on. A World's own endpoints are not here: POST /v1/webhook_endpoints
78
- // writes the WebhookEndpoint to the tree, and every emit reads the tree (the caller passes them as
79
- // `endpoints`), so delivery survives a restart and belongs to one World. A URL registered here
80
- // without a secret is signed with the fallback below, so the header is still a real, verifiable
81
- // signature; one registered without a list receives every event, equivalent to ['*'].
82
- const secrets = new Map();
83
- const subscriptions = new Map();
84
- export const STRIPE_WEBHOOK_FALLBACK_SECRET = 'whsec_twin_default';
85
- export function registerStripeWebhook(url, secret, enabledEvents) {
86
- if (!registry.includes(url))
87
- registry.push(url);
88
- if (secret)
89
- secrets.set(url, secret);
90
- if (enabledEvents)
91
- subscriptions.set(url, enabledEvents.map(String));
92
- }
93
- export function unregisterStripeWebhook(url) {
94
- const i = registry.indexOf(url);
95
- if (i !== -1)
96
- registry.splice(i, 1);
97
- secrets.delete(url);
98
- subscriptions.delete(url);
99
- }
100
- export function clearStripeWebhooks() {
101
- registry.length = 0;
102
- secrets.clear();
103
- subscriptions.clear();
104
- }
105
- // Does an enabled_events list subscribe an endpoint to `type`? Stripe semantics: '*'
106
- // matches everything, 'issuing_authorization.*' matches the family, else exact. Shared by
107
- // the organic fan-out below and the synchronous issuing leg's enrollment check.
108
- export function stripeEventMatches(enabledEvents, type) {
109
- if (!Array.isArray(enabledEvents))
110
- return false;
111
- return enabledEvents.some((p) => {
112
- const s = String(p);
113
- return s === '*' || (s.endsWith('.*') && type.startsWith(s.slice(0, -1))) || s === type;
114
- });
115
- }
116
- export function listStripeWebhooks() {
117
- return [...registry];
118
- }
119
- // twin write operation → Stripe event type (the ones an app's webhooks care about).
120
- // Returns null when an operation has no event (e.g. a plain create/retrieve we
121
- // don't model an event for).
122
- const VENDOR_EVENT_TYPES = new Set(vendorEvents.types);
123
- export function eventTypeFor(operation) {
124
- // Several twin write operations ARE already the Stripe event type (we record the
125
- // op as `<resource>.<event>` so it maps 1:1): payment_intent.amount_capturable_updated,
126
- // payment_intent.canceled, payment_intent.succeeded. Those pass through directly.
127
- const PASSTHROUGH = new Set([
128
- 'payment_intent.amount_capturable_updated', 'payment_intent.canceled', 'payment_intent.succeeded',
129
- 'payment_intent.payment_failed', 'payment_intent.created', 'payment_intent.processing',
130
- 'payment_intent.requires_action',
131
- 'charge.succeeded', 'charge.captured', 'charge.refunded', 'charge.dispute.created',
132
- // A refund fires TWO real Stripe events: `refund.created` carrying the Refund, and
133
- // `charge.refunded` carrying the CHARGE with its new totals. The twin records the charge's
134
- // own write as `charge.refunded`, so the event a consumer receives is the charge — which is
135
- // the whole point of that event and the reason a reconciler subscribes to it.
136
- 'refund.created', 'refund.updated',
137
- 'customer.updated', 'customer.deleted', 'invoice.created', 'invoice.finalized',
138
- 'invoice.paid', 'invoice.payment_failed', 'invoice.voided', 'invoice.marked_uncollectible', 'invoice.sent',
139
- 'customer.subscription.updated', 'customer.subscription.paused', 'customer.subscription.resumed',
140
- 'payout.created', 'payout.paid', 'payout.canceled', 'price.created', 'product.created',
141
- 'setup_intent.succeeded', 'setup_intent.created',
142
- // The twin's checkout completion transition records the op AS the real event type:
143
- // real Stripe fires checkout.session.completed (data.object = the completed Session)
144
- // the moment a session reaches status=complete — the event most billing integrations
145
- // fulfill from, so it must pass through, not be swallowed.
146
- 'checkout.session.completed',
147
- // Issuing writes record the op AS the real event type (issuing_authorization.updated on
148
- // approve/decline/update, issuing_card.updated on card updates, …) — all real vendor
149
- // event types (stripe@22.3.0 WebhookEndpoint.EnabledEvent enum).
150
- 'issuing_authorization.updated', 'issuing_card.updated', 'issuing_cardholder.updated',
151
- 'issuing_transaction.updated',
152
- ]);
153
- if (PASSTHROUGH.has(operation))
154
- return operation;
155
- switch (operation) {
156
- case 'customer.create': return 'customer.created';
157
- case 'payment_intent.create': return 'payment_intent.created';
158
- case 'payment_intent.confirm': return 'payment_intent.succeeded';
159
- case 'payment_method.attach': return 'payment_method.attached';
160
- case 'payment_method.detach': return 'payment_method.detached';
161
- case 'setup_intent.confirm': return 'setup_intent.succeeded';
162
- case 'subscription.create': return 'customer.subscription.created';
163
- case 'subscription.update': return 'customer.subscription.updated';
164
- case 'subscription.cancel': return 'customer.subscription.deleted';
165
- case 'invoice.finalize': return 'invoice.finalized';
166
- case 'invoice.pay': return 'invoice.paid';
167
- case 'invoice.void': return 'invoice.voided';
168
- case 'refund.create': return 'refund.created';
169
- case 'dispute.create': return 'charge.dispute.created';
170
- case 'payout.create': return 'payout.created';
171
- case 'product.create': return 'product.created';
172
- case 'price.create': return 'price.created';
173
- // Issuing: real Stripe fires issuing_authorization.created/.updated,
174
- // issuing_card.created/.updated, issuing_cardholder.created/.updated and
175
- // issuing_transaction.created (all present in the vendor SDK's
176
- // WebhookEndpoint.EnabledEvent enum, stripe@22.3.0 WebhookEndpoints.d.ts).
177
- // issuing_authorization.request is deliberately NOT here: it is not a
178
- // state-change event — the twin delivers it SYNCHRONOUSLY from the
179
- // present-authorization flow (requestAuthorizationDecision below).
180
- case 'issuing_authorization.create': return 'issuing_authorization.created';
181
- case 'issuing_card.create': return 'issuing_card.created';
182
- case 'issuing_cardholder.create': return 'issuing_cardholder.created';
183
- case 'issuing_transaction.create': return 'issuing_transaction.created';
184
- default: return vendorEventType(operation);
185
- }
186
- }
187
- /** Any other write records the event Stripe sends for it, when Stripe sends one: the operation itself, or its
188
- * resource's create/update/delete as `<resource>.created|updated|deleted` (the types Stripe's spec enumerates). */
189
- function vendorEventType(operation) {
190
- if (VENDOR_EVENT_TYPES.has(operation))
191
- return operation;
192
- const verb = /^(.+)\.(create|update|delete)$/.exec(operation);
193
- return verb && VENDOR_EVENT_TYPES.has(`${verb[1]}.${verb[2]}d`) ? `${verb[1]}.${verb[2]}d` : null;
194
- }
195
- /** An event's id, DERIVED from the event itself — the operation, the resource it carries and the instant —
196
- * never a process counter (protocol 2: two identical worlds deliver identically, and a replay of the same
197
- * write raises the same event id rather than one that drifts with process uptime). */
198
- function eventId(operation, resource, occurredAt, account) {
199
- let h = 0x811c9dc5;
200
- const seed = `${operation}|${String(resource.id ?? '')}|${occurredAt}|${account ?? ''}`;
201
- for (let i = 0; i < seed.length; i += 1) {
202
- h ^= seed.charCodeAt(i);
203
- h = Math.imul(h, 0x01000193) >>> 0;
204
- }
205
- return `evt_twin_${h.toString(16).padStart(8, '0')}`;
206
- }
207
- // Live HTTP delivery signs exactly like real Stripe: HMAC-SHA256 over
208
- // `${timestamp}.${payload}` keyed by the ENDPOINT'S OWN signing secret (the
209
- // `whsec_twin_*` minted by POST /v1/webhook_endpoints and registered alongside the
210
- // URL), sent as `Stripe-Signature: t=...,v1=...`. The signed bytes are the exact
211
- // request body, so `stripe.webhooks.constructEvent(rawBody, header, secret)` in the
212
- // consumer's real SDK verifies twin deliveries unchanged (a hardcoded placeholder
213
- // header made every verifying consumer 400 — the delivery was unverifiable).
214
- // Delivery is AT-LEAST-ONCE, like the vendor: real Stripe re-attempts a webhook whose
215
- // delivery fails at the transport layer rather than dropping it, so a consumer that missed
216
- // one event because a socket blipped is a consumer real Stripe would have reached. A single
217
- // swallowed `fetch` rejection here is indistinguishable, downstream, from the consumer
218
- // having a bug — it cost a week of "the settlement webhook is racy" before anyone could see
219
- // that the event had simply never left the twin. Two cheap re-attempts cover a transient
220
- // local failure (ECONNRESET / socket exhaustion under a boot storm); a genuinely unreachable
221
- // endpoint refuses instantly, so the retries cost microseconds. A NON-2xx response is the
222
- // consumer answering, not a transport failure — it is not retried here.
223
- // A delivery that still fails after the re-attempts is DROPPED, and says so: silent loss is
224
- // the one outcome a twin must never have, because it makes every consumer look flaky.
225
- const DELIVERY_ATTEMPTS = 3;
226
- const httpDelivery = async (url, event, endpointSecret) => {
227
- // the event as its API version renders it (stripe-version.ts)
228
- const payload = JSON.stringify(render(event, event.api_version));
229
- const secret = endpointSecret ?? secrets.get(url) ?? STRIPE_WEBHOOK_FALLBACK_SECRET;
230
- // the World's egress rule: an endpoint it refuses is not delivered to, and says so; the application's own hostnames
231
- // reach it inside the World
232
- const refusal = appDestination(url) ? null : worldEgressRefusal(url);
233
- if (refusal !== null)
234
- console.error(`[twin:stripe] webhook delivery DROPPED — ${event.type} ${event.id} -> ${url}: ${refusal}`);
235
- return refusal !== null ? undefined : postEvent(url, event, payload, secret);
236
- };
237
- /** The HTTP POST of a signed event to an endpoint the World lets it reach, re-attempted on a transport failure. */
238
- async function postEvent(url, event, payload, secret) {
239
- let last = '';
240
- for (let attempt = 1; attempt <= DELIVERY_ATTEMPTS; attempt += 1) {
241
- try {
242
- const header = generateTestHeaderString({ payload, secret });
243
- await appFetch(url, { method: 'POST', headers: { 'content-type': 'application/json', 'stripe-signature': header, ...deliveryTraceHeaders() }, body: payload });
244
- return;
245
- }
246
- catch (error) {
247
- last = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
248
- if (attempt < DELIVERY_ATTEMPTS)
249
- await new Promise((resolve) => setTimeout(resolve, 25 * attempt));
250
- }
251
- }
252
- console.error(`[twin:stripe] webhook delivery DROPPED after ${DELIVERY_ATTEMPTS} attempts — ${event.type} ${event.id} -> ${url}: ${last}`);
253
- }
254
- // Default deliverer override (a TEST SEAM). The twin's write path emits events without
255
- // threading a per-call deliverer, so to drive event delivery fully OFFLINE/deterministically
256
- // — no real sockets — a test installs a fake sink here. When unset, real HTTP POST is used
257
- // (prod behavior). This keeps D5 honest: verify() exercises the twin's own emission, in-process.
258
- // a slot, not module truth (protocol 2): WHERE a delivery goes, set once by the host that mounts the twin
259
- const defaultDelivery = { current: null };
260
- /** Install a default deliverer used by the write path when no per-call `deliver` is passed. */
261
- export function setStripeEventDelivery(deliver) {
262
- defaultDelivery.current = deliver;
263
- }
264
- // ── Real-time authorization (issuing_authorization.request) — the SYNCHRONOUS leg ────────
265
- // Real Stripe delivers issuing_authorization.request to the ONE enrolled endpoint while the
266
- // card network holds the authorization open, and the endpoint must answer within Stripe's
267
- // documented 2-second window ("This request should be made within the timeout window of the
268
- // real-time authorization flow" — stripe@22.3.0 Issuing/Authorizations.d.ts; the current
269
- // method is to "respond directly to the webhook request to approve an authorization"). The
270
- // endpoint's HTTP response body carries the decision: a JSON object with a boolean
271
- // `approved` (and, for an amount-controllable request, an optional integer `amount` to hold
272
- // a different amount). Outcomes map onto the vendor's request_history.reason values
273
- // (stripe@22.3.0 RequestHistory.Reason):
274
- // webhook_approved / webhook_declined — the endpoint answered in time;
275
- // webhook_timeout — no response arrived inside the window (incl. unreachable endpoint);
276
- // webhook_error — "the direct webhook response is invalid (for example, parsing errors
277
- // or missing parameters)" (verbatim from the SDK's reason_message doc),
278
- // i.e. non-2xx status, non-JSON body, or a missing `approved`.
279
- // On timeout/error real Stripe DECLINES the authorization (fail-closed; the card's own
280
- // spending_controls remain the backstop) — the account-level "approve on timeout" opt-in is
281
- // not API-configurable and is not modeled.
282
- export const STRIPE_REALTIME_AUTH_TIMEOUT_MS = 2_000;
283
- // The live synchronous deliverer: POST the signed event and WAIT for the response within
284
- // the 2s window. Signs with the enrolled endpoint's own whsec (passed by the caller, read
285
- // from the endpoint's state row) — never a placeholder.
286
- async function httpAuthRequestDelivery(url, event, secret) {
287
- // the event as its API version renders it (stripe-version.ts)
288
- const payload = JSON.stringify(render(event, event.api_version));
289
- const header = generateTestHeaderString({ payload, secret });
290
- // the World's egress rule: a refused endpoint is an unreachable one (the caller's timeout fallback); the
291
- // application's own hostnames reach it inside the World
292
- const refusal = appDestination(url) ? null : worldEgressRefusal(url);
293
- return refusal !== null ? Promise.reject(new Error(refusal)) : postAuthRequest(url, payload, header);
294
- }
295
- /** The HTTP POST of a real-time authorization request, cut off at the window, and the endpoint's answer. */
296
- async function postAuthRequest(url, payload, header) {
297
- const res = await appFetch(url, {
298
- method: 'POST',
299
- headers: { 'content-type': 'application/json', 'stripe-signature': header, ...deliveryTraceHeaders() },
300
- body: payload,
301
- signal: AbortSignal.timeout(STRIPE_REALTIME_AUTH_TIMEOUT_MS),
302
- });
303
- return { status: res.status, body: await res.text() };
304
- }
305
- /**
306
- * Deliver an issuing_authorization.request event to the enrolled endpoint and interpret
307
- * its synchronous response as the authorization decision. Honors the installed test
308
- * deliverer (setStripeEventDelivery) so verifies run fully offline: a fake returning a
309
- * {status, body} response drives the decision; a fake that throws a TimeoutError (the
310
- * exact error AbortSignal.timeout produces) exercises the timeout fallback.
311
- */
312
- export async function requestAuthorizationDecision(url, event, secret) {
313
- let res;
314
- try {
315
- res = defaultDelivery.current ? await defaultDelivery.current(url, event) : await httpAuthRequestDelivery(url, event, secret);
316
- }
317
- catch (e) {
318
- // no answer inside the window: cut off (TimeoutError, AbortError), or never reached (refused, DNS, reset), alike
319
- return (e instanceof Error && (e.name === 'TimeoutError' || e.name === 'AbortError')) ? TIMED_OUT : UNREACHED;
320
- }
321
- return readDecision(res);
322
- }
323
- const TIMED_OUT = { kind: 'timeout', message: 'Webhook endpoint did not respond within the real-time authorization window.' };
324
- const UNREACHED = { kind: 'timeout', message: 'Webhook endpoint was unreachable within the real-time authorization window.' };
325
- /** The endpoint's synchronous answer read as the decision: `approved` (and an optional `amount`), or an error for an
326
- * answer Stripe cannot read. */
327
- function readDecision(res) {
328
- if (!res || typeof res !== 'object') {
329
- return { kind: 'error', message: 'Webhook endpoint returned no response body.' };
330
- }
331
- if (res.status < 200 || res.status >= 300) {
332
- return { kind: 'error', message: `Webhook endpoint responded with HTTP status ${res.status}.` };
333
- }
334
- let parsed;
335
- try {
336
- parsed = JSON.parse(res.body);
337
- }
338
- catch {
339
- return { kind: 'error', message: 'Webhook response body was not valid JSON.' };
340
- }
341
- const approved = parsed?.approved;
342
- if (typeof approved !== 'boolean') {
343
- return { kind: 'error', message: 'Webhook response is missing the required `approved` parameter.' };
344
- }
345
- if (!approved)
346
- return { kind: 'declined' };
347
- const amount = parsed.amount;
348
- return { kind: 'approved', ...(typeof amount === 'number' && Number.isInteger(amount) && amount > 0 ? { amount } : {}) };
349
- }
350
- /**
351
- * Emit a Stripe event for a twin write to registered endpoints. `resource` is the
352
- * Stripe object the event is about. `occurredAt` is caller-supplied (deterministic).
353
- * Returns the delivered events (for assertions); no-op when nothing is registered
354
- * or the operation has no mapped event type.
355
- *
356
- * Fan-out filters by each endpoint's registered enabled_events (stripeEventMatches — '*',
357
- * 'family.*', exact), like the vendor: a consumer enrolled for one event type receives
358
- * only that type. A URL registered without a list (test seam) receives everything.
359
- */
360
- export async function emitStripeEvent(operation, resource, opts = { occurredAt: '1970-01-01T00:00:00.000Z' }) {
361
- const type = eventTypeFor(operation);
362
- // the World's own endpoints (its tree is the record), then any URL a host registered directly
363
- const targets = [...(opts.endpoints ?? [])];
364
- for (const url of registry)
365
- if (!targets.some((t) => t.url === url))
366
- targets.push({ url, ...(secrets.has(url) ? { secret: secrets.get(url) } : {}), ...(subscriptions.has(url) ? { enabledEvents: subscriptions.get(url) } : {}) });
367
- if (!type || targets.length === 0)
368
- return [];
369
- const deliver = opts.deliver ?? defaultDelivery.current ?? httpDelivery;
370
- const event = {
371
- id: opts.id ?? eventId(operation, resource, opts.occurredAt, opts.account),
372
- object: 'event',
373
- type,
374
- created: Math.floor(Date.parse(opts.occurredAt) / 1000) || 0,
375
- livemode: false,
376
- data: { object: resource },
377
- // "Each event for a connected account contains a top-level `account` property that identifies the connected account"
378
- ...(opts.account ? { account: opts.account } : {}),
379
- };
380
- const out = [];
381
- for (const target of targets) {
382
- if (target.enabledEvents && !stripeEventMatches(target.enabledEvents, type))
383
- continue;
384
- // an endpoint's scope (docs.stripe.com/connect/webhooks): `connect: true` receives the Connected accounts scope,
385
- // `connect: false` Your account; a URL registered without a scope (a host's seam) receives both
386
- if (target.connect !== undefined && target.connect !== Boolean(opts.account))
387
- continue;
388
- await deliver(target.url, event, target.secret);
389
- out.push(event);
390
- }
391
- return out;
392
- }
@@ -1,4 +0,0 @@
1
- /** The release train a script path names: `/v3`, `/v3/` or `/v3/stripe.js` → 3, `/<train>/stripe.js` → the train. */
2
- export declare function stripeJsTrain(pathname: string): 3 | string | undefined;
3
- /** js.stripe.com's script for a GET of its path, or undefined for any other request. */
4
- export declare function stripeJs(request: Request): Response | undefined;
@@ -1,70 +0,0 @@
1
- // STRIPE.JS — the client library an application's page loads from js.stripe.com (docs/contributing/architecture.md,
2
- // "Screens": a widget the vendor ships into the application's own page "is not a screen: it is a client library,
3
- // twinned from its published types as an SDK surface is"). Written from @stripe/stripe-js's published loader and types
4
- // (7.x: dist/index.mjs, dist/stripe-js/stripe.d.ts, dist/stripe-js/hosted-checkout.d.ts), nothing of Stripe's script
5
- // copied:
6
- // - the loader injects https://js.stripe.com/<release train>/stripe.js (or /v3/), and accepts a script already on the
7
- // page whose src matches `/^https:\/\/js\.stripe\.com\/(v3|[a-z]+)\/stripe\.js(\?.*)?$/` (so /v3/stripe.js too);
8
- // it resolves `window.Stripe`, reads `Stripe.version` (3 is the v3 URL, otherwise the train's name) and calls the
9
- // instance's `_registerWrapper` when it has one;
10
- // - `stripe.redirectToCheckout({ sessionId })` sends the customer to that Checkout Session's page (hosted-checkout.d.ts,
11
- // RedirectToCheckoutServerOptions), which this twin serves at checkout.stripe.com/c/pay/{id} (screens/checkout.tsx),
12
- // and its promise settles only on failure (`Promise<never | {error}>`);
13
- // - `stripe.collectFinancialConnectionsAccounts({ clientSecret })` loads the Financial Connections authentication
14
- // flow for the session whose client_secret it is (stripe.d.ts; docs.stripe.com/js/financial_connections/
15
- // collect_financial_connections_accounts: "it will load the Authentication Flow, an on-page modal UI"). Where the
16
- // twin decides: it navigates to the flow's page, js.stripe.com/v3/financial-connections/{client_secret}
17
- // (screens/financial-connections.tsx), instead of a modal, so its promise does not settle; the flow returns the
18
- // holder to the session's return_url, where the application reads the session's accounts.
19
- // Demand: Dub's upgrade button (apps/web/ui/workspaces/upgrade-plan-button.tsx) creates a session on its server and
20
- // calls redirectToCheckout. Every other member of the library throws, naming itself, when called: an application
21
- // reaching one finds the gap instead of a silent no-op.
22
- /** The release train a script path names: `/v3`, `/v3/` or `/v3/stripe.js` → 3, `/<train>/stripe.js` → the train. */
23
- export function stripeJsTrain(pathname) {
24
- if (/^\/v3(\/|\/stripe\.js)?$/.test(pathname))
25
- return 3;
26
- return /^\/([a-z]+)\/stripe\.js$/.exec(pathname)?.[1];
27
- }
28
- function script(version) {
29
- return `(function () {
30
- var version = ${JSON.stringify(version)};
31
- function gap(name) {
32
- return function () { throw new Error("Stripe.js (Volter twin): stripe." + name + " is not modelled by this twin yet"); };
33
- }
34
- function Stripe(publishableKey) {
35
- if (typeof publishableKey !== "string" || !publishableKey) throw new Error("Stripe.js (Volter twin): Stripe() needs a publishable key");
36
- var known = {
37
- _registerWrapper: function () {},
38
- redirectToCheckout: function (options) {
39
- if (!options || typeof options.sessionId !== "string" || !options.sessionId) return gap("redirectToCheckout without a sessionId")();
40
- window.location.assign("https://checkout.stripe.com/c/pay/" + encodeURIComponent(options.sessionId));
41
- return new Promise(function () {});
42
- },
43
- collectFinancialConnectionsAccounts: function (options) {
44
- if (!options || typeof options.clientSecret !== "string" || !options.clientSecret) return gap("collectFinancialConnectionsAccounts without a clientSecret")();
45
- window.location.assign("https://js.stripe.com/v3/financial-connections/" + encodeURIComponent(options.clientSecret));
46
- return new Promise(function () {});
47
- }
48
- };
49
- return new Proxy(known, {
50
- get: function (target, name) {
51
- if (name in target) return target[name];
52
- if (typeof name === "symbol" || name === "then") return undefined;
53
- return gap(String(name));
54
- }
55
- });
56
- }
57
- Stripe.version = version;
58
- window.Stripe = Stripe;
59
- })();
60
- `;
61
- }
62
- /** js.stripe.com's script for a GET of its path, or undefined for any other request. */
63
- export function stripeJs(request) {
64
- if (request.method !== 'GET')
65
- return undefined;
66
- const train = stripeJsTrain(new URL(request.url).pathname);
67
- if (train === undefined)
68
- return undefined;
69
- return new Response(script(train), { headers: { 'content-type': 'application/javascript; charset=utf-8', 'access-control-allow-origin': '*' } });
70
- }
@@ -1,15 +0,0 @@
1
- export * from './stripe-shared.js';
2
- /** Build the React/TSX dashboard client to browser JS (Bun bundles TSX); cached. */
3
- export declare function buildStripeMirrorClient(): Promise<string>;
4
- /** Serve the Stripe Dashboard (React app) with the twin's own fetch adapter mounted beside it. */
5
- export declare function createStripeMirrorServer(options: {
6
- root?: string;
7
- port?: number;
8
- }): Promise<{
9
- port: number;
10
- stop: () => void;
11
- }>;
12
- /** The app-shell HTML (pure, for tests). The Dashboard itself is the React client. */
13
- export declare function stripeMirrorHtml(): string;
14
- /** The mirror's stylesheet, for a host serving the shell's `assets/styles.css` itself (the hosted mirror mount). */
15
- export declare function stripeMirrorStyles(): Promise<string>;
@@ -1,87 +0,0 @@
1
- // The Stripe Dashboard (manifest screen `dashboard`, dashboard.stripe.com/test/{section}): a React app
2
- // (Bun-bundled) served beside the twin. A PURE FRONTEND (runtime contract R3): this module is the shell, its
3
- // assets and one listener that mounts the pack's OWN fetch adapter beside them. It imports no handler and no
4
- // twin internals; the client reads and writes only through Stripe's API (`/v1/...`, client/dashboard-api.ts),
5
- // so it renders a twin or a real account's test data unchanged, pointed at any origin by configuration.
6
- import { readFile } from 'node:fs/promises';
7
- import { bundleClient, fileResponse, filePathOf } from '@volter/world-core';
8
- import { serveHttp } from '@volter/world-core';
9
- import { createStripeTwinFetch } from "./stripe-server.js";
10
- const CLIENT_ENTRY = () => filePathOf(new URL('../client/stripe-mirror.tsx', import.meta.url)); // lazy: workerd rejects top-level relative URL from import.meta.url (bundled via pack index)
11
- const CLIENT_CSS = () => filePathOf(new URL('../client/stripe-mirror.css', import.meta.url)); // lazy: workerd rejects top-level relative URL from import.meta.url (bundled via pack index)
12
- // ---------------------------------------------------------------------------
13
- // Pure, dependency-free render/format/resolution helpers.
14
- //
15
- // These are intentionally framework-agnostic (plain data in → plain data out) so
16
- // they can be unit-tested in isolation AND imported by the React/TSX client
17
- // (Bun tree-shakes the server-only exports below out of the browser bundle).
18
- // Keep them free of any `@volter/world-core`/`Bun`/twin-adapter usage.
19
- // ---------------------------------------------------------------------------
20
- export * from "./stripe-shared.js";
21
- import { flattenStripeValue, resolveCrossRefs } from "./stripe-shared.js";
22
- void flattenStripeValue;
23
- void resolveCrossRefs;
24
- const APP_SHELL = `<!doctype html>
25
- <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
26
- <base href="/"><title>Dashboard – Stripe</title><link rel="stylesheet" href="assets/styles.css"></head>
27
- <body><div id="root"></div><script type="module" src="assets/app.js"></script></body></html>`;
28
- let clientBundle = null;
29
- /** Build the React/TSX dashboard client to browser JS (Bun bundles TSX); cached. */
30
- export function buildStripeMirrorClient() {
31
- if (!clientBundle) {
32
- clientBundle = bundleClient(CLIENT_ENTRY())
33
- .catch((error) => { clientBundle = null; throw error; });
34
- }
35
- return clientBundle;
36
- }
37
- /** Serve the Stripe Dashboard (React app) with the twin's own fetch adapter mounted beside it. */
38
- export async function createStripeMirrorServer(options) {
39
- const twin = createStripeTwinFetch(options);
40
- const server = await serveHttp({
41
- // LOOPBACK-SPECIFIC bind (2026-08-20, the roving ui-verify flake): with the default
42
- // wildcard hostname, `port: 0` can be handed a port some long-running app already LISTENS
43
- // on at 127.0.0.1 (SO_REUSEADDR allows the overlapping non-identical bind), and the more
44
- // specific loopback listener then shadows this server for every 127.0.0.1 fetch — the
45
- // verify talks to a STRANGER (captured: a desktop app's asset server answering 404s on the
46
- // mirror's port). Binding 127.0.0.1 makes the kernel allocate a port that is actually free
47
- // on loopback, so the verify's fetches deterministically reach THIS server.
48
- hostname: '127.0.0.1',
49
- port: options.port ?? 0,
50
- idleTimeout: 60,
51
- async fetch(request) {
52
- const url = new URL(request.url);
53
- if (request.method === 'GET' && url.pathname === '/assets/app.js') {
54
- try {
55
- return new Response(await buildStripeMirrorClient(), { headers: { 'content-type': 'text/javascript; charset=utf-8' } });
56
- }
57
- catch (error) {
58
- return new Response(String(error), { status: 500 });
59
- }
60
- }
61
- if (request.method === 'GET' && url.pathname === '/assets/styles.css') {
62
- return fileResponse(CLIENT_CSS(), { headers: { 'content-type': 'text/css; charset=utf-8' } });
63
- }
64
- // the Dashboard's own paths (/test/payments, /test/customers/cus_…) are the app; `/` opens Home
65
- if (request.method === 'GET' && (url.pathname === '/' || url.pathname === '' || url.pathname === '/test' || url.pathname.startsWith('/test/'))) {
66
- return new Response(APP_SHELL, { headers: { 'content-type': 'text/html; charset=utf-8' } });
67
- }
68
- // everything else → the twin's OWN FETCH ADAPTER (composition, R2): the React client fetches
69
- // the vendor's real paths (/v1/<collection>) and this is the same closure
70
- // `createStripeTwinServer` mounts, so there is exactly ONE serving code path — the `/twin`
71
- // manifest door, the form-encoded body passed through byte-for-byte, the Idempotency-Key /
72
- // Stripe-Version / Stripe-Account threading, the `request-id` response header, the world
73
- // clock and an honorable `readOnly` all come from it, and the mirror port cannot drift from
74
- // the API port.
75
- return twin(request);
76
- },
77
- });
78
- return { port: server.port ?? options.port ?? 0, stop: () => server.stop(true) };
79
- }
80
- /** The app-shell HTML (pure, for tests). The Dashboard itself is the React client. */
81
- export function stripeMirrorHtml() {
82
- return APP_SHELL;
83
- }
84
- /** The mirror's stylesheet, for a host serving the shell's `assets/styles.css` itself (the hosted mirror mount). */
85
- export function stripeMirrorStyles() {
86
- return readFile(CLIENT_CSS(), 'utf8');
87
- }
@@ -1,9 +0,0 @@
1
- import { type StripeExecute } from './stripe-connector.js';
2
- export declare function performPending(execute: StripeExecute, opts: {
3
- root?: string;
4
- occurredAt: string;
5
- }): Promise<{
6
- pushed: number;
7
- confirmed: string[];
8
- externalIds: Record<string, string>;
9
- }>;
@@ -1,26 +0,0 @@
1
- // A MINIATURE OF THE HEAD, for this pack's own claims and suites (protocol 2). The kernel's loop
2
- // (`performEntries`) needs a bound root and a sealed credential a unit test does not have; this is the same
3
- // shape without one — the same `deployableEntries`, the pack's own push, the same `confirmAction`. Not on
4
- // the serve path, not exported from the pack.
5
- import { confirmAction, deployableEntries, worldNow } from '@volter/world-core';
6
- import { INTERNAL_SUBJECT_TYPES, isPushable, pushStripeAction } from "./stripe-connector.js";
7
- export async function performPending(execute, opts) {
8
- const confirmed = [];
9
- const externalIds = {};
10
- for (const entry of deployableEntries('stripe', opts.root)) {
11
- const op = entry.operation ?? `${entry.subject.type}.update`;
12
- // the twin's own records — the recorded event envelopes and the idempotency bookkeeping — are local
13
- // state and are never sent
14
- if (INTERNAL_SUBJECT_TYPES.has(entry.subject.type) || !isPushable(op))
15
- continue;
16
- const { externalId } = await pushStripeAction(execute, { operation: op, subject: entry.subject, fields: entry.fields ?? {} });
17
- confirmAction({
18
- service: 'stripe', actionId: entry.id, subject: entry.subject, fields: entry.fields ?? {},
19
- occurredAt: opts.occurredAt ?? worldNow(), vendorSubjectId: externalId, receipt: { status: 'deployed' },
20
- ...(opts.root !== undefined ? { root: opts.root } : {}),
21
- });
22
- confirmed.push(entry.id);
23
- externalIds[entry.id] = externalId;
24
- }
25
- return { pushed: confirmed.length, confirmed, externalIds };
26
- }
@@ -1,33 +0,0 @@
1
- import { type DerivedFetch } from '@volter/world-core';
2
- /** Options shared by the fetch handler and the Bun.serve wrapper around it. `port` is a
3
- * BIND concern the fetch ignores; it stays in one shape so a caller configures the twin
4
- * once whichever way it is mounted. */
5
- export type StripeTwinOptions = {
6
- root?: string;
7
- port?: number;
8
- readOnly?: boolean; /** the World instant, when a caller pins it */
9
- clock?: () => string;
10
- };
11
- /**
12
- * The whole Stripe serve path as a plain `(Request) => Response` — the `/twin` manifest
13
- * door, the header threading (idempotency key, pinned API version, Connect account) and
14
- * the derived dispatch over the hand-written routes. NOTHING about it is port-bound.
15
- *
16
- * Why this is the factory and `createStripeTwinServer` is a wrapper (runtime contract R12,
17
- * the Cloudflare ruling): a Durable Object / Worker entry has no loopback ports — it mounts
18
- * pack fetches IN-PROCESS behind one router. Handing that entry `Bun.serve` is not an
19
- * option, so the vendor HTTP adaptation has to be a value it can call. Keeping the server a
20
- * thin `Bun.serve(fetch)` also means the local and hosted lanes execute the SAME bytes of
21
- * serving code — the parity claim (R9) is about one code path, not two that resemble each
22
- * other.
23
- *
24
- * SCOPING THE STORES AROUND IT: this fetch is ASYNC, so install the world store with
25
- * `setActiveWorldStore(store)` in a try/finally — **not** `withWorldStore(store, fn)`, whose
26
- * `finally` fires when `fn` RETURNS, i.e. at the first `await`, restoring the previous store
27
- * under the rest of the request.
28
- */
29
- export declare function createStripeTwinFetch(options: StripeTwinOptions): DerivedFetch;
30
- export declare function createStripeTwinServer(options: StripeTwinOptions): Promise<{
31
- port: number;
32
- stop: () => void;
33
- }>;