@saasicat/core 1.0.0-rc.20 → 1.0.0-rc.22

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.
package/dist/index.d.cts CHANGED
@@ -564,6 +564,15 @@ interface PaymentMethodSetupSession {
564
564
  redirectUrl: string;
565
565
  /** The customer the payment method is set up for, created if none was given. */
566
566
  customerRef: string;
567
+ /**
568
+ * The last moment a confirmation of this session can still arrive: the end
569
+ * of its form, after which nobody can complete it, plus the time the
570
+ * gateway goes on retrying a confirmation it could not deliver. `null` for
571
+ * a gateway that states neither. A sign-up's promo code slot is held until
572
+ * then, so a form paid shortly before its end still finds its slot when the
573
+ * confirmation arrives late, and an abandoned form gives it back.
574
+ */
575
+ confirmableUntil: Date | null;
567
576
  /**
568
577
  * A confirmation the gateway already holds when the session starts, to be
569
578
  * handled like any callback. Only a gateway without a form of its own has
@@ -634,12 +643,19 @@ interface PaymentGateway {
634
643
  /**
635
644
  * Opens the gateway's form for a payment method. Nothing is confirmed until
636
645
  * the gateway says so through `readCallback`.
646
+ *
647
+ * A failure is thrown as the provider reported it: the platform answers the
648
+ * person with `PAYMENT_GATEWAY_FAILED` and keeps what the error carries —
649
+ * its kind, code, status and request id — in the server log.
637
650
  */
638
651
  startPaymentMethodSetup(input: StartPaymentMethodSetupInput): Promise<PaymentMethodSetupSession>;
639
652
  /**
640
653
  * Verifies a callback with the account's secret and translates it.
641
654
  * Throws `PaymentCallbackRejectedError` for anything the gateway did not
642
- * send, before a single field of it is trusted.
655
+ * send, before a single field of it is trusted. Any other failure is
656
+ * answered with `PAYMENT_GATEWAY_FAILED` and 502, like one of
657
+ * `startPaymentMethodSetup` — to the gateway's webhook, or to the person
658
+ * an `immediateCallback` is read for.
643
659
  */
644
660
  readCallback(callback: PaymentGatewayCallback): Promise<PaymentGatewayEvent>;
645
661
  }
@@ -915,6 +931,11 @@ interface PromoCode {
915
931
  validUntil: string | null;
916
932
  maxRedemptions: number | null;
917
933
  redemptionsCount: number;
934
+ /**
935
+ * Slots held for checkouts that started and have not concluded. A code has
936
+ * a free slot while `redemptionsCount + heldCount` is below `maxRedemptions`.
937
+ */
938
+ heldCount: number;
918
939
  appliesToPlans: PlanId[];
919
940
  appliesToBilling: BillingCycle | null;
920
941
  firstTimeCustomersOnly: boolean;
@@ -1089,7 +1110,7 @@ interface SubscriptionBundleRecord {
1089
1110
  * or on one whose plan has no period; readers fall back to the plan's
1090
1111
  * cycle, which is what every booking used before.
1091
1112
  */
1092
- billingCycle: string | null;
1113
+ billingCycle: BillingCycle | null;
1093
1114
  currentPeriodStart: Date | null;
1094
1115
  currentPeriodEnd: Date | null;
1095
1116
  createdAt: Date;
@@ -1123,7 +1144,7 @@ interface CreateSubscriptionBundleData {
1123
1144
  /** Null unless a commitment was configured or asked for. */
1124
1145
  minimumTermEndsAt?: Date | null;
1125
1146
  /** The rhythm and window worked out above this port. */
1126
- billingCycle?: string | null;
1147
+ billingCycle?: BillingCycle | null;
1127
1148
  currentPeriodStart?: Date | null;
1128
1149
  currentPeriodEnd?: Date | null;
1129
1150
  }
@@ -1729,8 +1750,35 @@ type PromotionResult = {
1729
1750
  original: number;
1730
1751
  months: number;
1731
1752
  };
1732
- /** Applies the promotion math to a base price. */
1753
+ /**
1754
+ * Applies the promotion math to a base price, or `null` where the promotion
1755
+ * takes nothing off it.
1756
+ *
1757
+ * The discounted price stays between 0 and the base price, whatever the
1758
+ * promotion states: a promotion lowers the price of what it is on and nothing
1759
+ * else. Creating one refuses a value no price could make sense of, but whether
1760
+ * an intro price or an amount fits depends on the price it meets — which
1761
+ * differs per plan and rhythm and moves when a new version is published — so
1762
+ * the bound is held here, where every place that resolves a promotion reads it:
1763
+ * the public catalogue, a checkout offer, the operator's preview.
1764
+ */
1733
1765
  declare function applyPromo(promo: PromotionRow | null, basePrice: number | null): PromotionResult | null;
1766
+ /** A promotion on a price, and what it makes of that price. */
1767
+ interface PromotionOnPrice {
1768
+ promotion: PromotionRow;
1769
+ result: PromotionResult;
1770
+ }
1771
+ /**
1772
+ * The promotion a price carries: the one `pickActivePromo` selects for the key,
1773
+ * language and rhythm, where `applyPromo` finds that it lowers the price at
1774
+ * all — or `null`.
1775
+ *
1776
+ * One question, asked the same way by every place that shows or charges a
1777
+ * promotion: the public catalogue, a checkout offer, and the operator's
1778
+ * preview. A promotion that lowers nothing is no promotion there, so it carries
1779
+ * no badge and takes nothing off.
1780
+ */
1781
+ declare function promotionOnPrice(promotions: PromotionRow[], targetKey: string, locale: string, cycle: 'monthly' | 'yearly', basePrice: number | null, today?: Date, targetType?: PromotionTargetType): PromotionOnPrice | null;
1734
1782
 
1735
1783
  type CheckoutOfferLineItemKind = 'plan' | 'bundle' | 'discount';
1736
1784
  /** Frozen billable line item in the offer. */
@@ -2015,12 +2063,32 @@ interface PublicComparisonRow {
2015
2063
  /** Quotas only: display unit. */
2016
2064
  unit?: string;
2017
2065
  }
2066
+ /**
2067
+ * What this installation takes a new payment method with, so a page offering the
2068
+ * plans can say it before anybody reaches the form.
2069
+ *
2070
+ * It is the account `config/saas.yaml#payments.newPaymentMethods` names, with the
2071
+ * gateway bound for it — the same account a sign-up's payment step and a tenant's
2072
+ * own change both go to. Whether an installation runs sign-ups at all is not part
2073
+ * of it: that is the application's own wiring, and the application knows it.
2074
+ *
2075
+ * Which account it is and who keeps the payment method stay inside: a prospect is
2076
+ * told that a card or a direct debit will be asked for, not where it is kept.
2077
+ */
2078
+ interface PublicNewPaymentMethods {
2079
+ /** Whether a new payment method is taken here at all. */
2080
+ taken: boolean;
2081
+ /** The methods the form offers, in the order the installation names them; empty where none is taken. */
2082
+ methods: PaymentMethodType[];
2083
+ }
2018
2084
  /** Response of `GET /public/marketing-catalog`. */
2019
2085
  interface PublicMarketingCatalogResponse {
2020
2086
  locale: string;
2021
2087
  currency: string;
2022
2088
  /** VAT rate in percent — for the CheckoutOffer price breakdown. */
2023
2089
  vatRate: number;
2090
+ /** What a new payment method is taken with here, if one is taken. */
2091
+ newPaymentMethods: PublicNewPaymentMethods;
2024
2092
  /** Visible, marketed plans — sorted by `priority` DESC. */
2025
2093
  plans: PublicMarketingPlan[];
2026
2094
  /**
@@ -2145,6 +2213,16 @@ interface EffectiveLimitsSnapshot {
2145
2213
  plan: string;
2146
2214
  quotas: Record<string, number>;
2147
2215
  features: string[];
2216
+ /**
2217
+ * The add-ons a contract left out of these entitlements because their
2218
+ * cancellation was already declared when it was written. Each is granted by
2219
+ * its booking until its effective date, and by this snapshot never.
2220
+ *
2221
+ * Absent where nothing was left out — and on a snapshot written by an
2222
+ * application, or before the platform left anything out, which then counts
2223
+ * every add-on it names as its own.
2224
+ */
2225
+ leftOutBundleVersionIds?: string[];
2148
2226
  }
2149
2227
 
2150
2228
  interface FeatureUiMeta {
@@ -2390,7 +2468,7 @@ declare const CATALOGUE_KEYS: ReadonlySet<keyof PlanCatalog>;
2390
2468
  */
2391
2469
  declare function planCatalogSettingsOf(catalog: PlanCatalog): PlanCatalogSettings;
2392
2470
  /** Everything in the catalogue that is configuration, as it was resolved. */
2393
- declare function settingsSubtreeOf(catalog: PlanCatalog): AppliedSettingsValues;
2471
+ declare function settingsSubtreeOf(catalog: PlanCatalog | PlanCatalogSettings): AppliedSettingsValues;
2394
2472
  /**
2395
2473
  * `JSON.stringify` with object keys in sorted order at every depth, so that two
2396
2474
  * documents saying the same thing in a different order serialise identically.
@@ -2858,6 +2936,11 @@ interface PromoCodeRecord {
2858
2936
  validUntil: Date | null;
2859
2937
  maxRedemptions: number | null;
2860
2938
  redemptionsCount: number;
2939
+ /**
2940
+ * Slots held for checkouts that started and have not concluded
2941
+ * (`PromoCodeHoldRepository`). An adapter without holds reports 0.
2942
+ */
2943
+ heldCount: number;
2861
2944
  appliesToPlans: string[];
2862
2945
  appliesToBilling: BillingCycle | null;
2863
2946
  firstTimeCustomersOnly: boolean;
@@ -2947,7 +3030,7 @@ interface PromoCodeRedemptionListItem extends PromoCodeRedemptionRecord {
2947
3030
  /**
2948
3031
  * Adapter for PromoCode persistence. Atomic slot reservation lives in the
2949
3032
  * adapter because it is DB-specific (Postgres `UPDATE ... WHERE ... AND
2950
- * (maxRedemptions IS NULL OR redemptionsCount < maxRedemptions)`).
3033
+ * (maxRedemptions IS NULL OR redemptionsCount + heldCount < maxRedemptions)`).
2951
3034
  */
2952
3035
  interface PromoCodeRepository {
2953
3036
  findById(id: string): Promise<PromoCodeRecord | null>;
@@ -2958,12 +3041,17 @@ interface PromoCodeRepository {
2958
3041
  softDelete(id: string): Promise<void>;
2959
3042
  /**
2960
3043
  * Atomic slot reservation: increments `redemptionsCount` and checks
2961
- * `status === 'ACTIVE' && (maxRedemptions IS NULL || redemptionsCount < maxRedemptions)`.
3044
+ * `status === 'ACTIVE' && (maxRedemptions IS NULL || redemptionsCount + heldCount < maxRedemptions)`.
2962
3045
  * Returns true if the slot was reserved, false if EXHAUSTED
2963
- * or the status is not ACTIVE.
3046
+ * or the status is not ACTIVE. A slot held for a checkout is not free, so
3047
+ * an adapter that keeps holds counts `heldCount` here.
2964
3048
  */
2965
3049
  claimSlot(id: string, tx?: TransactionContext): Promise<boolean>;
2966
- /** Sets the status to `EXHAUSTED` when `redemptionsCount >= maxRedemptions`. */
3050
+ /**
3051
+ * Sets the status to `EXHAUSTED` when `redemptionsCount >= maxRedemptions`.
3052
+ * Holds do not count: a code full only because of held slots stays ACTIVE,
3053
+ * and gets its slots back when the holds end.
3054
+ */
2967
3055
  markExhaustedIfFull(id: string, tx?: TransactionContext): Promise<void>;
2968
3056
  /** Decrements `redemptionsCount` by 1 (min 0); EXHAUSTED → ACTIVE. */
2969
3057
  releaseSlot(id: string, tx?: TransactionContext): Promise<void>;
@@ -2973,6 +3061,98 @@ interface PromoCodeRepository {
2973
3061
  */
2974
3062
  expireDueCodes(now: Date): Promise<number>;
2975
3063
  }
3064
+ /**
3065
+ * A slot of a code kept for a checkout offer, from the start of its checkout
3066
+ * until the checkout concludes, the offer's code changes, or `expiresAt`
3067
+ * passes, whichever comes first. For a sign-up, `expiresAt` is the last moment
3068
+ * a confirmation of its payment form can arrive
3069
+ * (`PaymentMethodSetupSession.confirmableUntil`), not the checkout's lifetime.
3070
+ */
3071
+ interface PromoCodeHoldRecord {
3072
+ id: string;
3073
+ promoCodeId: string;
3074
+ checkoutOfferId: string;
3075
+ expiresAt: Date;
3076
+ createdAt: Date;
3077
+ }
3078
+ /** What `PromoCodeHoldRepository.take` did. */
3079
+ type PromoCodeHoldTaken = {
3080
+ outcome: 'taken';
3081
+ hold: PromoCodeHoldRecord;
3082
+ }
3083
+ /** The code is not ACTIVE, is deleted, or has no free slot. */
3084
+ | {
3085
+ outcome: 'no-slot';
3086
+ }
3087
+ /** The offer holds a slot already, perhaps taken by a concurrent call. */
3088
+ | {
3089
+ outcome: 'offer-holds-one';
3090
+ };
3091
+ /**
3092
+ * Adapter for the slots a code keeps for checkouts. Every method that ends a
3093
+ * hold deletes its row and gives its slot back in one statement, so a hold is
3094
+ * counted in `PromoCodeRecord.heldCount` exactly as long as its row exists.
3095
+ *
3096
+ * Optional in the promo module: an adapter that has no holds leaves
3097
+ * `heldCount` at 0, and taking a hold then refuses to start rather than
3098
+ * quietly holding nothing.
3099
+ */
3100
+ interface PromoCodeHoldRepository {
3101
+ /** The offer's hold, live or past its expiry and not yet given back. */
3102
+ findByCheckoutOffer(checkoutOfferId: string, tx?: TransactionContext): Promise<PromoCodeHoldRecord | null>;
3103
+ /**
3104
+ * Takes a slot of an ACTIVE, undeleted code for the offer, atomically with
3105
+ * `claimSlot`'s rule: `maxRedemptions IS NULL OR redemptionsCount +
3106
+ * heldCount < maxRedemptions`. An offer holds one slot at most. Runs on a
3107
+ * transaction of its own: a checkout starts outside any other, and the
3108
+ * slot is committed before the gateway's form opens.
3109
+ */
3110
+ take(hold: {
3111
+ promoCodeId: string;
3112
+ checkoutOfferId: string;
3113
+ expiresAt: Date;
3114
+ }): Promise<PromoCodeHoldTaken>;
3115
+ /**
3116
+ * Moves the expiry of the offer's hold on that code to `expiresAt`, and
3117
+ * never earlier than it stands: the later of the two is written in the one
3118
+ * statement, so a start of the same checkout that asks for less cannot
3119
+ * shorten the slot a form opened by another start relies on, however the
3120
+ * two interleave. False when the offer holds no slot of it any more — it
3121
+ * ended in the meantime.
3122
+ */
3123
+ extend(checkoutOfferId: string, promoCodeId: string, expiresAt: Date): Promise<boolean>;
3124
+ /** Ends the offer's hold and gives its slot back. False when it had none. */
3125
+ release(checkoutOfferId: string, tx?: TransactionContext): Promise<boolean>;
3126
+ /**
3127
+ * Ends the offer's hold and gives its slot back only while it still expires
3128
+ * at `expiresAt` — the hold as the caller wrote it. A hold another start
3129
+ * moved since stays, and so does its slot, in the same statement. False when
3130
+ * nothing was given back.
3131
+ */
3132
+ releaseIfUnmoved(checkoutOfferId: string, expiresAt: Date): Promise<boolean>;
3133
+ /**
3134
+ * Marks the offer's hold, if it is live at `now`, as the slot of the
3135
+ * redemption that runs on `tx`. The mark never outlives the transaction: the
3136
+ * redemption turns the hold into its slot (`convertHandedOver`), or the
3137
+ * caller releases it before committing. False when the offer has no live
3138
+ * hold.
3139
+ */
3140
+ handOver(checkoutOfferId: string, now: Date, tx: TransactionContext): Promise<boolean>;
3141
+ /**
3142
+ * Turns the hold of that code handed over on `tx` into a redemption's slot:
3143
+ * the row goes, `heldCount` drops by one and `redemptionsCount` rises by one,
3144
+ * whatever the code's status. False when nothing was handed over on `tx`.
3145
+ */
3146
+ convertHandedOver(promoCodeId: string, tx: TransactionContext): Promise<boolean>;
3147
+ /**
3148
+ * Ends every hold past its expiry at `now` — of one code when `promoCodeId`
3149
+ * is given — and gives the slots back. A hold handed over on `tx` is left
3150
+ * to the conclusion running there; one handed over on another running
3151
+ * transaction is waited for, and is gone once that transaction ends.
3152
+ * Returns how many ended.
3153
+ */
3154
+ expireDue(now: Date, promoCodeId?: string, tx?: TransactionContext): Promise<number>;
3155
+ }
2976
3156
  /** Adapter for PromoCodeRedemption persistence. */
2977
3157
  interface PromoCodeRedemptionRepository {
2978
3158
  findBySubscription(subscriptionId: string, tx?: TransactionContext): Promise<PromoCodeRedemptionRecord | null>;
@@ -3054,7 +3234,14 @@ interface ContractLineItemRecord {
3054
3234
  descriptionSnapshot: string | null;
3055
3235
  quantity: number;
3056
3236
  unit: string | null;
3237
+ /**
3238
+ * What the line costs over one of its billing periods, `quantity` already
3239
+ * in it — not a unit price. A contract's totals take its lines as they
3240
+ * stand, each counted as often as it falls due in one period of the
3241
+ * contract, and are refused where they do not add up.
3242
+ */
3057
3243
  priceNet: number;
3244
+ /** `priceNet` with the line's share of the tax its rhythm owes. */
3058
3245
  priceGross: number;
3059
3246
  billingCycle: 'monthly' | 'yearly';
3060
3247
  /**
@@ -3341,6 +3528,128 @@ interface SubscriberCorrectionResult {
3341
3528
  correction: SubscriberCorrectionRecord | null;
3342
3529
  }
3343
3530
 
3531
+ /**
3532
+ * What made the charge arise. activation: the first period of a subscription. renewal: a later period. planChange: what an immediate plan change adds. bundleBooking: the first, short period of an add-on. credit: a decision that reduces what is owed. correction: a counter-entry reversing an earlier charge, which is how the append-only journal answers a mistake.
3533
+ */
3534
+ type SubscriberChargeOrigin = 'activation' | 'renewal' | 'planChange' | 'bundleBooking' | 'credit' | 'correction';
3535
+ /**
3536
+ * Which kind of contract line the charge realises.
3537
+ */
3538
+ type SubscriberChargeSource = 'plan' | 'bundle' | 'discount';
3539
+ /**
3540
+ * One charge in a subscriber's account: an amount that became due for a period, derived from a line of the contract in force. The journal is append-only — a charge is never updated, and a mistake is answered with a counter-entry rather than an edit, so the account says what happened rather than what somebody thinks today. A charge is net: the tax is decided by the tax adapter when the charge is invoiced, from the subscriber's origin on that day, and computed once per rate on the invoice.
3541
+ */
3542
+ interface SubscriberCharge {
3543
+ /**
3544
+ * The charge's own identifier. Never shown to a customer as an invoice number: invoice numbering is sequential, gapless and legally constrained per country, and an identifier somebody has already seen on a screen cannot become one later without confusion.
3545
+ */
3546
+ id: string;
3547
+ /**
3548
+ * The party the contract is concluded with, whose account this is. It outlives the tenant.
3549
+ */
3550
+ subscriberId: string;
3551
+ /**
3552
+ * The tenant the subscription belonged to when the charge arose.
3553
+ */
3554
+ tenantId: string;
3555
+ /**
3556
+ * The subscription the charge arose on. Part of the natural key.
3557
+ */
3558
+ subscriptionId: string;
3559
+ /**
3560
+ * The contract whose line the charge realises.
3561
+ */
3562
+ contractId: string;
3563
+ /**
3564
+ * The contract line the charge came from, so that every invoice line can be traced back to what was agreed.
3565
+ */
3566
+ contractLineItemId: string;
3567
+ origin: SubscriberChargeOrigin;
3568
+ source: SubscriberChargeSource;
3569
+ /**
3570
+ * Which thing of its source the charge is for, stable across contracts: the subscription id for the plan, the booking id for an add-on, the discount's key for a discount. Part of the natural key (subscriptionId, source, sourceRef, periodStart, origin), which is unique — a charge derived twice is written once.
3571
+ */
3572
+ sourceRef: string;
3573
+ /**
3574
+ * The start of the period the charge belongs to — the grouping key for an invoice.
3575
+ */
3576
+ periodStart: string;
3577
+ periodEnd: string;
3578
+ /**
3579
+ * ISO 4217, as the contract line records it — recorded per charge so that a charge written in 2026 still means what it meant after the configured currency changes.
3580
+ */
3581
+ currency: string;
3582
+ /**
3583
+ * Net, rounded to the currency's decimal places once, when the charge is written; the written figure is the truth from then on. Negative for a discount.
3584
+ */
3585
+ amountNet: number;
3586
+ /**
3587
+ * When the amount became due. The account is ordered by this, not by when the row was written.
3588
+ */
3589
+ bookedAt: string;
3590
+ createdAt: string;
3591
+ }
3592
+
3593
+ /** A charge as a store reads it back: the wire format, with its dates as dates. */
3594
+ interface SubscriberChargeRecord {
3595
+ id: string;
3596
+ subscriberId: string;
3597
+ tenantId: string;
3598
+ subscriptionId: string;
3599
+ contractId: string;
3600
+ contractLineItemId: string;
3601
+ origin: SubscriberChargeOrigin;
3602
+ source: SubscriberChargeSource;
3603
+ /** The subscription id for the plan, the booking id for an add-on, the discount's key. */
3604
+ sourceRef: string;
3605
+ periodStart: Date;
3606
+ periodEnd: Date;
3607
+ currency: string;
3608
+ /** Net, rounded to the cent when written. Negative for a discount. */
3609
+ amountNet: number;
3610
+ /** When the amount became due. */
3611
+ bookedAt: Date;
3612
+ createdAt: Date;
3613
+ }
3614
+ /** A charge to write: everything but what the store assigns. */
3615
+ type NewSubscriberCharge = Omit<SubscriberChargeRecord, 'id' | 'createdAt'>;
3616
+ /**
3617
+ * The manifest capability that announces the operator's view of an account.
3618
+ * The platform sets it where it serves the view, and the admin UI shows the
3619
+ * view only where it is set.
3620
+ */
3621
+ declare const SUBSCRIBER_ACCOUNT_CAPABILITY = "charges.read";
3622
+ /** Whose account it is, as the operator is shown it. */
3623
+ interface AdminAccountHolder {
3624
+ id: string;
3625
+ /** What the customer quotes, and what an invoice will carry. */
3626
+ customerNumber: string;
3627
+ legalName: string;
3628
+ }
3629
+ /** One charge of an account, with the name its contract line gives it. */
3630
+ interface AdminAccountEntry {
3631
+ /** The charge as the journal holds it. */
3632
+ charge: SubscriberCharge;
3633
+ /**
3634
+ * The contract line's own title, as it was when the contract was
3635
+ * concluded, or `null` where that line cannot be read.
3636
+ */
3637
+ title: string | null;
3638
+ }
3639
+ /**
3640
+ * A tenant's account as the operator reads it: the charges of the subscription
3641
+ * it holds, newest first — by when each became due, then by its period, then
3642
+ * the plan before its add-ons before its discounts.
3643
+ *
3644
+ * No total: without invoices and payments, a sum would be what was charged so
3645
+ * far, and it would be read as what is owed.
3646
+ */
3647
+ interface AdminSubscriberAccount {
3648
+ /** `null` for a tenant that has no subscriber. */
3649
+ holder: AdminAccountHolder | null;
3650
+ entries: AdminAccountEntry[];
3651
+ }
3652
+
3344
3653
  /**
3345
3654
  * Snapshot form of a `Subscription` row for the EntitlementService
3346
3655
  * computation. The consumer maps its Prisma structure onto this form.
@@ -3588,6 +3897,27 @@ interface SubscriberRepository {
3588
3897
  /** Every correction of this subscriber, the latest first. */
3589
3898
  listCorrections(subscriberId: string): Promise<SubscriberCorrectionRecord[]>;
3590
3899
  }
3900
+ /**
3901
+ * The subscriber's account: the charges that became due, one per contract line
3902
+ * and period. Append-only — nothing here updates or deletes a charge, and a
3903
+ * mistake is answered with a counter-entry (`SC-PRIC-020`).
3904
+ *
3905
+ * Owned by the subscriber rather than the tenant, so that it outlives the
3906
+ * tenant it arose for (ADR 0012).
3907
+ */
3908
+ interface SubscriberLedgerRepository {
3909
+ /**
3910
+ * Writes the charges that are not there yet and returns them.
3911
+ *
3912
+ * A charge whose natural key — subscription, source, source reference,
3913
+ * period start and origin — is already written is left as it is and not
3914
+ * returned, however often it is derived and whoever derives it at the same
3915
+ * time: the unique index decides, not a read before the write.
3916
+ */
3917
+ recordCharges(charges: readonly NewSubscriberCharge[], tx?: TransactionContext): Promise<SubscriberChargeRecord[]>;
3918
+ /** Every charge of one subscription, oldest period first. */
3919
+ listBySubscription(subscriptionId: string, tx?: TransactionContext): Promise<SubscriberChargeRecord[]>;
3920
+ }
3591
3921
  /**
3592
3922
  * Display form of a subscription for the tenant self-service UI.
3593
3923
  * Richer than `SubscriptionRecord` (which is only the aggregation form); contains
@@ -3832,6 +4162,14 @@ interface CancelSubscriptionResult {
3832
4162
  alreadyCanceled: boolean;
3833
4163
  }
3834
4164
  interface TenantSubscriptionWritePort {
4165
+ /**
4166
+ * Whether the writes that change a plan — the immediate change and the
4167
+ * onboarding selection — bind the subscription's `planVersionId` to the
4168
+ * version they sell. A contract freeze records the bound version, so it
4169
+ * refuses to start beside a write that says `false`. Left out, it is taken
4170
+ * on trust: the platform cannot see into a write it did not ship.
4171
+ */
4172
+ readonly bindsPlanVersion?: boolean;
3835
4173
  /** Immediate change: set plan + cycle, clear pending fields, optionally reset the period. */
3836
4174
  changePlanImmediate(tenantId: string, input: ImmediatePlanChangeInput): Promise<{
3837
4175
  plan: string;
@@ -4110,13 +4448,14 @@ interface AdminResourcesPort {
4110
4448
  }
4111
4449
  /**
4112
4450
  * Read adapter for the current AdminManifest. The consumer implementation
4113
- * delegates to its `AdminManifestService.getManifest()`. The platform CLI
4114
- * uses this for `<app> manifest dump|hash|check` etc.
4451
+ * delegates to its `AdminManifestService.getManifest()`, which reads the plan
4452
+ * catalogue on every call and therefore answers asynchronously. The platform
4453
+ * CLI uses this for `<app> manifest dump|hash|check` etc.
4115
4454
  */
4116
4455
  interface ManifestAccessPort {
4117
- getManifest(): AdminManifest;
4456
+ getManifest(): Promise<AdminManifest>;
4118
4457
  /** Optional: forces a rebuild from the contributions (e.g. after code reload). */
4119
- rebuild?(): AdminManifest;
4458
+ rebuild?(): Promise<AdminManifest>;
4120
4459
  }
4121
4460
  /**
4122
4461
  * Adapter for the RLS bypass context. Platform code calls `runWithBypass`,
@@ -4606,6 +4945,26 @@ interface SubscriberPaymentMethodSetupMatch {
4606
4945
  sessionRef: string;
4607
4946
  subscriberId: string;
4608
4947
  }
4948
+ /**
4949
+ * Which payment method a read by reference asks about.
4950
+ *
4951
+ * All three together, because `(gatewayAccount, paymentMethodRef)` is unique
4952
+ * account-wide rather than per subscriber: without the subscriber the question
4953
+ * has no answer that is this caller's.
4954
+ *
4955
+ * One argument rather than three strings in a row, for the reason
4956
+ * `SubscriberPaymentMethodSetupMatch` is one — at a call site three strings of
4957
+ * the same type can be swapped with nothing saying so — and for a second that
4958
+ * is specific to a port. `TransactionContext` is `unknown`, so it accepts a
4959
+ * string: against a positional signature, an implementation whose parameters
4960
+ * are offset by one typechecks and then reads the account out of the
4961
+ * subscriber's place. Against an object it does not.
4962
+ */
4963
+ interface SubscriberPaymentMethodReference {
4964
+ subscriberId: string;
4965
+ gatewayAccount: string;
4966
+ paymentMethodRef: string;
4967
+ }
4609
4968
  interface RecordSubscriberPaymentMethodResult {
4610
4969
  method: SubscriberPaymentMethodRecord;
4611
4970
  outcome: RecordSubscriberPaymentMethodOutcome;
@@ -4666,24 +5025,66 @@ interface PaymentEventLog {
4666
5025
  *
4667
5026
  * A subscriber has at most one `ACTIVE` payment method; the database holds
4668
5027
  * that, so two confirmations recorded at once for one subscriber end with one.
5028
+ *
5029
+ * **Within an account, a reference belongs to exactly one subscriber**, and
5030
+ * keeps belonging to it once a newer payment method has replaced it. Every
5031
+ * method that reaches a payment method therefore names the subscriber it is
5032
+ * about, and an implementation answers about that one only. `accountsInUse` is
5033
+ * the exception and says so at itself: it counts accounts rather than handing
5034
+ * out a row.
5035
+ *
5036
+ * That matters on a gateway callback, which is where these are reached: it
5037
+ * arrives without a session, so an installation that keeps its tenants apart
5038
+ * with a policy lifts that policy for it, and what the question names is then
5039
+ * all that bounds it.
4669
5040
  */
4670
5041
  interface SubscriberPaymentMethodRepository {
4671
5042
  /**
4672
5043
  * Records a confirmed payment method for its subscriber, under a lock on the
4673
5044
  * subscriber so two confirmations take turns. See
4674
5045
  * `RecordSubscriberPaymentMethodOutcome` for the three outcomes.
5046
+ *
5047
+ * A confirmation carrying a reference **another** subscriber holds is a
5048
+ * fourth case and has no outcome: it is refused with
5049
+ * `ForeignPaymentMethodReferenceError`, because the account's reference is
5050
+ * that subscriber's and answering `already-recorded` would hand its payment
5051
+ * method to a caller acting for somebody else.
5052
+ *
5053
+ * Two subscribers can reach that reference at the same time: the lock is on
5054
+ * the subscriber, so confirmations for two of them do not take turns, and a
5055
+ * read sees nothing of a row the other has not committed. Reading is
5056
+ * therefore not enough to decide it. **Claim the reference with the first
5057
+ * write, conflict-free** — `ON CONFLICT DO NOTHING` on its unique key, or
5058
+ * whatever the store spells that as — and refuse when the claim takes no
5059
+ * row. Both shipped adapters do exactly that, and it is what lets the
5060
+ * refusal say the same thing everywhere: the key decides, not an error
5061
+ * whose shape belongs to one driver.
5062
+ *
5063
+ * The order is part of the contract, not an implementation detail. Because
5064
+ * the claim is the first write, a refusal leaves the caller's transaction
5065
+ * as it found it — nothing to undo, and nothing that makes it unusable.
5066
+ * An implementation that writes before it claims cannot promise that.
4675
5067
  */
4676
5068
  recordConfirmed(data: RecordSubscriberPaymentMethodData, tx?: TransactionContext): Promise<RecordSubscriberPaymentMethodResult>;
4677
5069
  /** The subscriber's payment method in use, or `null` when it has none. */
4678
5070
  findActive(subscriberId: string, tx?: TransactionContext): Promise<SubscriberPaymentMethodRecord | null>;
4679
5071
  /**
4680
- * The payment method an account's reference names, whatever its status.
5072
+ * The payment method the reference names, whatever its status — and `null`
5073
+ * when that subscriber holds none under it, which includes the case of
5074
+ * another subscriber holding the reference.
4681
5075
  *
4682
5076
  * The one read that reaches a payment method a newer one replaced, which is
4683
5077
  * how `@saasicat/persistence-testing` verifies that an implementation keeps
4684
5078
  * the history rather than overwriting the row (`SC-PRIC-030`).
5079
+ *
5080
+ * The subscriber is what bounds the read. Without it an implementation
5081
+ * would have only the account's reference to go on, which is unique
5082
+ * account-wide: inside a tenant's context a policy would answer `null` and
5083
+ * on a gateway callback, where that policy is lifted, the same call would
5084
+ * answer with somebody else's row. One question, two answers by where it
5085
+ * was asked, is what naming the subscriber removes.
4685
5086
  */
4686
- findByReference(gatewayAccount: string, paymentMethodRef: string, tx?: TransactionContext): Promise<SubscriberPaymentMethodRecord | null>;
5087
+ findByReference(reference: SubscriberPaymentMethodReference, tx?: TransactionContext): Promise<SubscriberPaymentMethodRecord | null>;
4687
5088
  /**
4688
5089
  * Every account that holds a payment method in use, each once.
4689
5090
  *
@@ -4844,6 +5245,8 @@ interface SaaSiCatPersistenceEntitlement {
4844
5245
  subscriptionContractRepository?: PersistenceProvider<SubscriptionContractRepository>;
4845
5246
  /** The parties contracts are concluded with; required wherever contracts are written. */
4846
5247
  subscriberRepository?: PersistenceProvider<SubscriberRepository>;
5248
+ /** The charges a subscriber's contracts give rise to (`tenantBilling.chargeJournal`). */
5249
+ subscriberLedgerRepository?: PersistenceProvider<SubscriberLedgerRepository>;
4847
5250
  subscriptionBundleRepository?: PersistenceProvider<SubscriptionBundleRepository>;
4848
5251
  bundleRepository?: PersistenceProvider<BundleRepository>;
4849
5252
  }
@@ -4895,6 +5298,8 @@ interface SaaSiCatPersistencePromo {
4895
5298
  validationLogRepository: PersistenceProvider<PromoCodeValidationLogRepository>;
4896
5299
  subscriptionLookup: PersistenceProvider<PromoSubscriptionLookup>;
4897
5300
  revenueAggregator: PersistenceProvider<PromoRevenueDeductionAggregator>;
5301
+ /** The slots a code keeps for checkouts; left out, no checkout holds one. */
5302
+ holdRepository?: PersistenceProvider<PromoCodeHoldRepository>;
4898
5303
  }
4899
5304
  /**
4900
5305
  * Aggregate persistence bundle. Produced by adapter factories such as
@@ -5006,6 +5411,12 @@ declare const CATALOG_ERROR_CODES: {
5006
5411
  readonly FEATURE_NOT_FOUND: "FEATURE_NOT_FOUND";
5007
5412
  readonly QUOTA_NOT_FOUND: "QUOTA_NOT_FOUND";
5008
5413
  readonly PROMOTION_NOT_FOUND: "PROMOTION_NOT_FOUND";
5414
+ /**
5415
+ * A promotion's value is not one its type takes: a percentage above 0 and
5416
+ * at most 100, an amount above 0, an intro price of at least 0 for a whole
5417
+ * number of months, or a whole number of free months.
5418
+ */
5419
+ readonly PROMOTION_VALUE_INVALID: "PROMOTION_VALUE_INVALID";
5009
5420
  readonly MARKETING_PROJECTION_NOT_FOUND: "MARKETING_PROJECTION_NOT_FOUND";
5010
5421
  readonly PLAN_ALREADY_EXISTS: "PLAN_ALREADY_EXISTS";
5011
5422
  readonly BUNDLE_ALREADY_EXISTS: "BUNDLE_ALREADY_EXISTS";
@@ -5152,6 +5563,13 @@ declare const CONTRACT_ERROR_CODES: {
5152
5563
  readonly SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH";
5153
5564
  readonly SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT: "SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT";
5154
5565
  readonly SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH";
5566
+ /**
5567
+ * The lines do not add up to a total the contract states, counted as often
5568
+ * as each falls due in one period. `field` names the total.
5569
+ */
5570
+ readonly SUBSCRIPTION_CONTRACT_LINES_DO_NOT_ADD_UP: "SUBSCRIPTION_CONTRACT_LINES_DO_NOT_ADD_UP";
5571
+ /** Something that takes money off states a negative amount. */
5572
+ readonly SUBSCRIPTION_CONTRACT_DISCOUNT_NEGATIVE: "SUBSCRIPTION_CONTRACT_DISCOUNT_NEGATIVE";
5155
5573
  readonly SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START: "SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START";
5156
5574
  readonly CHECKOUT_OFFER_NOT_FOUND: "CHECKOUT_OFFER_NOT_FOUND";
5157
5575
  readonly CHECKOUT_OFFER_EXPIRED: "CHECKOUT_OFFER_EXPIRED";
@@ -5274,6 +5692,13 @@ declare const PAYMENT_ERROR_CODES: {
5274
5692
  * does not name. Carries `field`.
5275
5693
  */
5276
5694
  readonly PAYMENT_RETURN_URL_NOT_ALLOWED: "PAYMENT_RETURN_URL_NOT_ALLOWED";
5695
+ /**
5696
+ * The gateway failed — unreachable, refusing the account's keys, or
5697
+ * answering with an error — while opening its form or reading a callback
5698
+ * back. Answered with 502; what the gateway answered stays in the server
5699
+ * log.
5700
+ */
5701
+ readonly PAYMENT_GATEWAY_FAILED: "PAYMENT_GATEWAY_FAILED";
5277
5702
  };
5278
5703
  type PaymentErrorCode = (typeof PAYMENT_ERROR_CODES)[keyof typeof PAYMENT_ERROR_CODES];
5279
5704
  /** Codes of the settings record (`GET /admin/settings`, the acknowledgement). */
@@ -5306,6 +5731,13 @@ declare const PLATFORM_ERROR_CODES: {
5306
5731
  * does not name. Carries `field`.
5307
5732
  */
5308
5733
  readonly PAYMENT_RETURN_URL_NOT_ALLOWED: "PAYMENT_RETURN_URL_NOT_ALLOWED";
5734
+ /**
5735
+ * The gateway failed — unreachable, refusing the account's keys, or
5736
+ * answering with an error — while opening its form or reading a callback
5737
+ * back. Answered with 502; what the gateway answered stays in the server
5738
+ * log.
5739
+ */
5740
+ readonly PAYMENT_GATEWAY_FAILED: "PAYMENT_GATEWAY_FAILED";
5309
5741
  readonly PENDING_REGISTRATION_NOT_FOUND: "PENDING_REGISTRATION_NOT_FOUND";
5310
5742
  readonly PENDING_REGISTRATION_EXPIRED: "PENDING_REGISTRATION_EXPIRED";
5311
5743
  readonly INVALID_REGISTRATION_STATE: "INVALID_REGISTRATION_STATE";
@@ -5359,6 +5791,13 @@ declare const PLATFORM_ERROR_CODES: {
5359
5791
  readonly SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH";
5360
5792
  readonly SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT: "SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT";
5361
5793
  readonly SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH";
5794
+ /**
5795
+ * The lines do not add up to a total the contract states, counted as often
5796
+ * as each falls due in one period. `field` names the total.
5797
+ */
5798
+ readonly SUBSCRIPTION_CONTRACT_LINES_DO_NOT_ADD_UP: "SUBSCRIPTION_CONTRACT_LINES_DO_NOT_ADD_UP";
5799
+ /** Something that takes money off states a negative amount. */
5800
+ readonly SUBSCRIPTION_CONTRACT_DISCOUNT_NEGATIVE: "SUBSCRIPTION_CONTRACT_DISCOUNT_NEGATIVE";
5362
5801
  readonly SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START: "SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START";
5363
5802
  readonly CHECKOUT_OFFER_NOT_FOUND: "CHECKOUT_OFFER_NOT_FOUND";
5364
5803
  readonly CHECKOUT_OFFER_EXPIRED: "CHECKOUT_OFFER_EXPIRED";
@@ -5527,6 +5966,12 @@ declare const PLATFORM_ERROR_CODES: {
5527
5966
  readonly FEATURE_NOT_FOUND: "FEATURE_NOT_FOUND";
5528
5967
  readonly QUOTA_NOT_FOUND: "QUOTA_NOT_FOUND";
5529
5968
  readonly PROMOTION_NOT_FOUND: "PROMOTION_NOT_FOUND";
5969
+ /**
5970
+ * A promotion's value is not one its type takes: a percentage above 0 and
5971
+ * at most 100, an amount above 0, an intro price of at least 0 for a whole
5972
+ * number of months, or a whole number of free months.
5973
+ */
5974
+ readonly PROMOTION_VALUE_INVALID: "PROMOTION_VALUE_INVALID";
5530
5975
  readonly MARKETING_PROJECTION_NOT_FOUND: "MARKETING_PROJECTION_NOT_FOUND";
5531
5976
  readonly PLAN_ALREADY_EXISTS: "PLAN_ALREADY_EXISTS";
5532
5977
  readonly BUNDLE_ALREADY_EXISTS: "BUNDLE_ALREADY_EXISTS";
@@ -6310,6 +6755,16 @@ interface StartCheckoutInput {
6310
6755
  successUrl: string;
6311
6756
  /** Where the gateway's form sends the person who leaves it. */
6312
6757
  cancelUrl: string;
6758
+ /**
6759
+ * The checkout offer the sign-up concludes on activation. When it carries a
6760
+ * promo code, a slot of that code is held for it from this step until a
6761
+ * confirmation of the gateway's form can no longer arrive
6762
+ * (`PaymentMethodSetupSession.confirmableUntil`), so the code cannot run
6763
+ * out between this step and the payment confirmation; a code that cannot
6764
+ * be held refuses the step before the gateway's form opens. Left out,
6765
+ * nothing is held.
6766
+ */
6767
+ checkoutOfferId?: string | null;
6313
6768
  }
6314
6769
  interface StartCheckoutResult {
6315
6770
  pendingRegistrationId: string;
@@ -6500,6 +6955,47 @@ type IssuerIdentityChange =
6500
6955
  */
6501
6956
  declare function classifyIssuerChange(recorded: LegalIdentity | null, issuer: PlanCatalogIssuer | undefined): IssuerIdentityChange;
6502
6957
 
6958
+ /**
6959
+ * A `subscriber_ledger_entries` row as either adapter reads it back. The amount
6960
+ * is `unknown` because a Prisma row carries a `Decimal` where a Drizzle row
6961
+ * carries a numeric string.
6962
+ */
6963
+ interface CanonicalSubscriberChargeRow {
6964
+ id: string;
6965
+ subscriberId: string;
6966
+ tenantId: string;
6967
+ subscriptionId: string;
6968
+ contractId: string;
6969
+ contractLineItemId: string;
6970
+ origin: string;
6971
+ source: string;
6972
+ sourceRef: string;
6973
+ periodStart: Date;
6974
+ periodEnd: Date;
6975
+ currency: string;
6976
+ amountNet: unknown;
6977
+ bookedAt: Date;
6978
+ createdAt: Date;
6979
+ }
6980
+ /**
6981
+ * Reads a row back as a record. The origin and the source are checked rather
6982
+ * than cast: a value written by hand or by a later release would otherwise
6983
+ * reach an invoice as a charge nobody knows how to read.
6984
+ */
6985
+ declare function toSubscriberChargeRecord(row: CanonicalSubscriberChargeRow): SubscriberChargeRecord;
6986
+ /**
6987
+ * The columns a charge is written with. The amount goes as a decimal string of
6988
+ * two places, which both a Prisma `Decimal` and a PostgreSQL `numeric` take
6989
+ * exactly — a JavaScript number on its way to either is where a cent is lost.
6990
+ *
6991
+ * An amount that is not already a whole number of cents is refused rather than
6992
+ * rounded: a charge is rounded once, where it is derived, and a second rounding
6993
+ * here would make the written figure differ from the one that was computed.
6994
+ */
6995
+ declare function subscriberChargeColumns(charge: NewSubscriberCharge): Omit<CanonicalSubscriberChargeRow, 'id' | 'createdAt' | 'amountNet'> & {
6996
+ amountNet: string;
6997
+ };
6998
+
6503
6999
  /** A `subscribers` row as either adapter reads it back. */
6504
7000
  interface CanonicalSubscriberRow {
6505
7001
  id: string;
@@ -6589,6 +7085,75 @@ interface CanonicalSubscriberPaymentMethodRow {
6589
7085
  declare function toSubscriberPaymentMethodRecord(row: CanonicalSubscriberPaymentMethodRow): SubscriberPaymentMethodRecord;
6590
7086
  /** The columns a confirmed payment method is written with, and nothing a caller added beside them. */
6591
7087
  declare function subscriberPaymentMethodColumns(data: RecordSubscriberPaymentMethodData): Omit<CanonicalSubscriberPaymentMethodRow, 'id' | 'status' | 'replacedAt' | 'createdAt'>;
7088
+ /**
7089
+ * A confirmation naming a reference that belongs to another subscriber.
7090
+ *
7091
+ * `(gatewayAccount, paymentMethodRef)` is unique account-wide rather than per
7092
+ * subscriber, and that is what makes the reference one subscriber's for good:
7093
+ * the second row cannot be written. This is the same boundary drawn for the
7094
+ * caller, so that a confirmation is refused rather than answered as the
7095
+ * duplicate of a payment method that is not this subscriber's — on a gateway
7096
+ * callback, which arrives without a session and with the tenant policy lifted,
7097
+ * so nothing else there bounds the question.
7098
+ *
7099
+ * That a provider issues a reference once per payer is a property of that
7100
+ * provider and no promise of this platform's, which is why the condition is
7101
+ * checked rather than assumed.
7102
+ *
7103
+ * It names neither the subscriber that holds the reference nor the tenant
7104
+ * behind it: whoever reads the log of the refused confirmation is on the other
7105
+ * side of the boundary this refusal draws. The account and the reference are
7106
+ * carried as fields so that a caller can say which confirmation was refused
7107
+ * without taking the sentence apart.
7108
+ */
7109
+ declare class ForeignPaymentMethodReferenceError extends Error {
7110
+ readonly gatewayAccount: string;
7111
+ readonly paymentMethodRef: string;
7112
+ readonly code = "FOREIGN_PAYMENT_METHOD_REFERENCE";
7113
+ constructor(gatewayAccount: string, paymentMethodRef: string);
7114
+ }
7115
+ /** Realm-safe type guard, like `isPaymentCallbackRejectedError`. */
7116
+ declare function isForeignPaymentMethodReferenceError(error: unknown): error is ForeignPaymentMethodReferenceError;
7117
+ /**
7118
+ * Refuses a reference of `gatewayAccount` that another subscriber already
7119
+ * holds, where the row could be read.
7120
+ *
7121
+ * A write cannot rely on this alone: a read does not see a row a concurrent
7122
+ * transaction has not committed. What the reference's unique key refuses is
7123
+ * refused with the same error — see `SubscriberPaymentMethodRepository`.
7124
+ */
7125
+ declare function refuseForeignPaymentMethodReference(recorded: Pick<CanonicalSubscriberPaymentMethodRow, 'subscriberId' | 'gatewayAccount' | 'paymentMethodRef'>, subscriberId: string): void;
7126
+
7127
+ /**
7128
+ * A `subscription_bundles` row as either adapter reads it back.
7129
+ *
7130
+ * The three billing columns are optional because a Prisma client generated from
7131
+ * a schema that predates them returns a row without them; an absent column
7132
+ * reads as null, the same as a booking made before they existed.
7133
+ */
7134
+ interface CanonicalSubscriptionBundleRow {
7135
+ id: string;
7136
+ subscriptionId: string;
7137
+ bundleVersionId: string;
7138
+ startedAt: Date;
7139
+ minimumTermEndsAt: Date | null;
7140
+ billingCycle?: string | null;
7141
+ currentPeriodStart?: Date | null;
7142
+ currentPeriodEnd?: Date | null;
7143
+ canceledAt: Date | null;
7144
+ canceledEffectiveAt: Date | null;
7145
+ createdAt: Date;
7146
+ updatedAt: Date;
7147
+ }
7148
+ /**
7149
+ * Reads a row back as a record.
7150
+ *
7151
+ * `billingCycle` is a text column the platform only ever writes as `MONTHLY` or
7152
+ * `YEARLY`, and a price is chosen by asking whether it is `YEARLY` — so any
7153
+ * other value would be billed monthly without a word. It is checked rather than
7154
+ * cast, and a value outside the two stops the read.
7155
+ */
7156
+ declare function toSubscriptionBundleRecord(row: CanonicalSubscriptionBundleRow): SubscriptionBundleRecord;
6592
7157
 
6593
7158
  /** A `subscription_contracts` row as either adapter reads it back. */
6594
7159
  interface CanonicalContractRow {
@@ -6733,4 +7298,4 @@ declare function resolveErrorMessage(body: ResolvableErrorBody, overrides?: Part
6733
7298
 
6734
7299
  declare const ERROR_MESSAGES_DE: Record<PlatformErrorCode, string>;
6735
7300
 
6736
- export { ACTIVE_SUBSCRIPTION_CONTRACT_STATUSES, AUTH_ERROR_CODES, type ActionKey, type ActivationOrchestrator, type ActivePlanVersionWhere, type ActivePlanVersionWhereWithEndsAt, type ActiveVersionWhere, type ActiveVersionWhereWithEndsAt, type ActorTag, type AdminActor, type AdminAuditListFilter, type AdminManifest, type AdminResourcesPort, type AdminSubscriptionListRow, type AdminTenantDetail, type AdminTenantListFilter, type AdminTenantListRow, type AdminTenantStateResult, type AdminUserListFilter, type AdminUserListRow, type AppliedSettingsPort, type AppliedSettingsRecord, type AppliedSettingsValues, type ApplyOnboardingSelectionInput, type ApplyOnboardingSelectionResult, type ApprovedCatalogKeys, type AuditActionDef, type AuditEntry, type AuditPort, type AuditQuery, type AuditQueryPort, type AuditStatsPort, type AuditStatsSnapshot, type AuthErrorCode, BILLING_ERROR_CODES, BUNDLE_PRICE_LOOKUP_LIMIT, type BillingCycle, type BillingErrorCode, type BundleAvailabilityState, type BundleCompatibility, type BundleFeatureShape, type BundleListFilter, type BundlePricingOverride, type BundleRepository, type BundleRow, type BundleVersionFields, type BundleVersionMutationResult, type BundleVersionRow, CATALOGUE_KEYS, CATALOG_ERROR_CODES, CONTRACT_ERROR_CODES, type CancelSubscriptionBundleData, type CancelSubscriptionInput, type CancelSubscriptionResult, type CancellationNoticePeriods, type CanonicalContractLineItemRow, type CanonicalContractRow, type CanonicalPlanRow, type CanonicalPlanVersionRow, type CanonicalRunningContractRow, type CanonicalSubscriberCorrectionRow, type CanonicalSubscriberPaymentMethodRow, type CanonicalSubscriberRow, type CapabilityCatalogEntryRow, type CapabilityCodeStatus, type CapabilityKey, type CapabilityKind, type CatalogEntryFilter, type CatalogEntryI18n, type CatalogEntryI18nFields, type CatalogEntryRepository, type CatalogErrorCode, type ChangeDirection, type CheckoutOfferFilter, type CheckoutOfferLineItem, type CheckoutOfferLineItemKind, type CheckoutOfferPriceBreakdown, type CheckoutOfferPromoCodeSnapshot, type CheckoutOfferPromotionSnapshot, type CheckoutOfferRepository, type CheckoutOfferRow, type CheckoutOfferSelection, type CheckoutOfferSelectionUpdate, type CheckoutOfferStatus, type CleanupResult, type CliUserRow, type ComponentKey, type ConfiguratorCatalog, type ConfiguratorMarketingProvider, type ConfiguratorModel, type ConfiguratorPlanMarketing, type ConfiguratorPlanVersionRow, type ConfiguratorPriceBreakdown, type ConfiguratorSourcesLookup, type ConfirmedPaymentMethod, type ContractErrorCode, type ContractIssuerParty, type ContractLineItemKind, type ContractLineItemRecord, type ContractSubscriberParty, type CreateBundleData, type CreateBundleVersionDraftData, type CreateCheckoutOfferData, type CreateMarketingProjectionData, type CreatePlanData, type CreatePlanVersionDraftData, type CreatePromoCodeData, type CreatePromoCodeRequest, type CreatePromotionData, type CreateSubscriberData, type CreateSubscriptionBundleData, type CreateSubscriptionContractData, type CreateSuperAdminCliInput, type CreateTenantInput, type DiffResult, type DiscoveredCapability, type DiscoveredFeature, type DiscoveredQuota, type DiscoveredQuotaPolicy, type DiscoveryCodeStatus, type DiscoverySnapshot, type DiscoveryStatus, ERROR_MESSAGES_DE, ERROR_MESSAGES_EN, type EffectiveLimitsSnapshot, type EmailPort, type ErrorMessageParams, FEATURE_NOT_LICENSED, type FeatureCatalogEntryRow, type FeatureDef, type FeatureKey, type FeatureNotLicensedBody, type FeatureRequiresIndex, type FeatureTier, type FeatureUiMeta, type FeatureUiRegistry, type FinalActivationResult, type FirstTimeCustomerCheck, type ImmediatePlanChangeInput, type InvoiceLineItemSnapshot, type IssuerCorrectionFault, type IssuerIdentityChange, type KpiCardDef, type KpiDisplayHint, LEGAL_IDENTITY_FIELDS, type LegalIdentity, type LegalIdentityField, MARKETING_PRIORITY_MAX, MARKETING_PRIORITY_MIN, type ManifestAccessPort, type ManifestContribution, type MarketingProjectionFilter, type MarketingProjectionRepository, type MarketingProjectionRow, type MarketingSettingsRepository, type MarketingSettingsRow, type MarketingTargetType, type MarketingTopFeature, type MaskedPaymentMethod, type MfaPort, type NewContractLineItemData, type NewSettingsChange, type NewSubscriberDetails, type NewSubscriptionContractData, OTP_RATE_LIMIT_MAX_SENDS, OTP_RATE_LIMIT_WINDOW_MINUTES, OTP_TTL_MINUTES, OTP_VERIFY_MAX_ATTEMPTS, type OnboardingPromoRedemption, type OnboardingSelectionRequest, type OnboardingSelectionResponse, PASSWORD_RESET_TTL_MINUTES, PAYMENT_ERROR_CODES, PAYMENT_METHOD_TYPES, PENDING_CHECKOUT_TTL_DAYS, PENDING_EMAIL_TTL_HOURS, PENDING_ONBOARDING_TTL_DAYS, PLATFORM_ERROR_CODES, PROMO_ERROR_CODES, type Paginated, type PartyAddress, type PasswordHasher, type PasswordResetCliResult, PaymentCallbackRejectedError, type PaymentErrorCode, type PaymentEventClaim, type PaymentEventLog, type PaymentGateway, type PaymentGatewayCallback, type PaymentGatewayEvent, type PaymentMethodHolder, type PaymentMethodSetupSession, type PaymentMethodSetupSubject, type PaymentMethodType, type PendingRegistration, type PendingRegistrationCreateInput, type PendingRegistrationRepository, type PendingRegistrationSnapshot, type PendingRegistrationUpdateInput, type PersistenceCapabilities, PersistenceCapabilityError, type PersistenceClassRef, type PersistenceInjectionToken, type PersistenceProvider, type PlanCatalog, type PlanCatalogApp, type PlanCatalogImportReport, type PlanCatalogImportSink, type PlanCatalogIssuer, type PlanCatalogIssuerCorrection, type PlanCatalogLookup, type PlanCatalogMarketing, type PlanCatalogNotifications, type PlanCatalogPaymentAccount, type PlanCatalogPayments, type PlanCatalogReadSink, type PlanCatalogReadSnapshot, type PlanCatalogSettings, type PlanCatalogSubscribers, type PlanCatalogTenantBilling, type PlanDef, type PlanId, type PlanListFilter, type PlanRepository, type PlanRow, type PlanVersion, type PlanVersionFields, type PlanVersionMappingFields, type PlanVersionMutationResult, type PlanVersionRecord, type PlanVersionRepository, type PlanVersionRow, type PlatformErrorBody, type PlatformErrorCode, type PlatformRole, type PlatformUserDto, PlatformUserExistsError, type ProjectPageDef, type PromoCode, type PromoCodeDurationType, type PromoCodeFilter, type PromoCodeRecord, type PromoCodeRedemption, type PromoCodeRedemptionListItem, type PromoCodeRedemptionRecord, type PromoCodeRedemptionRepository, type PromoCodeRedemptionStatus, type PromoCodeRepository, type PromoCodeStatsPort, type PromoCodeStatsSnapshot, type PromoCodeStatus, type PromoCodeValidationLog, type PromoCodeValidationLogRepository, type PromoCodeValidationResult, type PromoCodeValueType, type PromoErrorCode, type PromoPreviewInvalidReason, type PromoPreviewRequest, type PromoPreviewResponse, type PromoPreviewValidResponse, type PromoRevenueDeductionAggregator, type PromoSubscriptionLookup, type PromotionBillingCycle, type PromotionI18n, type PromotionI18nFields, type PromotionRepository, type PromotionResult, type PromotionRow, type PromotionStatus, type PromotionTargetType, type PromotionType, type PromotionValue, type PublicBootResponse, type PublicComparisonRow, type PublicMarketingBundle, type PublicMarketingCatalogResponse, type PublicMarketingPlan, type PublicMarketingPromo, type PublicSignupPlan, type PublishBundleVersionData, type PublishBundleVersionMeta, type PublishPlanVersionData, type QuotaCatalogEntryRow, type QuotaEnforcementMode, type QuotaKey, type QuotaProvider, REGISTRATION_ERROR_CODES, REGISTRATION_RESUME_TTL_MINUTES, REGISTRATION_STEP_BY_STATUS, type ReassignTenantAdminCliResult, type RecommendablePlan, type RecordSubscriberPaymentMethodData, type RecordSubscriberPaymentMethodOutcome, type RecordSubscriberPaymentMethodResult, type RedeemPromoInTransactionCallback, type RegistrationActivation, type RegistrationAuditContext, type RegistrationAuditEvent, type RegistrationAuditEventType, type RegistrationAuditLogger, type RegistrationBillingDetails, type RegistrationConfigSelection, type RegistrationConfiguratorLookup, type RegistrationErrorCode, type RegistrationOtpDelivery, type RegistrationPromoPreview, type RegistrationResumeDelivery, type RegistrationResumeTokenSigner, type RegistrationStatus, type RegistrationStep, type RequiredCapabilities, type ResolvableErrorBody, type ResumeRegistrationInput, type ResumeRegistrationResult, type ReviewCatalogEntryData, type RlsBypassPort, type RunningContractIssuer, type RunningContractIssuers, SETTINGS_ERROR_CODES, SETUP_ERROR_CODES, SUBSCRIBER_ERROR_CODES, type SaaSiCatPersistenceAdapter, type SaaSiCatPersistenceAdminResources, type SaaSiCatPersistenceCatalog, type SaaSiCatPersistenceCore, type SaaSiCatPersistenceEntitlement, type SaaSiCatPersistencePayments, type SaaSiCatPersistencePromo, type SaaSiCatPersistenceTenantBilling, type SaveRegistrationConfigInput, type SaveRegistrationConfigResult, type ScheduledPlanChangeInput, type SelectPlanInput, type SelectPlanResult, type SelectableBundleShape, type SelfServiceBlockedPlans, type SetCatalogEntryReviewData, type SettingsChangeFilter, type SettingsChangeRecord, type SettingsDifference, type SettingsErrorCode, type SetupConfirmMfaRequest, type SetupConfirmMfaResponse, type SetupErrorCode, type SetupRequest, type SetupResult, type SetupStatusResponse, type SlugAvailabilityCheck, type StandardPageDef, type StandardPageKey, type StartCheckoutInput, type StartCheckoutResult, type StartPaymentMethodSetupInput, type StartRegistrationInput, type StartRegistrationResult, type StoredBundleStem, type StrictModeWarning, type StrictModeWarningCode, type SubscriberContact, type SubscriberContactChange, type SubscriberCorrectionData, type SubscriberCorrectionRecord, type SubscriberCorrectionResult, type SubscriberDetails, type SubscriberErrorCode, type SubscriberIdentityCorrection, type SubscriberIdentityDelta, type SubscriberIdentityValues, type SubscriberPaymentMethodRecord, type SubscriberPaymentMethodRepository, type SubscriberPaymentMethodSetupData, type SubscriberPaymentMethodSetupMatch, type SubscriberPaymentMethodStatus, type SubscriberRecord, type SubscriberRepository, type Subscription, type SubscriptionBundleRecord, type SubscriptionBundleRepository, type SubscriptionBundleView, type SubscriptionContractFilter, type SubscriptionContractInvoiceSnapshot, type SubscriptionContractParties, type SubscriptionContractPriceSnapshot, type SubscriptionContractRecord, type SubscriptionContractRepository, type SubscriptionContractStatus, type SubscriptionRecord, type SubscriptionRepository, type SubscriptionStatsPort, type SubscriptionStatsSnapshot, type SubscriptionStatus, type SubscriptionUsagePort, type SubscriptionUsageRecord, type SuperAdminProvisioningPort, type SyncDiscoveryResult, type TenantActionDef, type TenantColumnDef, type TenantDto, type TenantListFilter, type TenantPort, type TenantSubscriptionWritePort, type TerminateSubscriptionContractData, type TopPromoCode, type TransactionContext, type TransactionRunner, type UpdateBundleData, type UpdateBundleVersionDraftData, type UpdateCatalogEntryBaseData, type UpdateCatalogEntryI18nData, type UpdateCheckoutOfferData, type UpdateMarketingProjectionData, type UpdateMarketingSettingsData, type UpdatePlanData, type UpdatePlanVersionDraftData, type UpdatePromoCodeData, type UpdatePromoCodeRequest, type UpdatePromotionData, type UpsellOffer, type UpsellOfferResolver, type UpsertCapabilityEntryData, type UpsertFeatureCatalogEntryInput, type UpsertFeatureEntryData, type UpsertPlanInput, type UpsertPlanVersionInput, type UpsertQuotaEntryData, type UpsertResult, type UsageSnapshotPort, type UserAccountLookup, type UserListFilter, type UserManagementPort, type UserPort, type VerifyRegistrationOtpResult, type VersionChange, type VersionChangeDirection, type VersionEditability, type VersionEditableReason, type VersionedEntityBase, applyPromo, assertPersistenceCapabilities, buildActivePlanVersionWhere, buildActiveVersionWhere, buildFeatureRequiresIndex, bundleDraftDefaults, bundleStemDefaults, canonicalJson, classifyBundleVersionDiff, classifyIssuerChange, classifyPlanDiff, collectUnsatisfiedRequires, contractPartiesOf, coverageExcludingSelf, definedFields, diffSettings, formatCustomerNumber, formatErrorMessage, identityCorrectionDelta, isBundleRedundant, isPaymentCallbackRejectedError, isPlatformUserExistsError, isVersionEditable, issuerIdentityOf, keepOneRecommended, missingRequiresFor, movedIdentityFields, pickActivePromo, planCatalogSettingsOf, previousUtcDay, promoStatus, readQuotaRecord, readQuotaValue, recordedIssuerIdentity, resolveBundleAvailability, resolveErrorMessage, sameLegalIdentity, selectChargeableBundles, settingsSubtreeOf, startOfUtcDay, subscriberFromRegistration, subscriberPaymentMethodColumns, toBundleStemRow, toContractLineItemRecord, toPlanRow, toPlanVersionRow, toRunningContractIssuer, toSubscriberCorrectionRecord, toSubscriberPaymentMethodRecord, toSubscriberRecord, toSubscriptionContractRecord };
7301
+ export { ACTIVE_SUBSCRIPTION_CONTRACT_STATUSES, AUTH_ERROR_CODES, type ActionKey, type ActivationOrchestrator, type ActivePlanVersionWhere, type ActivePlanVersionWhereWithEndsAt, type ActiveVersionWhere, type ActiveVersionWhereWithEndsAt, type ActorTag, type AdminAccountEntry, type AdminAccountHolder, type AdminActor, type AdminAuditListFilter, type AdminManifest, type AdminResourcesPort, type AdminSubscriberAccount, type AdminSubscriptionListRow, type AdminTenantDetail, type AdminTenantListFilter, type AdminTenantListRow, type AdminTenantStateResult, type AdminUserListFilter, type AdminUserListRow, type AppliedSettingsPort, type AppliedSettingsRecord, type AppliedSettingsValues, type ApplyOnboardingSelectionInput, type ApplyOnboardingSelectionResult, type ApprovedCatalogKeys, type AuditActionDef, type AuditEntry, type AuditPort, type AuditQuery, type AuditQueryPort, type AuditStatsPort, type AuditStatsSnapshot, type AuthErrorCode, BILLING_ERROR_CODES, BUNDLE_PRICE_LOOKUP_LIMIT, type BillingCycle, type BillingErrorCode, type BundleAvailabilityState, type BundleCompatibility, type BundleFeatureShape, type BundleListFilter, type BundlePricingOverride, type BundleRepository, type BundleRow, type BundleVersionFields, type BundleVersionMutationResult, type BundleVersionRow, CATALOGUE_KEYS, CATALOG_ERROR_CODES, CONTRACT_ERROR_CODES, type CancelSubscriptionBundleData, type CancelSubscriptionInput, type CancelSubscriptionResult, type CancellationNoticePeriods, type CanonicalContractLineItemRow, type CanonicalContractRow, type CanonicalPlanRow, type CanonicalPlanVersionRow, type CanonicalRunningContractRow, type CanonicalSubscriberChargeRow, type CanonicalSubscriberCorrectionRow, type CanonicalSubscriberPaymentMethodRow, type CanonicalSubscriberRow, type CanonicalSubscriptionBundleRow, type CapabilityCatalogEntryRow, type CapabilityCodeStatus, type CapabilityKey, type CapabilityKind, type CatalogEntryFilter, type CatalogEntryI18n, type CatalogEntryI18nFields, type CatalogEntryRepository, type CatalogErrorCode, type ChangeDirection, type CheckoutOfferFilter, type CheckoutOfferLineItem, type CheckoutOfferLineItemKind, type CheckoutOfferPriceBreakdown, type CheckoutOfferPromoCodeSnapshot, type CheckoutOfferPromotionSnapshot, type CheckoutOfferRepository, type CheckoutOfferRow, type CheckoutOfferSelection, type CheckoutOfferSelectionUpdate, type CheckoutOfferStatus, type CleanupResult, type CliUserRow, type ComponentKey, type ConfiguratorCatalog, type ConfiguratorMarketingProvider, type ConfiguratorModel, type ConfiguratorPlanMarketing, type ConfiguratorPlanVersionRow, type ConfiguratorPriceBreakdown, type ConfiguratorSourcesLookup, type ConfirmedPaymentMethod, type ContractErrorCode, type ContractIssuerParty, type ContractLineItemKind, type ContractLineItemRecord, type ContractSubscriberParty, type CreateBundleData, type CreateBundleVersionDraftData, type CreateCheckoutOfferData, type CreateMarketingProjectionData, type CreatePlanData, type CreatePlanVersionDraftData, type CreatePromoCodeData, type CreatePromoCodeRequest, type CreatePromotionData, type CreateSubscriberData, type CreateSubscriptionBundleData, type CreateSubscriptionContractData, type CreateSuperAdminCliInput, type CreateTenantInput, type DiffResult, type DiscoveredCapability, type DiscoveredFeature, type DiscoveredQuota, type DiscoveredQuotaPolicy, type DiscoveryCodeStatus, type DiscoverySnapshot, type DiscoveryStatus, ERROR_MESSAGES_DE, ERROR_MESSAGES_EN, type EffectiveLimitsSnapshot, type EmailPort, type ErrorMessageParams, FEATURE_NOT_LICENSED, type FeatureCatalogEntryRow, type FeatureDef, type FeatureKey, type FeatureNotLicensedBody, type FeatureRequiresIndex, type FeatureTier, type FeatureUiMeta, type FeatureUiRegistry, type FinalActivationResult, type FirstTimeCustomerCheck, ForeignPaymentMethodReferenceError, type ImmediatePlanChangeInput, type InvoiceLineItemSnapshot, type IssuerCorrectionFault, type IssuerIdentityChange, type KpiCardDef, type KpiDisplayHint, LEGAL_IDENTITY_FIELDS, type LegalIdentity, type LegalIdentityField, MARKETING_PRIORITY_MAX, MARKETING_PRIORITY_MIN, type ManifestAccessPort, type ManifestContribution, type MarketingProjectionFilter, type MarketingProjectionRepository, type MarketingProjectionRow, type MarketingSettingsRepository, type MarketingSettingsRow, type MarketingTargetType, type MarketingTopFeature, type MaskedPaymentMethod, type MfaPort, type NewContractLineItemData, type NewSettingsChange, type NewSubscriberCharge, type NewSubscriberDetails, type NewSubscriptionContractData, OTP_RATE_LIMIT_MAX_SENDS, OTP_RATE_LIMIT_WINDOW_MINUTES, OTP_TTL_MINUTES, OTP_VERIFY_MAX_ATTEMPTS, type OnboardingPromoRedemption, type OnboardingSelectionRequest, type OnboardingSelectionResponse, PASSWORD_RESET_TTL_MINUTES, PAYMENT_ERROR_CODES, PAYMENT_METHOD_TYPES, PENDING_CHECKOUT_TTL_DAYS, PENDING_EMAIL_TTL_HOURS, PENDING_ONBOARDING_TTL_DAYS, PLATFORM_ERROR_CODES, PROMO_ERROR_CODES, type Paginated, type PartyAddress, type PasswordHasher, type PasswordResetCliResult, PaymentCallbackRejectedError, type PaymentErrorCode, type PaymentEventClaim, type PaymentEventLog, type PaymentGateway, type PaymentGatewayCallback, type PaymentGatewayEvent, type PaymentMethodHolder, type PaymentMethodSetupSession, type PaymentMethodSetupSubject, type PaymentMethodType, type PendingRegistration, type PendingRegistrationCreateInput, type PendingRegistrationRepository, type PendingRegistrationSnapshot, type PendingRegistrationUpdateInput, type PersistenceCapabilities, PersistenceCapabilityError, type PersistenceClassRef, type PersistenceInjectionToken, type PersistenceProvider, type PlanCatalog, type PlanCatalogApp, type PlanCatalogImportReport, type PlanCatalogImportSink, type PlanCatalogIssuer, type PlanCatalogIssuerCorrection, type PlanCatalogLookup, type PlanCatalogMarketing, type PlanCatalogNotifications, type PlanCatalogPaymentAccount, type PlanCatalogPayments, type PlanCatalogReadSink, type PlanCatalogReadSnapshot, type PlanCatalogSettings, type PlanCatalogSubscribers, type PlanCatalogTenantBilling, type PlanDef, type PlanId, type PlanListFilter, type PlanRepository, type PlanRow, type PlanVersion, type PlanVersionFields, type PlanVersionMappingFields, type PlanVersionMutationResult, type PlanVersionRecord, type PlanVersionRepository, type PlanVersionRow, type PlatformErrorBody, type PlatformErrorCode, type PlatformRole, type PlatformUserDto, PlatformUserExistsError, type ProjectPageDef, type PromoCode, type PromoCodeDurationType, type PromoCodeFilter, type PromoCodeHoldRecord, type PromoCodeHoldRepository, type PromoCodeHoldTaken, type PromoCodeRecord, type PromoCodeRedemption, type PromoCodeRedemptionListItem, type PromoCodeRedemptionRecord, type PromoCodeRedemptionRepository, type PromoCodeRedemptionStatus, type PromoCodeRepository, type PromoCodeStatsPort, type PromoCodeStatsSnapshot, type PromoCodeStatus, type PromoCodeValidationLog, type PromoCodeValidationLogRepository, type PromoCodeValidationResult, type PromoCodeValueType, type PromoErrorCode, type PromoPreviewInvalidReason, type PromoPreviewRequest, type PromoPreviewResponse, type PromoPreviewValidResponse, type PromoRevenueDeductionAggregator, type PromoSubscriptionLookup, type PromotionBillingCycle, type PromotionI18n, type PromotionI18nFields, type PromotionOnPrice, type PromotionRepository, type PromotionResult, type PromotionRow, type PromotionStatus, type PromotionTargetType, type PromotionType, type PromotionValue, type PublicBootResponse, type PublicComparisonRow, type PublicMarketingBundle, type PublicMarketingCatalogResponse, type PublicMarketingPlan, type PublicMarketingPromo, type PublicNewPaymentMethods, type PublicSignupPlan, type PublishBundleVersionData, type PublishBundleVersionMeta, type PublishPlanVersionData, type QuotaCatalogEntryRow, type QuotaEnforcementMode, type QuotaKey, type QuotaProvider, REGISTRATION_ERROR_CODES, REGISTRATION_RESUME_TTL_MINUTES, REGISTRATION_STEP_BY_STATUS, type ReassignTenantAdminCliResult, type RecommendablePlan, type RecordSubscriberPaymentMethodData, type RecordSubscriberPaymentMethodOutcome, type RecordSubscriberPaymentMethodResult, type RedeemPromoInTransactionCallback, type RegistrationActivation, type RegistrationAuditContext, type RegistrationAuditEvent, type RegistrationAuditEventType, type RegistrationAuditLogger, type RegistrationBillingDetails, type RegistrationConfigSelection, type RegistrationConfiguratorLookup, type RegistrationErrorCode, type RegistrationOtpDelivery, type RegistrationPromoPreview, type RegistrationResumeDelivery, type RegistrationResumeTokenSigner, type RegistrationStatus, type RegistrationStep, type RequiredCapabilities, type ResolvableErrorBody, type ResumeRegistrationInput, type ResumeRegistrationResult, type ReviewCatalogEntryData, type RlsBypassPort, type RunningContractIssuer, type RunningContractIssuers, SETTINGS_ERROR_CODES, SETUP_ERROR_CODES, SUBSCRIBER_ACCOUNT_CAPABILITY, SUBSCRIBER_ERROR_CODES, type SaaSiCatPersistenceAdapter, type SaaSiCatPersistenceAdminResources, type SaaSiCatPersistenceCatalog, type SaaSiCatPersistenceCore, type SaaSiCatPersistenceEntitlement, type SaaSiCatPersistencePayments, type SaaSiCatPersistencePromo, type SaaSiCatPersistenceTenantBilling, type SaveRegistrationConfigInput, type SaveRegistrationConfigResult, type ScheduledPlanChangeInput, type SelectPlanInput, type SelectPlanResult, type SelectableBundleShape, type SelfServiceBlockedPlans, type SetCatalogEntryReviewData, type SettingsChangeFilter, type SettingsChangeRecord, type SettingsDifference, type SettingsErrorCode, type SetupConfirmMfaRequest, type SetupConfirmMfaResponse, type SetupErrorCode, type SetupRequest, type SetupResult, type SetupStatusResponse, type SlugAvailabilityCheck, type StandardPageDef, type StandardPageKey, type StartCheckoutInput, type StartCheckoutResult, type StartPaymentMethodSetupInput, type StartRegistrationInput, type StartRegistrationResult, type StoredBundleStem, type StrictModeWarning, type StrictModeWarningCode, type SubscriberCharge, type SubscriberChargeOrigin, type SubscriberChargeRecord, type SubscriberChargeSource, type SubscriberContact, type SubscriberContactChange, type SubscriberCorrectionData, type SubscriberCorrectionRecord, type SubscriberCorrectionResult, type SubscriberDetails, type SubscriberErrorCode, type SubscriberIdentityCorrection, type SubscriberIdentityDelta, type SubscriberIdentityValues, type SubscriberLedgerRepository, type SubscriberPaymentMethodRecord, type SubscriberPaymentMethodReference, type SubscriberPaymentMethodRepository, type SubscriberPaymentMethodSetupData, type SubscriberPaymentMethodSetupMatch, type SubscriberPaymentMethodStatus, type SubscriberRecord, type SubscriberRepository, type Subscription, type SubscriptionBundleRecord, type SubscriptionBundleRepository, type SubscriptionBundleView, type SubscriptionContractFilter, type SubscriptionContractInvoiceSnapshot, type SubscriptionContractParties, type SubscriptionContractPriceSnapshot, type SubscriptionContractRecord, type SubscriptionContractRepository, type SubscriptionContractStatus, type SubscriptionRecord, type SubscriptionRepository, type SubscriptionStatsPort, type SubscriptionStatsSnapshot, type SubscriptionStatus, type SubscriptionUsagePort, type SubscriptionUsageRecord, type SuperAdminProvisioningPort, type SyncDiscoveryResult, type TenantActionDef, type TenantColumnDef, type TenantDto, type TenantListFilter, type TenantPort, type TenantSubscriptionWritePort, type TerminateSubscriptionContractData, type TopPromoCode, type TransactionContext, type TransactionRunner, type UpdateBundleData, type UpdateBundleVersionDraftData, type UpdateCatalogEntryBaseData, type UpdateCatalogEntryI18nData, type UpdateCheckoutOfferData, type UpdateMarketingProjectionData, type UpdateMarketingSettingsData, type UpdatePlanData, type UpdatePlanVersionDraftData, type UpdatePromoCodeData, type UpdatePromoCodeRequest, type UpdatePromotionData, type UpsellOffer, type UpsellOfferResolver, type UpsertCapabilityEntryData, type UpsertFeatureCatalogEntryInput, type UpsertFeatureEntryData, type UpsertPlanInput, type UpsertPlanVersionInput, type UpsertQuotaEntryData, type UpsertResult, type UsageSnapshotPort, type UserAccountLookup, type UserListFilter, type UserManagementPort, type UserPort, type VerifyRegistrationOtpResult, type VersionChange, type VersionChangeDirection, type VersionEditability, type VersionEditableReason, type VersionedEntityBase, applyPromo, assertPersistenceCapabilities, buildActivePlanVersionWhere, buildActiveVersionWhere, buildFeatureRequiresIndex, bundleDraftDefaults, bundleStemDefaults, canonicalJson, classifyBundleVersionDiff, classifyIssuerChange, classifyPlanDiff, collectUnsatisfiedRequires, contractPartiesOf, coverageExcludingSelf, definedFields, diffSettings, formatCustomerNumber, formatErrorMessage, identityCorrectionDelta, isBundleRedundant, isForeignPaymentMethodReferenceError, isPaymentCallbackRejectedError, isPlatformUserExistsError, isVersionEditable, issuerIdentityOf, keepOneRecommended, missingRequiresFor, movedIdentityFields, pickActivePromo, planCatalogSettingsOf, previousUtcDay, promoStatus, promotionOnPrice, readQuotaRecord, readQuotaValue, recordedIssuerIdentity, refuseForeignPaymentMethodReference, resolveBundleAvailability, resolveErrorMessage, sameLegalIdentity, selectChargeableBundles, settingsSubtreeOf, startOfUtcDay, subscriberChargeColumns, subscriberFromRegistration, subscriberPaymentMethodColumns, toBundleStemRow, toContractLineItemRecord, toPlanRow, toPlanVersionRow, toRunningContractIssuer, toSubscriberChargeRecord, toSubscriberCorrectionRecord, toSubscriberPaymentMethodRecord, toSubscriberRecord, toSubscriptionBundleRecord, toSubscriptionContractRecord };