@volter/twin-stripe 3.0.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/README.md +51 -21
  2. package/dist/generated/pack-facts.json +3 -3
  3. package/dist/journeys/coverage.json +596 -0
  4. package/dist/journeys/customer-life.json +6108 -0
  5. package/dist/journeys/customer-life.outline.md +371 -0
  6. package/dist/journeys/decisions.json +677 -0
  7. package/dist/journeys/demand.json +706 -0
  8. package/dist/journeys/score.json +853 -0
  9. package/dist/journeys/unreachable.json +102 -0
  10. package/dist/journeys/vendor-examples.json +8010 -0
  11. package/dist/spec/SOURCE.md +5 -1
  12. package/dist/spec/doc-examples.json +445 -0
  13. package/dist/spec/sources.json +135 -207
  14. package/dist/src/cli.d.ts +0 -1
  15. package/dist/src/cli.js +0 -2
  16. package/dist/src/engine/after-payment.d.ts +0 -1
  17. package/dist/src/engine/after-payment.js +0 -1
  18. package/dist/src/engine/common.d.ts +5 -5
  19. package/dist/src/engine/common.js +13 -11
  20. package/dist/src/engine/connect.d.ts +0 -21
  21. package/dist/src/engine/connect.js +1 -82
  22. package/dist/src/engine/customers.d.ts +0 -8
  23. package/dist/src/engine/customers.js +0 -22
  24. package/dist/src/engine/display.d.ts +0 -3
  25. package/dist/src/engine/display.js +0 -3
  26. package/dist/src/engine/files.d.ts +0 -7
  27. package/dist/src/engine/files.js +0 -10
  28. package/dist/src/engine/invoices.d.ts +6 -9
  29. package/dist/src/engine/invoices.js +56 -29
  30. package/dist/src/engine/issuing.d.ts +6 -8
  31. package/dist/src/engine/issuing.js +19 -10
  32. package/dist/src/engine/ledger.d.ts +0 -1
  33. package/dist/src/engine/ledger.js +0 -1
  34. package/dist/src/engine/oauth.js +1 -2
  35. package/dist/src/engine/refunds.js +2 -27
  36. package/dist/src/engine/stripe.d.ts +2 -7
  37. package/dist/src/engine/stripe.js +34 -83
  38. package/dist/src/engine/subscriptions.d.ts +0 -1
  39. package/dist/src/engine/subscriptions.js +0 -1
  40. package/dist/src/engine/version.d.ts +0 -2
  41. package/dist/src/engine/version.js +17 -6
  42. package/dist/src/fetch.js +2 -2
  43. package/dist/src/generated/surface.gen.json +1 -1
  44. package/dist/src/generated/ui.gen.json +1 -1
  45. package/dist/src/index.js +5 -3
  46. package/dist/src/manifest.js +348 -220
  47. package/dist/src/screens/billing-portal.js +5 -5
  48. package/dist/src/screens/{connect-oauth.d.ts → checkout-js.d.ts} +0 -1
  49. package/dist/src/screens/checkout-js.js +84 -0
  50. package/dist/src/screens/connect-onboarding.js +3 -3
  51. package/dist/src/screens/dashboard.d.ts +1 -1
  52. package/dist/src/screens/dashboard.js +52 -53
  53. package/dist/src/screens/stripe-js.js +53 -93
  54. package/dist/src/semantics/account.d.ts +2 -0
  55. package/dist/src/semantics/account.js +8 -0
  56. package/dist/src/semantics/accounts.js +3 -1
  57. package/dist/src/semantics/around.js +3 -6
  58. package/dist/src/semantics/billing_portal.d.ts +0 -1
  59. package/dist/src/semantics/billing_portal.js +1 -7
  60. package/dist/src/semantics/checkout.d.ts +1 -1
  61. package/dist/src/semantics/checkout.js +18 -15
  62. package/dist/src/semantics/clock.js +1 -7
  63. package/dist/src/semantics/customers.d.ts +1 -2
  64. package/dist/src/semantics/customers.js +32 -38
  65. package/dist/src/semantics/entitlements.d.ts +0 -2
  66. package/dist/src/semantics/entitlements.js +4 -50
  67. package/dist/src/semantics/events.d.ts +2 -3
  68. package/dist/src/semantics/events.js +6 -11
  69. package/dist/src/semantics/index.js +16 -38
  70. package/dist/src/semantics/invoices.d.ts +3 -8
  71. package/dist/src/semantics/invoices.js +134 -127
  72. package/dist/src/semantics/issuing.d.ts +6 -0
  73. package/dist/src/semantics/issuing.js +77 -0
  74. package/dist/src/semantics/payment_intents.d.ts +0 -1
  75. package/dist/src/semantics/payment_intents.js +5 -13
  76. package/dist/src/semantics/payment_methods.d.ts +0 -2
  77. package/dist/src/semantics/payment_methods.js +2 -26
  78. package/dist/src/semantics/payouts.d.ts +1 -0
  79. package/dist/src/semantics/payouts.js +8 -1
  80. package/dist/src/semantics/products.d.ts +1 -3
  81. package/dist/src/semantics/products.js +3 -14
  82. package/dist/src/semantics/refunds.d.ts +1 -2
  83. package/dist/src/semantics/refunds.js +1 -5
  84. package/dist/src/semantics/shared.d.ts +64 -336
  85. package/dist/src/semantics/shared.js +326 -1336
  86. package/dist/src/semantics/states.d.ts +20 -89
  87. package/dist/src/semantics/states.js +116 -334
  88. package/dist/src/semantics/subscriptions.d.ts +1 -2
  89. package/dist/src/semantics/subscriptions.js +23 -145
  90. package/dist/src/semantics/test_helpers.d.ts +2 -5
  91. package/dist/src/semantics/test_helpers.js +121 -43
  92. package/dist/src/semantics/webhook_endpoints.d.ts +2 -0
  93. package/dist/src/semantics/webhook_endpoints.js +26 -0
  94. package/generated/pack-facts.json +3 -3
  95. package/journeys/coverage.json +596 -0
  96. package/journeys/customer-life.json +6108 -0
  97. package/journeys/customer-life.outline.md +371 -0
  98. package/journeys/decisions.json +677 -0
  99. package/journeys/demand.json +706 -0
  100. package/journeys/score.json +853 -0
  101. package/journeys/unreachable.json +102 -0
  102. package/journeys/vendor-examples.json +8010 -0
  103. package/package.json +4 -3
  104. package/spec/SOURCE.md +5 -1
  105. package/spec/doc-examples.json +445 -0
  106. package/spec/sources.json +135 -207
  107. package/src/cli.ts +0 -3
  108. package/src/engine/after-payment.ts +0 -2
  109. package/src/engine/balance.ts +0 -1
  110. package/src/engine/checkout.ts +0 -1
  111. package/src/engine/common.ts +19 -17
  112. package/src/engine/connect.ts +1 -79
  113. package/src/engine/customers.ts +0 -25
  114. package/src/engine/display.ts +2 -3
  115. package/src/engine/files.ts +0 -13
  116. package/src/engine/invoices.ts +64 -33
  117. package/src/engine/issuing.ts +16 -11
  118. package/src/engine/ledger.ts +0 -2
  119. package/src/engine/oauth.ts +1 -2
  120. package/src/engine/onboarding.ts +0 -1
  121. package/src/engine/params.ts +0 -1
  122. package/src/engine/payment-intents.ts +0 -1
  123. package/src/engine/payment-methods.ts +0 -1
  124. package/src/engine/refunds.ts +2 -28
  125. package/src/engine/renewals.ts +0 -1
  126. package/src/engine/stripe.ts +35 -83
  127. package/src/engine/subscriptions.ts +0 -3
  128. package/src/engine/transfers.ts +0 -1
  129. package/src/engine/version.ts +15 -7
  130. package/src/engine/webhooks.ts +0 -2
  131. package/src/fetch.ts +2 -2
  132. package/src/generated/surface.gen.json +1 -1
  133. package/src/generated/ui.gen.json +1 -1
  134. package/src/index.ts +6 -4
  135. package/src/manifest.ts +348 -220
  136. package/src/screens/billing-portal.tsx +5 -7
  137. package/src/screens/checkout-js.ts +80 -0
  138. package/src/screens/checkout.tsx +0 -2
  139. package/src/screens/connect-onboarding.tsx +3 -5
  140. package/src/screens/dashboard.tsx +53 -73
  141. package/src/screens/stripe-js.ts +57 -125
  142. package/src/semantics/account.ts +10 -0
  143. package/src/semantics/account_links.ts +0 -1
  144. package/src/semantics/accounts.ts +8 -7
  145. package/src/semantics/apps.ts +1 -2
  146. package/src/semantics/around.ts +3 -6
  147. package/src/semantics/balance.ts +0 -1
  148. package/src/semantics/balance_transactions.ts +1 -3
  149. package/src/semantics/billing_portal.ts +1 -7
  150. package/src/semantics/charges.ts +1 -6
  151. package/src/semantics/checkout.ts +16 -12
  152. package/src/semantics/clock.ts +1 -8
  153. package/src/semantics/coupons.ts +0 -1
  154. package/src/semantics/customers.ts +32 -35
  155. package/src/semantics/doors.ts +2 -3
  156. package/src/semantics/entitlements.ts +1 -45
  157. package/src/semantics/events.ts +7 -14
  158. package/src/semantics/index.ts +16 -38
  159. package/src/semantics/invoice_payments.ts +1 -3
  160. package/src/semantics/invoices.ts +124 -119
  161. package/src/semantics/issuing.ts +74 -0
  162. package/src/semantics/payment_intents.ts +10 -17
  163. package/src/semantics/payment_methods.ts +2 -25
  164. package/src/semantics/payouts.ts +9 -3
  165. package/src/semantics/prices.ts +0 -1
  166. package/src/semantics/products.ts +4 -14
  167. package/src/semantics/promotion_codes.ts +0 -1
  168. package/src/semantics/radar.ts +1 -3
  169. package/src/semantics/refunds.ts +2 -11
  170. package/src/semantics/shared.ts +350 -1382
  171. package/src/semantics/states.ts +109 -330
  172. package/src/semantics/subscriptions.ts +25 -145
  173. package/src/semantics/test_helpers.ts +109 -43
  174. package/src/semantics/transfers.ts +1 -3
  175. package/src/semantics/webhook_endpoints.ts +27 -0
  176. package/src/server.ts +0 -1
  177. package/dist/src/engine/billing.d.ts +0 -5
  178. package/dist/src/engine/billing.js +0 -6
  179. package/dist/src/engine/charges.d.ts +0 -6
  180. package/dist/src/engine/charges.js +0 -13
  181. package/dist/src/engine/connect-settings.d.ts +0 -16
  182. package/dist/src/engine/connect-settings.js +0 -26
  183. package/dist/src/engine/coupons.d.ts +0 -0
  184. package/dist/src/engine/coupons.js +0 -5
  185. package/dist/src/engine/credit-notes.d.ts +0 -1
  186. package/dist/src/engine/credit-notes.js +0 -5
  187. package/dist/src/engine/disputes.d.ts +0 -0
  188. package/dist/src/engine/disputes.js +0 -9
  189. package/dist/src/engine/entitlements.d.ts +0 -1
  190. package/dist/src/engine/entitlements.js +0 -4
  191. package/dist/src/engine/ephemeral-keys.d.ts +0 -0
  192. package/dist/src/engine/ephemeral-keys.js +0 -4
  193. package/dist/src/engine/front.d.ts +0 -5
  194. package/dist/src/engine/front.js +0 -25
  195. package/dist/src/engine/payment-links.d.ts +0 -1
  196. package/dist/src/engine/payment-links.js +0 -5
  197. package/dist/src/engine/plans.d.ts +0 -6
  198. package/dist/src/engine/plans.js +0 -26
  199. package/dist/src/engine/platform.d.ts +0 -39
  200. package/dist/src/engine/platform.js +0 -34
  201. package/dist/src/engine/products.d.ts +0 -0
  202. package/dist/src/engine/products.js +0 -4
  203. package/dist/src/engine/setup-intents.d.ts +0 -1
  204. package/dist/src/engine/setup-intents.js +0 -4
  205. package/dist/src/engine/subscription-schedules.d.ts +0 -3
  206. package/dist/src/engine/subscription-schedules.js +0 -1
  207. package/dist/src/engine/tax.d.ts +0 -7
  208. package/dist/src/engine/tax.js +0 -28
  209. package/dist/src/engine/terminal.d.ts +0 -4
  210. package/dist/src/engine/terminal.js +0 -20
  211. package/dist/src/engine/test-clocks.d.ts +0 -5
  212. package/dist/src/engine/test-clocks.js +0 -9
  213. package/dist/src/engine/tokens.d.ts +0 -7
  214. package/dist/src/engine/tokens.js +0 -20
  215. package/dist/src/engine/treasury.d.ts +0 -23
  216. package/dist/src/engine/treasury.js +0 -45
  217. package/dist/src/screens/connect-oauth.js +0 -333
  218. package/dist/src/semantics/disputes.d.ts +0 -2
  219. package/dist/src/semantics/disputes.js +0 -5
  220. package/dist/src/semantics/invoiceitems.d.ts +0 -3
  221. package/dist/src/semantics/invoiceitems.js +0 -59
  222. package/dist/src/semantics/setup_intents.d.ts +0 -3
  223. package/dist/src/semantics/setup_intents.js +0 -41
  224. package/dist/src/semantics/subscription_items.d.ts +0 -5
  225. package/dist/src/semantics/subscription_items.js +0 -55
  226. package/dist/src/semantics/subscription_schedules.d.ts +0 -4
  227. package/dist/src/semantics/subscription_schedules.js +0 -60
  228. package/src/engine/billing.ts +0 -16
  229. package/src/engine/charges.ts +0 -19
  230. package/src/engine/connect-settings.ts +0 -23
  231. package/src/engine/coupons.ts +0 -5
  232. package/src/engine/credit-notes.ts +0 -6
  233. package/src/engine/disputes.ts +0 -9
  234. package/src/engine/entitlements.ts +0 -5
  235. package/src/engine/ephemeral-keys.ts +0 -3
  236. package/src/engine/front.ts +0 -31
  237. package/src/engine/payment-links.ts +0 -6
  238. package/src/engine/plans.ts +0 -42
  239. package/src/engine/platform.ts +0 -47
  240. package/src/engine/products.ts +0 -3
  241. package/src/engine/setup-intents.ts +0 -5
  242. package/src/engine/subscription-schedules.ts +0 -10
  243. package/src/engine/tax.ts +0 -39
  244. package/src/engine/terminal.ts +0 -23
  245. package/src/engine/test-clocks.ts +0 -11
  246. package/src/engine/tokens.ts +0 -22
  247. package/src/engine/treasury.ts +0 -47
  248. package/src/screens/connect-oauth.tsx +0 -376
  249. package/src/semantics/disputes.ts +0 -12
  250. package/src/semantics/invoiceitems.ts +0 -59
  251. package/src/semantics/setup_intents.ts +0 -45
  252. package/src/semantics/subscription_items.ts +0 -54
  253. package/src/semantics/subscription_schedules.ts +0 -66
@@ -1,23 +0,0 @@
1
- // The platform's Connect OAuth settings (its client_id, whether OAuth is on, its redirect URIs), which the Dashboard's
2
- // settings page saves (../screens/dashboard.tsx) and connect.stripe.com/oauth/authorize reads (../screens/connect-oauth.tsx).
3
-
4
- /** The platform's test client_id: the World's one platform (acct_twin_self) is the application it names. */
5
- export const PLATFORM_CLIENT_ID = 'ca_twin_self';
6
- export const SETTINGS_URL = 'https://dashboard.stripe.com/settings/connect/onboarding-options/oauth';
7
- /** The page's addresses: the docs' own, its test-mode link, and Connect's settings root. */
8
- export const CONNECT_SETTINGS_PATH = /^\/(test\/)?settings\/connect(\/onboarding-options\/oauth)?\/?$/;
9
- export const SETTINGS = '_connect_oauth_settings';
10
-
11
- export type ConnectOAuthSettings = { oauth_enabled: boolean; redirect_uris: string[] };
12
-
13
- /** The redirect URIs a form's field names, or the first one refused and why. */
14
- export function redirectUris(field: string): { uris: string[] } | { refused: string } {
15
- const uris = [...new Set(field.split(/[\n,]/).map((s) => s.trim()).filter(Boolean))];
16
- for (const uri of uris) {
17
- let url: URL;
18
- try { url = new URL(uri); } catch { return { refused: `${uri} is not a valid URL.` }; }
19
- if (url.protocol !== 'https:' && url.protocol !== 'http:') return { refused: `${uri} must use http or https.` };
20
- if (uri.includes('#')) return { refused: `${uri} must not contain a fragment.` };
21
- }
22
- return { uris };
23
- }
@@ -1,5 +0,0 @@
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
-
@@ -1,6 +0,0 @@
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';
@@ -1,9 +0,0 @@
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
-
@@ -1,5 +0,0 @@
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';
@@ -1,3 +0,0 @@
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.
@@ -1,31 +0,0 @@
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
- };
@@ -1,6 +0,0 @@
1
- // Payment Link and Quote semantics. Both carry line items resolved from existing prices. A payment
2
- // link is a reusable hosted-checkout URL, active until switched off; a quote moves draft → open
3
- // (finalize) → accepted or canceled, the machine in ../manifest.ts. Link retrieve and update
4
- // (`active`, its machine), quote retrieve and the quote list are the derived core's.
5
-
6
- export const PL = 'payment_link';
@@ -1,42 +0,0 @@
1
- // Plan semantics. Stripe's Prices API "replaces the Plans API and is backwards compatible" (docs.stripe.com/api/plans/create),
2
- // and "Existing plans can be used wherever recurring prices are accepted", a plan being one "which can be used
3
- // interchangeably with a price" (docs.stripe.com/billing/migration/migrating-prices). So a plan is stored as the recurring
4
- // price it is, under the plan's id, and the Plans API answers recurring prices in the plan's shape: a plan made here is
5
- // read, listed, updated and subscribed to as a price, and a recurring price made through the Prices API is a plan.
6
- // The plan's id: "An identifier randomly generated by Stripe ... You can optionally override this ID, but the ID must be
7
- // unique across all plans in your Stripe account" (the create page's `id`). `amount_decimal` is "Same as `amount`, but
8
- // accepts a decimal value with at most 12 decimal places. Only one of `amount` and `amount_decimal` can be set", and the
9
- // plan answers it as "a decimal string", its `amount` "a whole integer if possible" (spec/openapi.json.gz, the plan
10
- // object). Plan writes send the plan events, plan.created / plan.updated / plan.deleted, each carrying the plan object
11
- // (docs.stripe.com/api/events/types; the write hook renders it, ./stripe.ts afterStripeWrite). "Deleting plans
12
- // means new subscribers can't be added. Existing subscribers aren't affected." (docs.stripe.com/api/plans/delete), and
13
- // deleting one twice is an error. Where the documentation stops and the twin decides: a minted plan id is `plan_` over
14
- // the price counter, a duplicate id is refused with resource_already_exists, the refusals are worded by the twin, and only
15
- // the per_unit scheme is modelled (a tiered plan is refused, naming the gap); a deleted plan is gone from the Plans API
16
- // while the recurring price it was stays readable through the Prices API, inactive, so the subscription items that name
17
- // it still resolve (the docs do not say what the Prices API answers for it).
18
- import type { Row } from './common.ts';
19
-
20
- export const INTERVALS = new Set(['day', 'week', 'month', 'year']);
21
-
22
- /** A recurring price in the plan object's shape (the create page's example response). */
23
- export function planOf(price: Row): Row {
24
- const r = (price.recurring ?? {}) as Row;
25
- const amount = typeof price.unit_amount === 'number' ? price.unit_amount : null;
26
- const decimal = typeof price.unit_amount_decimal === 'string' ? price.unit_amount_decimal : amount === null ? null : String(amount);
27
- return {
28
- id: price.id, object: 'plan', active: price.active ?? true, amount, amount_decimal: decimal,
29
- billing_scheme: price.billing_scheme ?? 'per_unit', created: price.created, currency: price.currency, interval: r.interval ?? null,
30
- interval_count: r.interval_count ?? 1, livemode: false, metadata: price.metadata ?? {}, meter: r.meter ?? null, nickname: price.nickname ?? null,
31
- product: price.product, tiers_mode: price.tiers_mode ?? null, transform_usage: price.transform_quantity ?? null,
32
- trial_period_days: r.trial_period_days ?? null, usage_type: r.usage_type ?? 'licensed',
33
- };
34
- }
35
-
36
- /** Metadata after an update: an empty value unsets the key, an empty `metadata` unsets them all. */
37
- export function metadataAfter(was: Row, given: unknown): Row {
38
- if (given === '' || given === null || typeof given !== 'object') return {};
39
- const next: Row = { ...was };
40
- for (const [k, v] of Object.entries(given as Row)) if (v === '' || v === null) delete next[k]; else next[k] = v;
41
- return next;
42
- }
@@ -1,47 +0,0 @@
1
- // Handler for Stripe's smaller products: Climate (a fixed product and supplier catalog, and
2
- // orders against it), Financial Connections (sessions, linked accounts, their transactions),
3
- // PAN forwarding requests, and Reporting (a report-type catalog and report runs, which the twin
4
- // completes at once). Lists and retrieves of what is stored are the derived core's.
5
- import type { Handler } from '@volter/world-core';
6
- import type { Row } from './common.ts';
7
-
8
- // ── Climate: Stripe's catalog is managed and account-independent. The twin serves the catalog Stripe's reference
9
- // publishes (docs.stripe.com/api/climate/product/object, /api/climate/supplier/object): Frontier's 2027 offtake
10
- // portfolio at $550 a ton plus Frontier's service fees of $16.50 (3%), 18,000 tons, from Charm Industrial.
11
- // Where the documentation stops and the twin decides: the catalog is that one product and supplier. ──
12
-
13
- export const CLIMATE_SUPPLIERS = [
14
- { id: 'climsup_charm_industrial', name: 'Charm Industrial', removal_pathway: 'biomass_carbon_removal_and_storage', info_url: 'https://frontierclimate.com/portfolio/charm-industrial', locations: [{ city: 'San Francisco', country: 'US', latitude: 37.7749, longitude: -122.4194, region: 'CA' }] },
15
- ] as const;
16
- export const CLIMATE_PRODUCTS = [
17
- { id: 'climsku_frontier_offtake_portfolio_2027', name: "Frontier's 2027 offtake portfolio", subtotal: 55000, fees: 1650, currency: 'usd', delivery_year: 2027, metric_tons_available: '18000', created: 1881439203, suppliers: ['climsup_charm_industrial'] },
18
- ] as const;
19
- export const supplierView = (s: (typeof CLIMATE_SUPPLIERS)[number]): Row => ({ id: s.id, object: 'climate.supplier', name: s.name, removal_pathway: s.removal_pathway, info_url: s.info_url, locations: s.locations, livemode: false });
20
- export const productView = (p: (typeof CLIMATE_PRODUCTS)[number]): Row => ({
21
- id: p.id, object: 'climate.product', name: p.name, livemode: false, delivery_year: p.delivery_year,
22
- metric_tons_available: p.metric_tons_available, created: p.created,
23
- current_prices_per_metric_ton: { [p.currency]: { amount_fees: p.fees, amount_subtotal: p.subtotal, amount_total: p.subtotal + p.fees } },
24
- suppliers: p.suppliers.map((id) => supplierView(CLIMATE_SUPPLIERS.find((s) => s.id === id)!)),
25
- });
26
-
27
- export const ORDER = 'climate.order';
28
-
29
- // ── Financial Connections: a session is created for an account holder and its permissions; accounts
30
- // are linked in the authentication flow Stripe.js opens (../screens/financial-connections.tsx) ──
31
-
32
- export const FCS = 'financial_connections.session';
33
- export const FCA = 'financial_connections.account';
34
- export const FCT = 'financial_connections.transaction';
35
-
36
- // ── Reporting: a representative subset of Stripe's report types; a run succeeds at once ──
37
-
38
- export const REPORT_TYPES: Array<{ id: string; name: string }> = [
39
- { id: 'balance.summary.1', name: 'Balance summary' },
40
- { id: 'balance_change_from_activity.summary.1', name: 'Balance change from activity (summary)' },
41
- { id: 'payouts.summary.1', name: 'Payouts (summary)' },
42
- { id: 'payout_reconciliation.by_id.itemized.4', name: 'Payout reconciliation (itemized)' },
43
- ];
44
- export const reportTypeView = (t: { id: string; name: string }): Row => ({
45
- id: t.id, object: 'reporting.report_type', name: t.name, version: 1,
46
- data_available_start: 0, data_available_end: 0, default_columns: null, updated: 0, livemode: false,
47
- });
@@ -1,3 +0,0 @@
1
- // Product and Price semantics, with the entitlement features granted to a product. Retrieve of a
2
- // product and the product and price updates (archiving and restoring by `active`, the machines in
3
- // ../manifest.ts) are the derived core's.
@@ -1,5 +0,0 @@
1
- // SetupIntent semantics. The machine in ../manifest.ts says which moves of `status` are legal and
2
- // what Stripe answers otherwise; these handlers compute what each move does. List, retrieve and
3
- // update are the derived core's.
4
-
5
- export const SI = 'setup_intent';
@@ -1,10 +0,0 @@
1
- // Subscription schedule semantics: a schedule drives a subscription through phases (items for a
2
- // duration). One made for a customer starts its subscription at once on the first phase's items. Cancel and
3
- // release end it, the machine's moves in ../manifest.ts. List and update are the derived core's.
4
- //
5
- // Where the documentation stops and the twin decides: the subscription a schedule starts raises no first invoice.
6
- import { addBillingInterval } from './stripe.ts';
7
-
8
- export const SS = 'subscription_schedule';
9
-
10
- export type Interval = Parameters<typeof addBillingInterval>[1];
package/src/engine/tax.ts DELETED
@@ -1,39 +0,0 @@
1
- // Stripe Tax semantics: tax rates, the account's tax settings (a singleton), calculations,
2
- // registrations, and the transactions that commit a calculation or reverse one. A calculation's
3
- // tax comes from one flat default rate so its amounts are stable (Stripe derives it from the
4
- // customer's jurisdiction and the account's registrations). Rate, calculation, registration and
5
- // transaction retrieves and the registration list are the derived core's.
6
- import type { Row } from './common.ts';
7
-
8
- export const TWIN_TAX_RATE_PCT = 10;
9
-
10
- // ── settings: active once a head office is set; the answer has no id ──
11
-
12
- // the defaults' provider: "The tax calculation provider this account uses. Defaults to `stripe` when not using a
13
- // third-party provider" (the served spec's tax settings defaults); the head office's address answers each line, the
14
- // lines not given null (the served spec's address: each "(string, nullable)"; the settings page's example answers
15
- // line2 null)
16
- export const ADDRESS_LINES = ['city', 'country', 'line1', 'line2', 'postal_code', 'state'];
17
- export function settingsBody(stored: Row | undefined): Row {
18
- const given = (stored?.head_office ?? null) as Row | null;
19
- const address = given && typeof given.address === 'object' && given.address ? (given.address as Row) : undefined;
20
- const headOffice = given ? { ...given, ...(address ? { address: Object.fromEntries(ADDRESS_LINES.map((k) => [k, address[k] ?? null])) } : {}) } : null;
21
- const active = !!headOffice;
22
- return {
23
- object: 'tax.settings', livemode: false,
24
- defaults: { provider: 'stripe', ...((stored?.defaults as Row) ?? { tax_behavior: null, tax_code: null }) }, head_office: headOffice,
25
- status: active ? 'active' : 'pending',
26
- status_details: active ? { active: {} } : { pending: { missing_fields: ['head_office'] } },
27
- };
28
- }
29
-
30
- // ── transactions: committing a calculation, or reversing a transaction with negated amounts ──
31
-
32
- export const TX = 'tax.transaction';
33
- export const txLine = (id: string, i: number, l: Row, sign: 1 | -1, reversal: Row | null, type: string): Row => ({
34
- object: 'tax.transaction_line_item', id: `tax_li_${id}_${i + 1}`,
35
- amount: sign === 1 ? l.amount : -(Number(l.amount) || 0), amount_tax: sign === 1 ? l.amount_tax : -(Number(l.amount_tax) || 0),
36
- reference: l.reference ?? null, tax_behavior: l.tax_behavior ?? 'exclusive', tax_code: l.tax_code ?? 'txcd_99999999',
37
- quantity: l.quantity ?? 1, reversal, type, livemode: false, metadata: {},
38
- });
39
- export const linesOf = (holder: Row): Row[] => (holder.line_items as { data?: Row[] } | undefined)?.data ?? [];
@@ -1,23 +0,0 @@
1
- // Terminal and top-up semantics: in-person locations, readers (handed a PaymentIntent to process)
2
- // and their configurations, the reader SDK's connection tokens, and top-ups that fund the balance
3
- // (a test top-up succeeds at once; only a pending one cancels, the machine in ../manifest.ts). In test mode a
4
- // simulated reader is presented a card by a test helper: the PaymentIntent the reader is processing is paid with a
5
- // card_present payment method (succeeded, or requires_capture under manual capture) and the reader's action succeeds
6
- // (docs.stripe.com/terminal/references/testing#simulated-test-cards,
7
- // docs.stripe.com/api/terminal/readers/present_payment_method). Where the documentation stops and the twin decides:
8
- // the presented card is the simulated reader's default Visa, and the reader answers at once.
9
- // Lists and retrieves are the derived core's.
10
-
11
- export const LOC = 'terminal.location';
12
- export const READER = 'terminal.reader';
13
- export const CONF = 'terminal.configuration';
14
-
15
- // ── top-ups ──
16
-
17
- // a top-up adds money to the balance it names, through the ledger, once its funds arrive: "USA (USD) ACH Debit Transfer
18
- // 5 days" (docs.stripe.com/connect/top-ups), and to the Issuing balance alike: "Top-ups debit your bank account. Your
19
- // top-ups can take up to 5 business days to become available. While they're pending, they won't be added to your
20
- // Issuing balance" (docs.stripe.com/issuing/funding/balance). It is pending until its expected_availability_date, then
21
- // settled by settleTopups. Where the documentation stops and the twin decides: every top-up takes exactly five days,
22
- // whatever its currency and balance, and succeeds.
23
- export const TOPUP_DAYS = 5;
@@ -1,11 +0,0 @@
1
- // Test clock semantics. A test clock is Stripe's own door for a transition no API verb makes: the
2
- // passage of time. Advancing it moves the subscriptions of the clock's customers as a real clock tick does:
3
- // trials that ended end, and periods that ended renew (./renewals.ts advanceBilling). List, retrieve and delete are
4
- // the derived core's.
5
-
6
- export const CLOCK = 'test_helpers.test_clock';
7
-
8
- /** How long an advance takes: "it takes a few seconds to advance to the specified time"
9
- * (docs.stripe.com/billing/testing/test-clocks/api-advanced-usage). Where the documentation stops and the twin decides:
10
- * five seconds of World time from the advance. */
11
- export const ADVANCE_SECONDS = 5;
@@ -1,22 +0,0 @@
1
- // Token semantics: the older integrations' single-use tokens for a card, a bank account or PII. A
2
- // token carries only the safe fields of its instrument, never the card or account number. Retrieve
3
- // is the derived core's.
4
- import { paymentMethodSubObject } from './stripe.ts';
5
- import type { Row } from './common.ts';
6
-
7
- /** The Card object a card token carries, as the served spec's `card` describes it: its brand as a name ("Card brand.
8
- * Can be `American Express`, ... `MasterCard`, `UnionPay`, `Visa`, or `Unknown`"), the holder's name and address as
9
- * given ("Cardholder name"), and the CVC's check when one was given ("If a CVC was provided, results of the check:
10
- * pass, fail, unavailable, or unchecked"). Where the documentation stops and the twin decides: a test card's CVC passes. */
11
- export const BRAND_NAMES: Record<string, string> = { amex: 'American Express', cartes_bancaires: 'Cartes Bancaires', diners: 'Diners Club', discover: 'Discover', eftpos_au: 'Eftpos Australia', girocard: 'Girocard', jcb: 'JCB', mastercard: 'MasterCard', unionpay: 'UnionPay', visa: 'Visa' };
12
- export function legacyCard(id: string, card: Row): Row {
13
- const pm = paymentMethodSubObject('card', { card }).card as Row;
14
- const given = (k: string): unknown => (typeof card[k] === 'string' && card[k] !== '' ? card[k] : null);
15
- return {
16
- id, object: 'card', brand: BRAND_NAMES[String(pm.brand)] ?? 'Unknown', last4: pm.last4, exp_month: pm.exp_month, exp_year: pm.exp_year,
17
- funding: pm.funding ?? 'credit', country: pm.country ?? null, fingerprint: pm.fingerprint ?? null, name: given('name'),
18
- address_line1: given('address_line1'), address_line2: given('address_line2'), address_city: given('address_city'), address_state: given('address_state'),
19
- address_zip: given('address_zip'), address_country: given('address_country'), address_line1_check: null, address_zip_check: null,
20
- cvc_check: card.cvc !== undefined && card.cvc !== '' ? 'pass' : null, dynamic_last4: null, tokenization_method: null, metadata: {}, customer: null,
21
- };
22
- }
@@ -1,47 +0,0 @@
1
- // Treasury semantics: financial accounts and the flows that move their money (outbound payments
2
- // and transfers, inbound transfers), each posting a double entry to the account's ledger (a
3
- // transaction and its entry). An outbound flow stays processing (cancelable) until the network
4
- // settles it; an inbound transfer settles at once, as in test mode. The machines in
5
- // ../manifest.ts say which flows cancel. Lists and retrieves with no required scope are the
6
- // derived core's.
7
- import type { Row } from './common.ts';
8
-
9
- export const FA = 'treasury.financial_account';
10
- export const TX = 'treasury.transaction';
11
- export const ENTRY = 'treasury.transaction_entry';
12
- export const ENTRY_TYPES = new Set(['credit_reversal', 'debit_reversal', 'inbound_transfer', 'inbound_transfer_return', 'issuing_authorization_hold', 'issuing_authorization_release', 'outbound_payment', 'outbound_transfer', 'received_credit', 'received_debit']);
13
-
14
- /** A financial account's features as the served spec's treasury.financial_account_features gives them: a toggle
15
- * (card_issuing, deposit_insurance, intra_stripe_flows) or a feature per network (financial_addresses.aba,
16
- * inbound_transfers.ach, outbound_payments.ach and .us_domestic_wire, outbound_transfers likewise), each
17
- * { requested, status, status_details }. What a request asks for is laid over what the account had. Where the
18
- * documentation stops and the twin decides: a requested feature is active at once (test mode), and one never requested
19
- * is left out (each is optional in the served spec). Answers the features and the active features' paths. */
20
- export const NETWORKS: Record<string, string[]> = { financial_addresses: ['aba'], inbound_transfers: ['ach'], outbound_payments: ['ach', 'us_domestic_wire'], outbound_transfers: ['ach', 'us_domestic_wire'] };
21
- export const TOGGLES = ['card_issuing', 'deposit_insurance', 'intra_stripe_flows'];
22
- export function featuresOf(requested: Row, had: Row = {}): { features: Row; active: string[] } {
23
- const on = (v: unknown): boolean => v === true || v === 'true';
24
- const setting = (asked: boolean) => ({ requested: asked, status: asked ? 'active' : 'restricted', status_details: [] });
25
- const features: Row = { ...had };
26
- for (const t of TOGGLES) {
27
- const r = requested[t] as Row | undefined;
28
- if (r && typeof r === 'object' && r.requested !== undefined) features[t] = setting(on(r.requested));
29
- }
30
- for (const [f, nets] of Object.entries(NETWORKS)) {
31
- const r = requested[f] as Row | undefined;
32
- if (!r || typeof r !== 'object') continue;
33
- const current = (features[f] as Row | undefined) ?? {};
34
- const next: Row = { ...current };
35
- for (const n of nets) {
36
- const nr = r[n] as Row | undefined;
37
- if (nr && typeof nr === 'object' && nr.requested !== undefined) next[n] = setting(on(nr.requested));
38
- }
39
- features[f] = next;
40
- }
41
- const active: string[] = [];
42
- for (const t of TOGGLES) if ((features[t] as Row | undefined)?.status === 'active') active.push(t);
43
- for (const [f, nets] of Object.entries(NETWORKS)) for (const n of nets) if (((features[f] as Row | undefined)?.[n] as Row | undefined)?.status === 'active') active.push(`${f}.${n}`);
44
- return { features, active };
45
- }
46
-
47
- export const noTransitions = { canceled_at: null, failed_at: null, posted_at: null, returned_at: null };