@volter/twin-stripe 2.0.38 → 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
@@ -0,0 +1,184 @@
1
+ // Connect semantics: connected accounts (and the platform's own account), their persons,
2
+ // capabilities, external (payout) accounts, login links, onboarding links and embedded-component
3
+ // sessions. A new connected account is not yet active: charges and payouts are off and its
4
+ // requirements are outstanding, as on Stripe before onboarding. Account retrieve and delete and
5
+ // the person list are the derived core's.
6
+ import { accountRequirements, accountSettings, asBool, PLATFORM_ACCOUNT_ID } from './stripe.ts';
7
+ import { currentlyDue, kindOf } from './onboarding.ts';
8
+ import { externalList, type Row } from './common.ts';
9
+
10
+ // the platform's own account: stored once it is written, otherwise Stripe's default. It "controls itself" (controller
11
+ // type `account`, docs.stripe.com/api/accounts/object), is fully onboarded with nothing due, and takes card payments
12
+ // and transfers. Where the documentation stops and the twin decides: it was created as the World began (2026-01-01),
13
+ // and its bank account, which its automatic payouts reach, is not modelled, so it lists none.
14
+ export const PLATFORM_CREATED = 1_767_225_600;
15
+ /** The platform's own account as Stripe's default has it, before anything is written to it. */
16
+ export const platformAccountDefault = (): Row => ({
17
+ object: 'account', id: PLATFORM_ACCOUNT_ID, type: 'standard', country: 'US', default_currency: 'usd', created: PLATFORM_CREATED,
18
+ charges_enabled: true, payouts_enabled: true, details_submitted: true, email: null, metadata: {},
19
+ capabilities: { card_payments: 'active', transfers: 'active' }, controller: { type: 'account' },
20
+ requirements: { alternatives: [], current_deadline: null, currently_due: [], disabled_reason: null, errors: [], eventually_due: [], past_due: [], pending_verification: [] },
21
+ future_requirements: { alternatives: [], current_deadline: null, currently_due: [], disabled_reason: null, errors: [], eventually_due: [], past_due: [], pending_verification: [] },
22
+ external_accounts: externalList(PLATFORM_ACCOUNT_ID, []), tos_acceptance: { date: null, ip: null, user_agent: null }, business_profile: {},
23
+ settings: accountSettings(undefined), livemode: false,
24
+ });
25
+
26
+ /** A new Express account owes what its hosted onboarding will ask for (screens/connect-onboarding.tsx; the US sets
27
+ * docs.stripe.com/connect/required-verification-information lists), or, where the twin does not model the set, the
28
+ * generic list. */
29
+ export function expressRequirements(params: Row): Row {
30
+ const kind = kindOf({ country: params.country ?? 'US', business_type: params.business_type ?? 'individual' });
31
+ const base = accountRequirements();
32
+ return kind ? { ...base, currently_due: currentlyDue(kind), eventually_due: currentlyDue(kind) } : base;
33
+ }
34
+
35
+ /** The controller an account made with a `type` has: "Each of the three account types maps to values in the
36
+ * `controller` hash", Standard to losses.payments `stripe`, fees.payer `account`, requirement_collection `stripe` and
37
+ * a `full` dashboard, Express to `application`, `application_express`, `stripe` and `express`, Custom to
38
+ * `application`, `application_custom`, `application` and `none`; each "type": "application", "is_controller": true
39
+ * (docs.stripe.com/connect/migrate-to-controller-properties). */
40
+ export function controllerOf(type: string): Row {
41
+ const [losses, payer, collection, dashboard] = type === 'express' ? ['application', 'application_express', 'stripe', 'express']
42
+ : type === 'custom' ? ['application', 'application_custom', 'application', 'none'] : ['stripe', 'account', 'stripe', 'full'];
43
+ return { type: 'application', is_controller: true, losses: { payments: losses }, fees: { payer }, requirement_collection: collection, stripe_dashboard: { type: dashboard } };
44
+ }
45
+
46
+ /** What a Custom account still owes, from what the platform has given for it, as Stripe's requirements endpoint lists it
47
+ * for a US account with no Stripe Dashboard and the full service agreement
48
+ * (docs.stripe.com/_endpoint/get-requirements-for-setups, the data behind
49
+ * docs.stripe.com/connect/required-verification-information). With transfers alone, a company owes business_profile.url,
50
+ * company.name, an external account and tos_acceptance.date and .ip at once (capability_limit_amount -1: paused until
51
+ * given) and company.tax_id before $3,000 of payouts (payout_limit_amount 300000); an individual owes the url, its
52
+ * first and last name, the bank account and the terms at once, and its date of birth and ssn_last_4 before $3,000 of
53
+ * payouts. Requesting card_payments adds business_profile.mcc and the entity's address at once (and an individual's
54
+ * email and ssn_last_4). A company with card_payments owes, at once, business_profile.mcc, its address, that its owners
55
+ * are provided, each owner's name and email, and its representative's name, email, address, title and ssn_last_4; and
56
+ * in time its phone, its statement descriptor and its representative's date of birth and phone (the endpoint's answer
57
+ * for US / dashboard none / full terms / company / card_payments and transfers, saved in scratch as
58
+ * req-custom-company-cards-transfers.json: capability_limit_amount -1 for the first, none for the second). The
59
+ * representative and the owners are the account's persons (relationship.representative, relationship.owner).
60
+ * Where the documentation stops and the twin decides: what has no limit, or is owed before $3,000 of payouts, is
61
+ * eventually_due and blocks nothing (the twin keeps no payout total against it); an owner field is met when every
62
+ * person marked owner has it (none marked: met). */
63
+ export const at_path = (a: Row, path: string): unknown => path.split('.').reduce<unknown>((v, k) => (v && typeof v === 'object' ? (v as Row)[k] : undefined), a);
64
+ export const CARD_COMPANY_NOW = ['business_profile.mcc', 'company.address.line1', 'company.address.city', 'company.address.state', 'company.address.postal_code', 'company.owners_provided', 'owners.first_name', 'owners.last_name', 'owners.email', 'representative.first_name', 'representative.last_name', 'representative.email', 'representative.address.line1', 'representative.address.city', 'representative.address.state', 'representative.address.postal_code', 'representative.relationship.title', 'representative.ssn_last_4'];
65
+ export const CARD_COMPANY_LATER = ['company.phone', 'settings.payments.statement_descriptor', 'representative.dob.day', 'representative.dob.month', 'representative.dob.year', 'representative.phone'];
66
+ export const CARD_INDIVIDUAL_NOW = ['business_profile.mcc', 'individual.address.line1', 'individual.address.city', 'individual.address.state', 'individual.address.postal_code', 'individual.email', 'individual.ssn_last_4'];
67
+ /** A field only card_payments asks for (the transfers capability's requirements leave it out). */
68
+ export const cardOnly = (field: string): boolean => [...CARD_COMPANY_NOW, ...CARD_COMPANY_LATER, ...CARD_INDIVIDUAL_NOW].includes(field);
69
+ export const personHas = (p: Row, field: string): boolean => {
70
+ if (field === 'ssn_last_4') return p.ssn_last_4_provided === true;
71
+ const v = at_path(p, field);
72
+ return v !== undefined && v !== null && v !== '';
73
+ };
74
+ export const met = (a: Row, bank: boolean, field: string, persons: Row[] = []): boolean => {
75
+ if (field === 'external_account') return bank;
76
+ if (field.startsWith('representative.')) {
77
+ const rep = persons.find((p) => (p.relationship as Row | undefined)?.representative === true);
78
+ return !!rep && personHas(rep, field.slice('representative.'.length));
79
+ }
80
+ if (field.startsWith('owners.')) return persons.filter((p) => (p.relationship as Row | undefined)?.owner === true).every((p) => personHas(p, field.slice('owners.'.length)));
81
+ if (field === 'company.tax_id') return at_path(a, 'company.tax_id_provided') === true;
82
+ if (field === 'individual.ssn_last_4') return at_path(a, 'individual.ssn_last_4_provided') === true;
83
+ const v = at_path(a, field);
84
+ return v !== undefined && v !== null && v !== '';
85
+ };
86
+ export function customRequirements(a: Row, bank: boolean, persons: Row[] = []): { now: string[]; later: string[] } {
87
+ const company = a.business_type === 'company';
88
+ const cards = Object.keys((a.capabilities as Row | undefined) ?? {}).includes('card_payments');
89
+ const now = ['business_profile.url', ...(company ? ['company.name'] : ['individual.first_name', 'individual.last_name']), 'external_account', 'tos_acceptance.date', 'tos_acceptance.ip'];
90
+ if (cards) now.push(...(company ? CARD_COMPANY_NOW : CARD_INDIVIDUAL_NOW));
91
+ const later = [...(company ? ['company.tax_id'] : ['individual.dob.day', 'individual.dob.month', 'individual.dob.year', 'individual.ssn_last_4']), ...(cards && company ? CARD_COMPANY_LATER : [])].filter((f) => !now.includes(f));
92
+ return { now: now.filter((f) => !met(a, bank, f, persons)), later: later.filter((f) => !met(a, bank, f, persons)) };
93
+ }
94
+
95
+ /** A request's company or individual as Stripe keeps it: a tax id or SSN given is kept only as provided (the Account
96
+ * object answers company.tax_id_provided and individual.ssn_last_4_provided, never the numbers;
97
+ * docs.stripe.com/api/accounts/object). */
98
+ export function keptKyc(params: Row): Row {
99
+ const out: Row = { ...params };
100
+ if (params.company && typeof params.company === 'object') {
101
+ const { tax_id, ...company } = params.company as Row;
102
+ out.company = { ...company, ...(tax_id !== undefined && tax_id !== '' ? { tax_id_provided: true } : {}) };
103
+ }
104
+ if (params.individual && typeof params.individual === 'object') {
105
+ const { ssn_last_4, id_number, ...individual } = params.individual as Row;
106
+ out.individual = { ...individual, ...(ssn_last_4 !== undefined && ssn_last_4 !== '' ? { ssn_last_4_provided: true } : {}), ...(id_number !== undefined && id_number !== '' ? { id_number_provided: true } : {}) };
107
+ }
108
+ return out;
109
+ }
110
+
111
+ /** A person's details as Stripe keeps them: an SSN or ID number given is kept only as provided (the Person object
112
+ * answers ssn_last_4_provided and id_number_provided, never the numbers; docs.stripe.com/api/persons/object). */
113
+ export function keptPerson(params: Row, was: Row = {}): Row {
114
+ const { ssn_last_4, id_number, ...rest } = params;
115
+ const out: Row = { ...rest, ...(ssn_last_4 !== undefined && ssn_last_4 !== '' ? { ssn_last_4_provided: true } : {}), ...(id_number !== undefined && id_number !== '' ? { id_number_provided: true } : {}) };
116
+ // a relationship, address or date of birth given in part is laid over what the person holds
117
+ for (const k of ['relationship', 'address', 'dob'] as const) if (out[k] && typeof out[k] === 'object' && was[k] && typeof was[k] === 'object') out[k] = { ...(was[k] as Row), ...(out[k] as Row) };
118
+ return out;
119
+ }
120
+ export const RELATIONSHIP: Row = { director: false, executive: false, owner: false, representative: false, percent_ownership: null, title: null };
121
+
122
+ // ── capabilities: the account's capability map is the truth; requesting one leaves it pending ──
123
+
124
+ /** A capability as its account stands: its status, and the account's requirements that capability asks for (transfers
125
+ * leaves out what only card_payments asks for). Where the documentation stops and the twin decides: the account-wide
126
+ * fields (the bank account, the terms) belong to every capability. */
127
+ export const capabilityBody = (acct: Row, id: string, status: unknown, requested = true, requestedAt: unknown = null): Row => {
128
+ const req = (acct.requirements as Row | undefined) ?? {};
129
+ const mine = (list: unknown): string[] => (Array.isArray(list) ? (list as string[]) : []).filter((f) => id === 'card_payments' || !cardOnly(f));
130
+ const due = mine(req.currently_due);
131
+ return {
132
+ id, object: 'capability', account: acct.id, status, requested, requested_at: requestedAt,
133
+ requirements: { currently_due: due, eventually_due: mine(req.eventually_due), past_due: [], pending_verification: [], errors: [], alternatives: [], current_deadline: null, disabled_reason: due.length ? 'requirements.past_due' : null },
134
+ };
135
+ };
136
+
137
+ // a session is identified by its client_secret: the row is kept for traceability, the answer has no id
138
+ /** Every embedded component an account session answers (the served spec requires all of them), each enabled only when
139
+ * the request enables it, with its features: what the request gives, else the spec's stated default, "The default
140
+ * value for this feature is `true`" (external_account_collection); disable_stripe_user_authentication "the opposite of
141
+ * the `external_account_collection` value"; edit_payout_schedule and standard_payouts "Defaults to `true` when
142
+ * `controller.losses.payments` is set to `stripe` for the account, otherwise `false`"; capture_payments, dispute_management
143
+ * and refund_management "true by default"; destination_on_behalf_of_charge_management "false by default";
144
+ * smart_disputes_management "Defaults to the value of `dispute_management`". Where the documentation stops and the twin
145
+ * decides: instant_payouts (described as `enabled` "when Stripe is responsible for negative account balances", typed
146
+ * boolean) is true exactly then, and the Issuing and financial-account features, which state no default, are false. */
147
+ export const SESSION_COMPONENTS: Record<string, string[]> = {
148
+ account_management: ['external_account_collection', 'disable_stripe_user_authentication'],
149
+ account_onboarding: ['external_account_collection', 'disable_stripe_user_authentication'],
150
+ balance_report: [], documents: [], payout_details: [], payout_reconciliation_report: [], payouts_list: [], tax_registrations: [], tax_settings: [],
151
+ balances: ['external_account_collection', 'disable_stripe_user_authentication', 'edit_payout_schedule', 'instant_payouts', 'standard_payouts'],
152
+ payouts: ['external_account_collection', 'disable_stripe_user_authentication', 'edit_payout_schedule', 'instant_payouts', 'standard_payouts'],
153
+ disputes_list: ['capture_payments', 'destination_on_behalf_of_charge_management', 'dispute_management', 'refund_management', 'smart_disputes_management'],
154
+ payment_details: ['capture_payments', 'destination_on_behalf_of_charge_management', 'dispute_management', 'refund_management', 'smart_disputes_management'],
155
+ payments: ['capture_payments', 'destination_on_behalf_of_charge_management', 'dispute_management', 'refund_management', 'smart_disputes_management'],
156
+ payment_disputes: ['destination_on_behalf_of_charge_management', 'dispute_management', 'refund_management', 'smart_disputes_management'],
157
+ financial_account: ['external_account_collection', 'disable_stripe_user_authentication', 'send_money', 'transfer_balance'],
158
+ financial_account_transactions: ['card_spend_dispute_management'],
159
+ instant_payouts_promotion: ['external_account_collection', 'disable_stripe_user_authentication', 'instant_payouts'],
160
+ issuing_card: ['card_management', 'card_spend_dispute_management', 'cardholder_management', 'spend_control_management'],
161
+ issuing_cards_list: ['card_management', 'card_spend_dispute_management', 'cardholder_management', 'disable_stripe_user_authentication', 'spend_control_management'],
162
+ notification_banner: ['external_account_collection', 'disable_stripe_user_authentication'],
163
+ payment_method_settings: ['disable_stripe_user_authentication'],
164
+ };
165
+ export function sessionComponents(account: Row, given: Row): Row {
166
+ const stripeLosses = (((account.controller as Row | undefined)?.losses as Row | undefined)?.payments) === 'stripe';
167
+ const out: Row = {};
168
+ for (const [name, featureNames] of Object.entries(SESSION_COMPONENTS)) {
169
+ const c = given[name] && typeof given[name] === 'object' ? (given[name] as Row) : {};
170
+ const asked = c.features && typeof c.features === 'object' ? (c.features as Row) : {};
171
+ const f: Row = {};
172
+ const val = (k: string, fallback: boolean): boolean => (asked[k] !== undefined ? asBool(asked[k]) : fallback);
173
+ for (const k of featureNames) {
174
+ if (k === 'external_account_collection') f[k] = val(k, true);
175
+ else if (k === 'disable_stripe_user_authentication') f[k] = val(k, !val('external_account_collection', true));
176
+ else if (k === 'edit_payout_schedule' || k === 'standard_payouts' || k === 'instant_payouts') f[k] = val(k, stripeLosses);
177
+ else if (k === 'capture_payments' || k === 'dispute_management' || k === 'refund_management') f[k] = val(k, true);
178
+ else if (k === 'smart_disputes_management') f[k] = val(k, val('dispute_management', true));
179
+ else f[k] = val(k, false);
180
+ }
181
+ out[name] = { enabled: c.enabled !== undefined ? asBool(c.enabled) : false, features: f };
182
+ }
183
+ return out;
184
+ }
@@ -0,0 +1,5 @@
1
+ // Coupon and PromotionCode semantics. A coupon is exactly one of percent_off or amount_off (with
2
+ // its currency) over a duration; a promotion code is a customer-facing code for an existing
3
+ // coupon, active until switched off (the machine in ../manifest.ts). Coupon list, retrieve, update
4
+ // and delete and promotion-code retrieve and update (`active`, the machine) are the derived core's.
5
+
@@ -0,0 +1,6 @@
1
+ // Credit note semantics. A credit note credits part of an invoice: pre_payment while the invoice
2
+ // is unpaid (it lowers what is owed), post_payment once paid. The invoice carries the sums of its
3
+ // issued credit notes, re-derived on every change so voiding one returns the invoice to where it
4
+ // was. The machine in ../manifest.ts says a credit note is voided once. The list is the derived core's.
5
+
6
+ export const CN = 'credit_note';
@@ -0,0 +1,35 @@
1
+ // Customer semantics: the customer and what hangs off it (tax ids, the credit-balance ledger, the
2
+ // cash balance, legacy sources, attached payment methods) and the top-level Source object. List,
3
+ // update and delete of a customer, retrieve of a Source and the flat tax-id list are the derived core's.
4
+ import { invoicePrefix } from './invoices.ts';
5
+ import type { Row } from './common.ts';
6
+
7
+ /** What a new customer answers before any invoice: its invoice_prefix and a next_invoice_sequence of 1, a zero balance,
8
+ * no metadata (docs.stripe.com/api/customers/object). */
9
+ export const newCustomer = (id: string): Row => ({ invoice_prefix: invoicePrefix(id), next_invoice_sequence: 1, balance: 0, metadata: {}, invoice_settings: {} });
10
+
11
+ // ── tax ids: a customer's, keyed under it; `type` and `value` are required ──
12
+
13
+ // An EU VAT number is its country's prefix and that country's format (the European Commission's VIES formats,
14
+ // ec.europa.eu/taxation_customs/vies); Stripe refuses one that does not fit as tax_id_invalid
15
+ // (docs.stripe.com/error-codes#tax-id-invalid). The message's wording is the twin's.
16
+ export const EU_VAT: Record<string, RegExp> = {
17
+ AT: /^U\d{8}$/, BE: /^[01]\d{9}$/, BG: /^\d{9,10}$/, CY: /^\d{8}[A-Z]$/, CZ: /^\d{8,10}$/, DE: /^\d{9}$/, DK: /^\d{8}$/,
18
+ EE: /^\d{9}$/, EL: /^\d{9}$/, ES: /^[A-Z0-9]\d{7}[A-Z0-9]$/, FI: /^\d{8}$/, FR: /^[A-Z0-9]{2}\d{9}$/, HR: /^\d{11}$/,
19
+ HU: /^\d{8}$/, IE: /^(\d{7}[A-W][A-I]?|\d[A-Z+*]\d{5}[A-W])$/, IT: /^\d{11}$/, LT: /^(\d{9}|\d{12})$/, LU: /^\d{8}$/,
20
+ LV: /^\d{11}$/, MT: /^\d{8}$/, NL: /^\d{9}B\d{2}$/, PL: /^\d{10}$/, PT: /^\d{9}$/, RO: /^\d{2,10}$/, SE: /^\d{12}$/,
21
+ SI: /^\d{8}$/, SK: /^\d{10}$/, XI: /^(\d{9}|\d{12}|GD\d{3}|HA\d{3})$/,
22
+ };
23
+ export const euVatCountry = (value: string): string | undefined => {
24
+ const v = value.replace(/[\s.-]/g, '').toUpperCase();
25
+ const prefix = v.slice(0, 2);
26
+ const format = EU_VAT[prefix];
27
+ return format && format.test(v.slice(2)) ? (prefix === 'EL' ? 'GR' : prefix) : undefined;
28
+ };
29
+
30
+ /** The tax ID types Stripe checks against a government register: "Stripe automatically validates all Australian
31
+ * Business Numbers (ABNs)", "all European Value-Added-Tax (EU VAT) numbers" (VIES) and "all UK Value-Added-Tax (GB VAT)
32
+ * numbers" (HMRC); a verification's status "is pending, verified, unverified, or unavailable", and "When automatic
33
+ * validation is unavailable, you must manually verify the tax ID" (docs.stripe.com/billing/customer/tax-ids). Any other
34
+ * type answers unavailable; one of these waits pending. */
35
+ export const AUTO_VALIDATED = new Set(['au_abn', 'eu_vat', 'gb_vat']);
@@ -0,0 +1,19 @@
1
+ // What Stripe's pages show of an account, and where its Connect OAuth connections are kept.
2
+
3
+ type Row = Record<string, any>;
4
+
5
+ /** The name an account shows its customers (Checkout, the customer portal): its public business name,
6
+ * `business_profile.name` ("The customer-facing business name", docs.stripe.com/api/accounts/object), which the
7
+ * operator sets on the Dashboard ("You can change a Checkout page's name by modifying the Business name field",
8
+ * docs.stripe.com/payments/checkout/customization/appearance). Where the documentation stops and the twin decides:
9
+ * with none set it falls back to the Dashboard's account name, `settings.dashboard.display_name` ("used on the Stripe
10
+ * Dashboard to differentiate between accounts", the same object page), and with neither to "Twin Inc.", the name the
11
+ * twin has always given the World's own account. */
12
+ export const PLATFORM_DEFAULT_NAME = 'Twin Inc.';
13
+ /** The bookkeeping type of a connected account's Connect OAuth connection (../screens/connect-oauth.tsx): one row per
14
+ * account, `revoked: true` once deauthorized or its code reused. Read by the account list and the event path too. */
15
+ export const OAUTH_CONNECTIONS = '_oauth_connection';
16
+ export function publicBusinessName(account: Row | undefined): string {
17
+ const named = (v: unknown): string | undefined => (typeof v === 'string' && v.trim() ? v : undefined);
18
+ return named(account?.business_profile?.name) ?? named(account?.settings?.dashboard?.display_name) ?? PLATFORM_DEFAULT_NAME;
19
+ }
@@ -0,0 +1,9 @@
1
+ // Dispute semantics. A dispute is Stripe's to open, when a charge's cardholder disputes it: the test cards
2
+ // that are disputed open one as their charge succeeds (./after-payment.ts). It is then listed, retrieved,
3
+ // updated with evidence and closed. Closing concedes it (status → lost), the machine's move in
4
+ // ../manifest.ts. Evidence is submitted with the update unless `submit` is false
5
+ // (docs.stripe.com/api/disputes/update#update_dispute-submit), and the bank then decides it: in test mode, evidence whose
6
+ // uncategorized_text is `winning_evidence` wins it and `losing_evidence` loses it (docs.stripe.com/testing#evidence);
7
+ // a won dispute returns the disputed amount. Where the documentation stops and the twin decides: the bank decides at
8
+ // once, and any other evidence leaves the dispute under review. List is the derived core's.
9
+
@@ -0,0 +1,5 @@
1
+ // Entitlements semantics: features (unique by lookup_key) that products grant, and the features a
2
+ // customer is entitled to now, derived from its live subscriptions' products. Feature retrieve is
3
+ // the derived core's.
4
+
5
+ export const FEAT = 'entitlements.feature';
@@ -0,0 +1,3 @@
1
+ // Ephemeral key semantics: the short-lived key the mobile SDKs use, scoped to exactly one object.
2
+ // It needs the Stripe-Version header; its secret is answered only by the create; deleting it
3
+ // expires it early.
@@ -0,0 +1,41 @@
1
+ // File, file link, Identity and billing-portal semantics. A file is the uploaded document's object
2
+ // (the twin keeps no bytes); a file link is answered, not kept. An Identity verification session is
3
+ // created here and verified through the twin's own helper outside Stripe's surface; its reports
4
+ // are the derived core's to list and read, as are file list and retrieve, session retrieve and
5
+ // portal-configuration retrieve.
6
+ import type { Row } from './common.ts';
7
+
8
+ /** The type Stripe answers for an uploaded file: "The returned file type (for example, csv, pdf, jpg, or png)"
9
+ * (docs.stripe.com/api/files/object). Where the documentation stops and the twin decides: read from the name's
10
+ * extension (jpeg as jpg), and null for a name without one. */
11
+ export function fileType(name: string): string | null {
12
+ const ext = /\.([a-z0-9]+)$/i.exec(name)?.[1]?.toLowerCase();
13
+ return ext ? (ext === 'jpeg' ? 'jpg' : ext) : null;
14
+ }
15
+
16
+ /** The purposes a file link may be made to: "The file's `purpose` must be one of the following: …" (the served
17
+ * spec, POST /v1/file_links `file`). */
18
+ export const LINKABLE = ['business_icon', 'business_logo', 'customer_signature', 'dispute_evidence', 'finance_report_run', 'financial_account_statement', 'identity_document_downloadable', 'issuing_regulatory_reporting', 'pci_document', 'selfie', 'sigma_scheduled_query', 'tax_document_user_upload', 'terminal_android_apk', 'terminal_reader_splashscreen'] as const;
19
+
20
+ export const PBC = 'billing_portal.configuration';
21
+
22
+ /** A portal configuration's features, each filled where the request leaves it: every feature is answered (the served
23
+ * spec requires all five), as the create page's example answers a request that sets only customer_update and
24
+ * invoice_history: payment_method_update disabled, subscription_cancel disabled at_period_end with proration_behavior
25
+ * none and its five default reasons, subscription_update disabled with no allowed updates and proration_behavior none
26
+ * (docs.stripe.com/api/customer_portal/configurations/create); trial_update_behavior "Defaults to a value of
27
+ * `end_trial` if you don't set it during creation" (the served spec). Where the documentation stops and the twin
28
+ * decides: a feature the request leaves out is disabled, and schedule_at_period_end has no conditions. */
29
+ export const PORTAL_FEATURES: Row = {
30
+ customer_update: { allowed_updates: [], enabled: false },
31
+ invoice_history: { enabled: false },
32
+ payment_method_update: { enabled: false, payment_method_configuration: null },
33
+ subscription_cancel: { cancellation_reason: { enabled: false, options: ['too_expensive', 'missing_features', 'switched_service', 'unused', 'other'] }, enabled: false, mode: 'at_period_end', proration_behavior: 'none' },
34
+ subscription_update: { default_allowed_updates: [], enabled: false, proration_behavior: 'none', schedule_at_period_end: { conditions: [] }, trial_update_behavior: 'end_trial' },
35
+ };
36
+ export const filled = (base: unknown, given: unknown): unknown => {
37
+ if (!given || typeof given !== 'object' || Array.isArray(given) || !base || typeof base !== 'object' || Array.isArray(base)) return given === undefined ? base : given;
38
+ const out: Row = { ...(base as Row) };
39
+ for (const [k, v] of Object.entries(given as Row)) out[k] = filled((base as Row)[k], v);
40
+ return out;
41
+ };
@@ -0,0 +1,31 @@
1
+ // What a publishable key may call, as data the handlers' shared checks read (../semantics/shared.ts
2
+ // publishableKeyRefused, run by ../semantics/around.ts).
3
+ import { expandOf, render, servesCurrent, withoutEndpointSecret } from './version.ts';
4
+
5
+ type Row = Record<string, unknown>;
6
+
7
+ // ── what a publishable key may call ──
8
+ // "Publishable API key pk_... | Safe to expose: Yes | API key for Stripe.js, Elements, and mobile SDKs. It can identify
9
+ // your account and create tokens or PaymentMethods from payment details, but it can't perform sensitive operations such
10
+ // as creating charges or reading account data" (docs.stripe.com/keys). The served spec names the calls a publishable key
11
+ // makes with an object's client secret: "You can retrieve a PaymentIntent client-side using a publishable key when the
12
+ // client_secret is provided in the query string" (GET /v1/payment_intents/{intent}), "Client-side retrieval using a
13
+ // publishable key is allowed when the client_secret is provided" (GET /v1/setup_intents/{intent}), "Required if a
14
+ // publishable key is used to retrieve the source" (GET /v1/sources/{source}), and the confirm and verify_microdeposits
15
+ // calls that take "The client secret of the PaymentIntent" (or SetupIntent). Anything else is refused with Stripe's
16
+ // code: "secret_key_required | The API key provided is a publishable key, but a secret key is required"
17
+ // (docs.stripe.com/error-codes), as 403, "The API key doesn't have permissions to perform the request"
18
+ // (docs.stripe.com/api/errors).
19
+ // Where the documentation stops and the twin decides: the list above is the whole of what a publishable key may call
20
+ // (Stripe publishes no complete list); a client-secret call without the secret answers parameter_missing, and one with a
21
+ // secret that is not the object's answers the object's 404, as though the key could not see it.
22
+ export const PUBLISHABLE_CREATES = new Set(['PostTokens', 'PostPaymentMethods']);
23
+ export const BY_CLIENT_SECRET: Record<string, { type: string; param: string }> = {
24
+ GetPaymentIntentsIntent: { type: 'payment_intent', param: 'intent' },
25
+ PostPaymentIntentsIntentConfirm: { type: 'payment_intent', param: 'intent' },
26
+ PostPaymentIntentsIntentVerifyMicrodeposits: { type: 'payment_intent', param: 'intent' },
27
+ GetSetupIntentsIntent: { type: 'setup_intent', param: 'intent' },
28
+ PostSetupIntentsIntentConfirm: { type: 'setup_intent', param: 'intent' },
29
+ PostSetupIntentsIntentVerifyMicrodeposits: { type: 'setup_intent', param: 'intent' },
30
+ GetSourcesSource: { type: 'source', param: 'source' },
31
+ };
@@ -0,0 +1,71 @@
1
+ // Invoice and InvoiceItem semantics. The machine in ../manifest.ts says which moves of an invoice's
2
+ // `status` are legal (finalize, send, pay, mark_uncollectible, void) and what Stripe answers
3
+ // otherwise; these handlers compute each move, keep a draft's lines and totals in step with its
4
+ // items, and mint the PaymentIntent a finalized invoice collects through. The invoice list and the
5
+ // item list are the derived core's.
6
+ import type { Row } from './common.ts';
7
+
8
+ export const INV = 'invoice';
9
+ export const linesOf = (inv: Row): Row[] => (inv.lines as { data?: Row[] } | undefined)?.data ?? [];
10
+ export const sumLines = (lines: Row[]): number => lines.reduce((s, l) => s + (Number(l.amount) || 0), 0);
11
+
12
+ /** A draft's line no invoice item made (a subscription's) stays as it is when an item changes. */
13
+ export function unlinkedLine(line: Row): Row {
14
+ return line;
15
+ }
16
+
17
+ /** A preview's proration for a change at proration_date. Where the documentation stops and the twin decides: half the
18
+ * period's charge credited as unused time and half charged as remaining time. */
19
+ export function prorationLines(out: Row[], subtotal: number, currency: string, now: number, period: number): void {
20
+ const half = Math.round(subtotal / 2);
21
+ out.unshift({ id: 'il_twin_proration_unused', object: 'line_item', type: 'invoiceitem', amount: -half, currency, proration: true, period: { start: now, end: period }, description: 'Unused time (proration credit)' });
22
+ out.push({ id: 'il_twin_proration_remaining', object: 'line_item', type: 'invoiceitem', amount: half, currency, proration: true, period: { start: now, end: period }, description: 'Remaining time (proration charge)' });
23
+ }
24
+
25
+ // ── invoices ──
26
+
27
+ /** A draft invoice's fields before anything is on it: what a new invoice and a preview start from. */
28
+ export const draft = (now: number): Row => ({
29
+ status: 'draft', livemode: false, currency: 'usd', collection_method: 'charge_automatically',
30
+ auto_advance: false, attempt_count: 0, attempted: false,
31
+ amount_due: 0, amount_paid: 0, amount_remaining: 0, amount_overpaid: 0, amount_paid_off_stripe: 0, amount_shipping: 0,
32
+ subtotal: 0, total: 0, starting_balance: 0, post_payment_credit_notes_amount: 0, pre_payment_credit_notes_amount: 0,
33
+ period_start: now, period_end: now, default_tax_rates: [], discounts: [],
34
+ lines: { object: 'list', data: [], has_more: false, total_count: 0 },
35
+ automatic_tax: { enabled: false, liability: null, status: null },
36
+ status_transitions: { finalized_at: null, marked_uncollectible_at: null, paid_at: null, voided_at: null },
37
+ issuer: { type: 'self' },
38
+ payment_settings: { default_mandate: null, payment_method_options: null, payment_method_types: null },
39
+ // a draft has no PaymentIntent: finalize mints it
40
+ payment_intent: null,
41
+ });
42
+
43
+ /** Whether leaving draft mints a PaymentIntent: only a charge_automatically invoice with a balance. */
44
+ // "Finalizing an invoice does the following: ... It creates an incomplete payment intent for the invoice"
45
+ // (docs.stripe.com/invoicing/integration/workflow-transitions), whichever its collection method
46
+ export const collectsThroughIntent = (inv: Row): boolean => inv.status === 'draft' && (Number(inv.amount_due) || 0) > 0;
47
+
48
+ export const transitions = (inv: Row): object => (inv.status_transitions as object) ?? {};
49
+
50
+ /** What finalizing assigns: the invoice's `number`, the customer's invoice_prefix and a sequence
51
+ * (https://docs.stripe.com/api/invoices/object#invoice_object-number), and for send_invoice a
52
+ * `due_date` days_until_due after finalization (#invoice_object-due_date). */
53
+ /** A customer's invoice_prefix, "The prefix for the customer used to generate unique invoice numbers"
54
+ * (docs.stripe.com/api/customers/object): the twin's, from the customer's id. */
55
+ export const invoicePrefix = (customerId: string): string => customerId.replace(/[^a-z0-9]/gi, '').slice(-8).toUpperCase() || 'TWIN';
56
+
57
+ /** An invoice's payment as Stripe answers it (docs.stripe.com/api/invoice-payment/object): the PaymentIntent that
58
+ * collects the invoice, open until the invoice is paid. Where the documentation stops and the twin decides: an
59
+ * invoice has one payment, its default, and the payment's id is the invoice's with `inpay_`. */
60
+ export function invoicePayment(inv: Row): Row | undefined {
61
+ if (typeof inv.payment_intent !== 'string') return undefined;
62
+ const paid = inv.status === 'paid';
63
+ const transitions = (inv.status_transitions as Row | undefined) ?? {};
64
+ return {
65
+ id: `inpay_${String(inv.id).replace(/^in_/, '')}`, object: 'invoice_payment', invoice: inv.id, is_default: true, livemode: false,
66
+ amount_requested: Number(inv.amount_due ?? 0), amount_paid: paid ? Number(inv.amount_paid ?? inv.amount_due ?? 0) : null, currency: inv.currency,
67
+ created: inv.created, payment: { type: 'payment_intent', payment_intent: inv.payment_intent },
68
+ status: paid ? 'paid' : inv.status === 'void' ? 'canceled' : 'open',
69
+ status_transitions: { paid_at: paid ? (transitions.paid_at ?? null) : null, canceled_at: inv.status === 'void' ? (transitions.voided_at ?? null) : null },
70
+ };
71
+ }
@@ -0,0 +1,61 @@
1
+ // Issuing semantics: cardholders, cards, authorizations, transactions, disputes, network tokens and
2
+ // personalization designs. An authorization's `card` is the full Card in every answer and webhook
3
+ // (the manifest's write hook embeds it on writes; reads embed it here). The machines in
4
+ // ../manifest.ts say how authorizations, disputes, cards, cardholders, tokens and designs move.
5
+ //
6
+ // The test-helper routes here (/v1/test_helpers/issuing/…) are Stripe's own doors for what no API
7
+ // verb makes: a card presented at a merchant, a capture, a force capture, a design's review. A
8
+ // presented authorization is decided in Stripe's order: card status, then spending controls
9
+ // (card, then cardholder), then the real-time issuing_authorization.request webhook delivered
10
+ // synchronously to the first enrolled endpoint; with none it is approved (card_active).
11
+ import type { Row } from './common.ts';
12
+
13
+ export const CH = 'issuing.cardholder';
14
+ /** The id of a card's cardholder: the card answers the cardholder in full (the served spec's issuing.card.cardholder is
15
+ * the Cardholder object, not an id); its id is read from it for filtering and for the objects that name it by id. */
16
+ export const holderId = (c: Row): string => (typeof c.cardholder === 'string' ? c.cardholder : String((c.cardholder as Row | undefined)?.id ?? ''));
17
+ export const CARD = 'issuing.card';
18
+ export const AUTH = 'issuing.authorization';
19
+ export const TXN = 'issuing.transaction';
20
+ export const DSP = 'issuing.dispute';
21
+ export const TOK = 'issuing.token';
22
+ export const PD = 'issuing.personalization_design';
23
+
24
+ /** One request_history entry; the authorization code is derived from the request time (Stripe's is not unique either). */
25
+ export function historyEntry(o: { amount: number; currency: string; approved: boolean; reason: string; reasonMessage: string | null; createdSec: number; merchantAmount: number; merchantCurrency: string }): Row {
26
+ return {
27
+ amount: o.amount, amount_details: null, approved: o.approved,
28
+ authorization_code: o.approved ? `S${String(100000 + (o.createdSec % 900000))}` : null,
29
+ created: o.createdSec, currency: o.currency,
30
+ merchant_amount: o.merchantAmount, merchant_currency: o.merchantCurrency,
31
+ network_risk_score: null, reason: o.reason, reason_message: o.reasonMessage,
32
+ requested_at: o.createdSec,
33
+ };
34
+ }
35
+
36
+ /** The test helper's default merchant, under any merchant_data the caller gives. */
37
+ export function merchantData(param: unknown): Row {
38
+ const base: Row = {
39
+ category: 'general', category_code: '5399', city: 'San Francisco', country: 'US',
40
+ name: 'Twin Test Merchant', network_id: '1234567890', postal_code: '94103', state: 'CA',
41
+ tax_id: null, terminal_id: null, url: null,
42
+ };
43
+ if (param && typeof param === 'object' && !Array.isArray(param)) Object.assign(base, param);
44
+ return base;
45
+ }
46
+
47
+ /** The card's stored id (an embedded card answers with its id). */
48
+ export const cardId = (auth: Row): unknown => (auth.card && typeof auth.card === 'object' ? (auth.card as Row).id : auth.card);
49
+
50
+ /** The real-time window: "If Stripe doesn't receive your approve or decline response within 2 seconds, the
51
+ * Authorization is automatically approved or declined based on your timeout settings"
52
+ * (docs.stripe.com/issuing/controls/real-time-authorizations). */
53
+ export const REALTIME_WINDOW_SECONDS = 2;
54
+
55
+ /** Stripe's physical bundles are its catalog, not the account's: the twin serves the one its reference publishes
56
+ * (docs.stripe.com/api/issuing/physical_bundles: "US Visa Credit White", standard, active, a card logo required and
57
+ * carrier text optional). Where the documentation stops and the twin decides: the catalog is that one bundle, and its
58
+ * second_line (required by the served spec, absent from the example) is optional. */
59
+ export const PHYSICAL_BUNDLES: Row[] = [
60
+ { id: 'ics_NLuXJPDYSTjFON', object: 'issuing.physical_bundle', livemode: false, name: 'US Visa Credit White', features: { card_logo: 'required', carrier_text: 'optional', second_line: 'optional' }, status: 'active', type: 'standard' },
61
+ ];
@@ -0,0 +1,50 @@
1
+ // Stripe's balance ledger (docs.stripe.com/api/balance_transactions): every movement of the account's money writes
2
+ // a balance transaction, and the balance is their sum. A captured charge adds its amount less Stripe's fee, pending
3
+ // until its available_on; a refund takes its amount back at once; a payout takes its amount out of what is available
4
+ // and is refused beyond it (balance_insufficient). A transaction's status is what the World clock says of its
5
+ // available_on (the machine's time move, pending → available), so a `wait` in a story settles funds as time does.
6
+ //
7
+ // Where the documentation stops and the twin decides: the fee is Stripe's standard US card pricing, 2.9% + 30¢
8
+ // (stripe.com/pricing), for every charge; funds become available two days after capture (Stripe's standard US
9
+ // payout schedule counts business days).
10
+ //
11
+ // Test mode (the twin serves livemode: false), as docs.stripe.com/testing documents it:
12
+ // - cards keep that delay but two: "Other test cards send funds from a successful payment to your pending balance",
13
+ // while 4000000000000077 and 4000003720000278 (and their test names pm_card_bypassPending,
14
+ // pm_card_bypassPendingInternational, tok_bypassPending, tok_bypassPendingInternational) "succeed. Funds are added
15
+ // directly to your available balance, bypassing your pending balance" (#available-balance; test-cards.ts). A
16
+ // PaymentMethod made from one keeps that (payment-methods.ts, after-payment.ts), so a saved card charged later by
17
+ // id bypasses too;
18
+ // - a US bank account debit: "Test transactions settle instantly and are added to your available test balance. This
19
+ // behavior differs from live mode" (ACH Direct Debit, "Test settlement behavior");
20
+ // - a source_transaction transfer "takes on the pending status of the associated charge"
21
+ // (docs.stripe.com/connect/separate-charges-and-transfers), so it is available at once when its charge is;
22
+ // - "Test payouts simulate a live payout but aren't processed with the bank" (docs.stripe.com/payouts#test-payouts):
23
+ // the payout clock (semantics/balance.ts) is live's.
24
+ // No other test-mode speed-up is documented, so 4242 4242 4242 4242 funds sit pending the two days.
25
+ //
26
+ // Where the documentation stops and the twin decides: every credit written available at once (a bypass or bank-debit
27
+ // charge, a transfer, a transfer from such a charge, an application fee, a top-up, an Issuing top-up included, a reversal) is marked not yet
28
+ // sent, and the drain sends its account balance.available for it ("Occurs whenever your Stripe balance has been
29
+ // updated (e.g., when a charge is available to be paid out). ... This event is not fired for negative
30
+ // transactions", docs.stripe.com/api/events/types), as it does for funds that came due after the delay. The Balance
31
+ // it carries is the account's at the drain: a debit or an automatic payout landing first shows in it.
32
+ //
33
+ // Each connected account keeps its own balance (docs.stripe.com/connect/account-balances): a transaction belongs to
34
+ // the account the request acts for (the Stripe-Account header), else to the platform. A transfer takes its amount out
35
+ // of the platform's available balance and adds it to the destination's; a destination charge transfers its amount
36
+ // less the application fee, available when the charge's funds are; a direct charge's application fee moves from the
37
+ // connected account to the platform.
38
+ import type { Row } from './common.ts';
39
+ import { BYPASS_PENDING_CARDS } from './test-cards.ts';
40
+
41
+ export const BT = 'balance_transaction';
42
+ export const DAY = 86_400;
43
+ /** A ledger entry's mark: available at once, its balance.available not yet sent (settleDueEntries). */
44
+ export const UNSENT = '_availableUnsent';
45
+ export const BYPASS_NUMBERS = new Set(Object.values(BYPASS_PENDING_CARDS).map((c) => c.number));
46
+
47
+ export const feeOf = (amount: number): number => (amount > 0 ? Math.round(amount * 0.029) + 30 : 0);
48
+
49
+ /** Whether a stored ledger entry is on this account's balance (undefined: the platform's). */
50
+ export const onAccount = (t: Row, account: string | undefined): boolean => (typeof t._account === 'string' ? t._account : undefined) === account;
@@ -0,0 +1,19 @@
1
+ // A connected account's OAuth connection to the platform (../screens/connect-oauth.tsx makes it), as the API reads it:
2
+ // whether it was revoked, which account an OAuth key acts as, and a key shown as Stripe's errors show one.
3
+
4
+ /** A key shown the way Stripe's errors show one: its prefix and its last four. */
5
+ export const redactKey = (key: string): string => {
6
+ const prefix = /^(sk|rk|pk)_(test|live)_/.exec(key)?.[0] ?? '';
7
+ const rest = key.slice(prefix.length);
8
+ return rest.length > 4 ? `${prefix}${'*'.repeat(rest.length - 4)}${rest.slice(-4)}` : `${prefix}${'*'.repeat(rest.length)}`;
9
+ };
10
+
11
+ /** The API key a request carries: Bearer, or Basic's user (`curl -u sk_…:`, docs.stripe.com/api/authentication). */
12
+ export function requestKey(request: Request): string {
13
+ const header = request.headers.get('authorization') ?? '';
14
+ const bearer = /^bearer\s+(\S+)/i.exec(header)?.[1];
15
+ if (bearer) return bearer;
16
+ const basic = /^basic\s+(\S+)/i.exec(header)?.[1];
17
+ if (basic) { try { return atob(basic).split(':')[0] ?? ''; } catch { return ''; } }
18
+ return '';
19
+ }