@volter/twin-stripe 0.1.0 → 0.1.2

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.
@@ -80,6 +80,31 @@
80
80
  "path": "_credit_note.single-amount-type",
81
81
  "kind": "field-simplified",
82
82
  "reason": "CreditNotes are modeled in the amount form (the credited cents) referencing a finalized invoice (POST /v1/credit_notes requires invoice (must exist) plus a positive amount); preview (GET /v1/credit_notes/preview), retrieve, /lines, void (terminal: status void) and list all round-trip. Stripe additionally supports per-invoice-line credits and a mixed type; the twin emits a single custom_line_item and picks pre_payment (unpaid invoice) or post_payment (paid invoice) for the vendor type. All 22 vendor-required credit_note fields are emitted. The vendor type field collides with the kernel discriminator and is stashed under the reserved _stripe_type key (restored by view()), like payout/account. Leading underscore marks this as a twin-internal note (not a vendor schema path)."
83
+ },
84
+ {
85
+ "path": "current_period_start",
86
+ "kind": "extra",
87
+ "reason": "Real Stripe moved current_period_start off the top-level Subscription object onto subscription ITEMS in the 2025-03-31.basil API version. The vendored stripe-schemas.json fixture is fetched from stripe/openapi@master (always the LATEST published shape), so its subscription schema reflects the post-migration object and has no current_period_start property — hence this shows as a fabricated 'extra' field under the harness's single-snapshot schema. But this twin's own DEFAULT served version when a caller sends no Stripe-Version header is TWIN_API_VERSION ('2024-06-20', see its definition in stripe-twin.ts), which pre-dates that migration; on that version real Stripe DOES emit current_period_start top-level, so emitting it here is faithful to what this twin actually serves by default. Prior to this fix the twin never set this field at all (a real fidelity gap: real Stripe on ANY version always populates a billing period on a subscription). It is now computed (== the create-time billing_cycle_anchor, or trial_start during a trial — see the POST /v1/subscriptions handler and POST /v1/checkout/sessions/:id completion handler). A future improvement would branch by req.apiVersion and additionally/only emit it at the item level for callers explicitly on 2025-03-31.basil+, but the twin does not currently branch response SHAPE by apiVersion anywhere (only the recorded api_version metadata on events does), so that is left as a known follow-up rather than implemented speculatively here."
88
+ },
89
+ {
90
+ "path": "current_period_end",
91
+ "kind": "extra",
92
+ "reason": "Same deviation and reasoning as current_period_start immediately above — also computed by the same two create paths as current_period_start + one billing interval (day/week/month/year × interval_count) taken from the subscription's first item's Price.recurring, defaulting to month/1 when no recurring price is resolvable (e.g. an inline price_data item, or — real Stripe would itself reject this — no item at all)."
93
+ },
94
+ {
95
+ "path": "payment_intent",
96
+ "kind": "extra",
97
+ "reason": "Real Stripe removed the top-level payment_intent field from Invoice (replaced by the `payments` list + `confirmation_secret`) as part of the multiple-payment-attempts migration on newer API versions. The vendored stripe-schemas.json fixture is fetched from stripe/openapi@master (always the LATEST published shape), so its invoice schema reflects the post-migration object and has no payment_intent property — hence this shows as a fabricated 'extra' field under the harness's single-snapshot schema, same mechanism as current_period_start/_end above. But this twin's own DEFAULT served version when a caller sends no Stripe-Version header is TWIN_API_VERSION ('2024-06-20', see its definition in stripe-twin.ts), which pre-dates that migration; on that version real Stripe DOES emit invoice.payment_intent top-level, so emitting it here is faithful to what this twin actually serves by default. Prior to this fix the field existed in the EXPANDABLE map (expand[]=payment_intent was already wired) but the invoice action handler (POST /v1/invoices/:id/{finalize,pay,send}) never created a PaymentIntent or set it — every expand came back with nothing (PEAK-3102). It is now minted the moment a charge_automatically invoice with a positive balance is finalized (or auto-finalized via send), null for send_invoice / $0 invoices, and set to null explicitly at draft creation so the field round-trips before finalize too."
98
+ },
99
+ {
100
+ "path": "invoice",
101
+ "kind": "extra",
102
+ "reason": "Same pre-2025 API-version story as the payment_intent deviation immediately above, on the OTHER two objects of that same reverse link: real Stripe also removed the top-level invoice field from BOTH PaymentIntent and Charge in the same multiple-payment-attempts migration (a payment's invoice is reached via Invoice.payments now, not a back-reference on the payment side), so stripe-schemas.json (LATEST published shape) has no invoice property on payment_intent or charge — 'extra' under the harness's single-snapshot schema. On this twin's default-served TWIN_API_VERSION ('2024-06-20', pre-migration) real Stripe DOES emit both. The twin's own EXPANDABLE map already declared payment_intent.invoice and charge.invoice as expandable before this fix (used by the subscription default_incomplete first-invoice PaymentIntent); this fix (PEAK-3102) is the first path that also sets charge.invoice, when POST /v1/invoices/:id/pay settles the invoice's PaymentIntent and mints a Charge referencing it."
103
+ },
104
+ {
105
+ "path": "price",
106
+ "kind": "extra",
107
+ "reason": "PEAK-3102 round 2: POST /v1/invoiceitems now stores the caller-supplied `price` id on the invoiceitem (needed to resolve amount = unit_amount * quantity for PeakHealth's catalog-product order path). Real Stripe replaced the top-level InvoiceItem.price field with a `pricing.price_details` object in a later API-version migration — stripe-schemas.json (LATEST published shape) reflects the post-migration object and has no price property, hence 'extra' under the harness's single-snapshot schema, same mechanism as current_period_start/_end and payment_intent above. This twin's default-served TWIN_API_VERSION ('2024-06-20') pre-dates that migration, where real Stripe DOES emit invoiceitem.price top-level, so emitting it here is faithful to what this twin actually serves by default."
83
108
  }
84
109
  ]
85
110
  }